본문으로 건너뛰기

PBR 텍스처 점검 · 브라우저에서 머티리얼 세트 검사

머티리얼의 맵들을 넣으면 텍스처 랩이 역할별로 나누고, 고른 워크플로에 맞는지 점검해 모든 문제를 파일 이름과 근거 수치와 함께 보고합니다.

PBR 머티리얼은 서로 맞아야 하는 여러 장의 텍스처입니다. 크기가 같아야 하고, 맵마다 그 맵을 기대하는 슬롯에 들어가야 하며, 색 맵은 sRGB로, 데이터 맵(노멀·러프니스·메탈릭·AO·하이트)은 리니어로 가져와야 합니다. 패킹한 채널은 엔진이 읽는 순서여야 하고 노멀맵은 엔진의 초록 채널 규약을 따라야 합니다. 머티리얼 하나의 맵을 텍스처 랩에 넣으면 파일 이름으로 역할을 나누고, 고른 워크플로(개별 맵·Unity HDRP 마스크·Unity URP 메탈릭·Godot ORM·Unreal ORM)에 맞는지 점검해 문제마다 근거 수치를 JSON 보고서에 적습니다. 결과 파일은 바이트 단위로 측정했고, Unity·Unreal·Godot 가져오기는 실행하지 않았습니다.

텍스처 맵을 끌어다 놓으세요(PNG는 채널 바이트를 그대로 유지)
브라우저에서 처리하며 파일은 업로드되지 않습니다.
텍스처 랩: CC0 텍스처로 만든 노멀맵과 OpenGL/DirectX 규약 표시
CC0 에셋(ambientCG)을 연 실제 텍스처 랩 화면입니다.
출력
  • Channel PNGs측정 확인· numpy
  • Normal map측정 확인· numpy
  • Packed mask / ORM측정 확인· Pillow
  • Engine import미검증

가져오기 전에 PBR 세트가 맞춰야 할 것

색인가, 데이터인가. 베이스 컬러(알베도)와 에미션은 sRGB로 그린 그림이라 엔진이 조명 계산 전에 디코딩합니다. 러프니스·메탈릭·앰비언트 오클루전·하이트·노멀맵은 숫자이므로 셰이더까지 그대로 가야 하고, 그래서 리니어(비색상) 데이터로 가져옵니다. glTF 2.0은 이를 규정으로 정해, 베이스 컬러 RGB는 반드시 sRGB 전달 함수를, 메탈릭·러프니스 값은 반드시 리니어를 쓰게 합니다. Unity에서는 임포터의 sRGB (Color Texture) 체크가 이 스위치이고, Godot 셰이딩 문서는 색 텍스처에만 source_color 힌트를 주고 노멀·러프니스·메탈릭·하이트에는 주지 않는다고 안내합니다.

패킹. 엔진은 샘플링 횟수를 줄이려고 여러 회색 맵을 RGBA 한 장의 채널에서 읽는데, 순서는 엔진마다 다릅니다. Unity HDRP 마스크 맵은 R 메탈릭·G AO·B 디테일 마스크·A 스무스니스, URP 채널 패킹 텍스처는 R 메탈릭·G 오클루전·A 스무스니스입니다. glTF 2.0은 러프니스를 G, 메탈릭을 B, 오클루전을 R에서 읽으므로 한 장으로 "ORM"을 만들 수 있고, Godot ORMMaterial3D도 같은 R·G·B 순서를 쓰는데 이는 매뉴얼이 아니라 Godot 4.4 셰이더 소스에 적혀 있습니다. Unity는 러프니스 대신 1 − 러프니스인 스무스니스를 저장합니다.

노멀. Unity와 Godot는 OpenGL 방식 노멀맵(초록 = +Y, 위쪽)을 기대합니다. DirectX 방식은 초록 채널만 다르며, 다시 구울 필요 없이 255 − g로 바뀝니다. 맵 한 장의 픽셀만으로는 어느 쪽인지 측정할 수 없어 랩은 변환만 하고 추측하지 않습니다.

캔버스가 아니라 랩으로 재는 이유: 브라우저 캔버스는 픽셀을 미리 곱한(premultiplied) 상태로 보관하므로 알파가 0인 텍셀은 모두 (0, 0, 0, 0)으로 돌아오고 그 아래 패킹된 바이트는 사라집니다. 랩은 PNG를 직접 디코딩하며(인터레이스가 아닌 모든 색 형식, 1~16비트) JPEG·WebP 입력에는 "바이트 동일 아님"을 표시합니다.

sRGB / 리니어
엔진이 0~255 값을 읽는 방식. sRGB는 색으로 디코딩하고(128 → 약 0.216), 리니어는 그대로 씁니다(128 → 0.502).
채널 패킹 텍스처
네 채널에 서로 무관한 회색 맵 네 장을 담은 RGBA 이미지 한 장.
ORM
R 오클루전·G 러프니스·B 메탈릭. glTF 2.0의 채널 순서이며 Godot ORMMaterial3D도 이 순서로 읽습니다.
스무스니스
Unity가 쓰는 러프니스의 반대값. 스무스니스 = 1 − 러프니스(8비트로는 255 − 값).

예시: ambientCG 벽돌 세트를 세 워크플로로 점검

ambientCG 세트 하나의 1024 × 1024 PNG 네 장입니다. 역할은 파일 이름에서 나오고, 문제 목록은 랩의 검사기가 돌려주는 값입니다(러프니스 파일은 세 채널이 같은 RGB로 저장됐다고 가정).

파일                                     역할       가져오기
Bricks076C_1K-PNG_Color.png              albedo     sRGB
Bricks076C_1K-PNG_Roughness.png          roughness  linear
Bricks076C_1K-PNG_AmbientOcclusion.png   ao         linear
Bricks076C_1K-PNG_Displacement.png       height     linear

개별 맵 (glTF·공통)             warn  missing-recommended  normal, metallic
                                 info  gray-stored-as-rgb   Roughness.png (R = G = B)
Unity HDRP 마스크 맵             error missing-required     mask map
                                 warn  missing-recommended  normal
Godot 4 ORM                      warn  missing-recommended  normal, orm

노멀맵만 더하면 개별 맵 워크플로로는 문제가 없습니다(ambientCG는 Unity·Godot용 _NormalGL과 _NormalDX를 함께 주므로 하나만 넣으세요. 둘 다 넣으면 역할 중복 경고가 뜹니다). HDRP에는 메탈릭·AO 슬롯이 따로 없어 마스크 맵이 없으면 오류입니다. 이 세트에는 메탈릭 맵이 없어서 "패킹 가능" 안내도 나오지 않으며, 메탈릭 0은 마스크 패커의 상수 채널로 채워야 합니다.

이렇게 작동합니다

  • 파일 이름으로 역할 판별(albedo·normal·roughness·metallic·AO·height·emission·ORM 등). 모든 역할은 바꿀 수 있는 선택 상자입니다.
  • 점검: 크기 불일치, 누락 맵, 중복 역할, 2의 거듭제곱 아님, 예상 밖 알파, RGB로 저장된 회색 맵, 패킹된 맵.
  • 노멀맵을 측정으로 검증: 단위 길이와 파랑이 음수가 아닌지.
  • 채널·노멀·패킹·수정(가장자리 번짐·밉맵 미리보기·2의 거듭제곱)·일괄 내보내기 단계.

사용 방법

  1. 머티리얼 하나의 맵들을 끌어다 놓습니다.
  2. 역할과 워크플로를 확인합니다.
  3. 문제 목록을 읽고 다른 단계에서 맵을 고치거나 변환합니다.
  4. 보고서나 처리한 텍스처를 내보냅니다.

받게 되는 파일

파일용도
texture-report.json점검 보고서: 텍스처마다 역할·크기·2의 거듭제곱 여부·정확한 PNG 채널 여부·색 형식·비트 깊이·srgbChunkPresent·색 공간 안내·알파와 노멀 측정값, 그리고 문제마다 id·수준·수치.
rock-channels.zip채널 단계 결과: rock-r-ao.png, rock-g-roughness.png 등 채널마다 8비트 회색 PNG 한 장, 원본과 바이트 동일.
rock-mask.png패킹 단계 결과: 고른 엔진 배치로 패킹한 회색 맵.
rock-directx.png / rock-normal.png노멀 단계 결과: 변환한 맵, 또는 하이트에서 만든 노멀맵.
nerulio-textures.zip내보내기 결과: 모든 파일을 (선택) 크기 변경 → (선택) 가장자리 번짐 → 인코딩 순서로 처리.

점검한 세트를 Unity·Godot·glTF에서 쓰기

아래 설정은 각 엔진 문서를 따른 것이며, Nerulio가 이 가져오기를 실행하지는 않았습니다.

  1. Unity: 데이터 텍스처(러프니스·메탈릭·AO·마스크 맵)를 모두 선택하고 인스펙터에서 sRGB (Color Texture)를 끕니다. 베이스 컬러와 에미션은 켠 채로 둡니다. HDRP는 마스크 맵의 Texture Type을 Default로 두라고 추가로 안내합니다.
  2. Unity 노멀맵: Texture Type을 Normal map으로 설정합니다. 파일이 DirectX 방식이면 같은 임포터의 Flip Green Channel(Unity 6)을 켜거나 먼저 파일을 변환합니다.
  3. Unity URP Lit(Workflow Mode Metallic): 패킹한 텍스처를 Metallic Map과 Occlusion Map에 지정하고 Smoothness › Source는 Metallic Alpha로 둡니다. HDRP Lit: 마스크 맵을 Mask Map에 지정하면 Metallic·Smoothness·AO Remapping 슬라이더가 나타납니다.
  4. Godot 4: ORM 텍스처는 ORMMaterial3D에, 개별 맵은 StandardMaterial3D에 씁니다. 다른 배치의 패킹 텍스처도 StandardMaterial3D에서 roughness_texture_channel·metallic_texture_channel·ao_texture_channel을 해당 채널로 지정하면 읽을 수 있습니다.
  5. Godot 가져오기: DirectX 방식 노멀맵은 가져오기 독에서 Process › Normal Map Invert Y를 켜고 Reimport를 누릅니다.
  6. glTF: metallicRoughness 텍스처의 G에 러프니스, B에 메탈릭, R에 오클루전을 넣고(같은 이미지를 오클루전 텍스처로 참조해도 됨) 노멀맵은 +Y 위쪽 규약으로 둡니다.

결과 확인

  • 처리한 파일을 랩에 다시 넣고 같은 워크플로를 고릅니다. 보고서의 오류는 0이어야 하고, 채널 단계에서 각 채널의 최소·최대가 예상과 같아야 합니다(상수 채널은 최소 = 최대).
  • 엔진에서 잘 아는 표면을 봅니다. 연마한 금속은 날카로운 하이라이트, 거친 돌은 넓고 흐린 하이라이트여야 합니다. 전부 번들거리거나 전부 무광이면 대개 러프니스가 반전됐거나 데이터 맵을 sRGB로 가져온 것입니다.
  • 조명을 머티리얼 위쪽에 둡니다. 튀어나온 부분은 위쪽 가장자리가 밝아야 하며, 아래가 밝으면 노멀맵이 반대 규약입니다.

문제 해결

증상유력한 원인확인 방법해결
머티리얼 전체가 너무 번들거리거나 너무 무광데이터 맵을 sRGB로 가져왔거나(128이 약 0.216으로 읽힘), 스무스니스 자리에 러프니스가 들어감러프니스·메탈릭·마스크 맵의 sRGB (Color Texture)가 켜져 있는지 확인하고, 채널을 풀어 원본과 비교데이터 맵은 sRGB를 끄고, Unity용은 러프니스 → 스무스니스로 반전
패킹 후 금속이나 AO가 엉뚱한 곳에 보임다른 엔진의 배치로 패킹함(glTF의 G는 러프니스, HDRP의 G는 AO)채널 단계에서 배치 프리셋을 바꿔 가며 채널 통계를 읽기마스크 패커에서 맞는 프리셋으로 다시 패킹
튀어나온 곳이 들어가 보이거나 빛이 아래에서 오는 듯함노멀맵이 초록 채널 규약이 반대위에서 비출 때 요철의 어느 가장자리가 밝은지 확인노멀맵 변환기로 바꾸거나 Unity의 Flip Green Channel·Godot의 Normal Map Invert Y 사용
패킹 텍스처를 URP의 오클루전에도 지정하자 주변광이 어두워짐URP는 G에서 오클루전을 읽는데 Nerulio의 URP 프리셋은 G에 0을 씀채널 단계에서 G의 최소 = 최대 = 0오클루전에 지정하지 않거나, 직접 배치로 G에 AO를 패킹
잘라 낸 가장자리(잎·데칼)에 어둡거나 밝은 테두리알파 0 아래의 RGB가 필터링과 밉맵으로 가장자리에 섞임보정 › 밉맵 미리보기에서 1/4~1/16 확인텍스처 가장자리 번짐으로 색을 채우기
dimension-mismatch 오류맵 하나를 다른 해상도로 내보냄문제 항목에 파일마다 크기가 나옴모든 맵을 같은 크기로 내보내기. 꼭 줄여야 하면 보정 단계의 2의 거듭제곱 변경이 품질 리샘플러를 씀

다른 방법

방법이럴 때 더 낫습니다
엔진 자체의 텍스처 임포터배치를 이미 아는 맵 한두 장일 때. sRGB·Texture Type·노멀 반전은 어차피 거기서 정하며 파일이 늘지 않습니다.
텍스처링 프로그램의 내보내기 프리셋맵이 페인팅 도구에서 나올 때. 처음부터 엔진 배치로 내보내면 패킹 단계가 필요 없습니다. Godot 문서는 Substance Painter와 ArmorPaint가 Unreal Engine 프리셋으로 ORM을 내보낸다고 적고 있습니다.
PBR 텍스처 검사기변환 단계 없이 점검 목록(이름·크기·누락 맵)과 JSON 보고서만 필요할 때.

출력 파일과 검증 방법

"측정 확인"은 내려받은 파일을 페이지 밖에서(Pillow·numpy·별도 파서) 다시 열어 그 속성을 측정했다는 뜻입니다. 게임 엔진에서 불러오는 것은 시험하지 않았습니다.

대상파일검증
Channel PNGs<name>-r/g/b/a.png (8-bit grey)측정 확인 numpy채널마다 바이트가 같고 완전히 투명한 텍셀 아래의 RGB도 유지됩니다.
Normal mapPNG · OpenGL (+Y) or DirectX (−Y)측정 확인 numpy디코딩한 벡터가 단위 길이(최대 오차 0.0002)이고, OpenGL과 DirectX는 초록 채널만 다릅니다.
Packed mask / ORMUnity HDRP mask · URP metallic · ORM (glTF, Godot)측정 확인 Pillow패킹된 바이트 확인: ORM 프리셋, AO 10 / 러프니스 80 / 메탈릭 220 → (10, 80, 220, 255).
Engine importUnity · Unreal · Godot미검증어떤 엔진에서도 불러오지 않았습니다.

검증 근거

채널 분리가 네 채널 모두 바이트 동일(최대 차이 0), 투명 텍셀 2048개가 RGB 유지. 가장자리 번짐은 알파 0인 텍셀 448개만 바꾸고 알파 바이트는 하나도 건드리지 않음. OpenGL ↔ DirectX는 초록(255 − g)만 다름. 변환한 노멀은 단위 벡터.

한계

  • 머티리얼 미리보기는 조명 하나와 균일한 주변광의 GGX 근사입니다. 조명 판단은 엔진에서 하세요.
  • Unreal ORM 프리셋은 glTF 순서를 따르며, Epic이 Unreal의 순서로 문서화한 것은 아닙니다.
  • 정확한 채널 바이트는 PNG에서만 보장됩니다. JPEG·WebP는 브라우저가 디코딩하며 "바이트 동일 아님"으로 표시합니다.
  • 인터레이스 PNG와 16비트 출력은 지원하지 않습니다. 정확 경로는 3,355만 픽셀까지입니다.
  • 노멀맵의 규약은 픽셀로 알아낼 수 없고 변환만 할 수 있습니다.
  • Unity·Unreal·Godot에서 불러오지 않았습니다. 채널 순서는 각 문서와 엔진 소스에 근거합니다.

버전과 출처

텍스처 랩에서 측정한 값(docs/TEXTURE-LAB.md): 채널 분리가 R·G·B·A 모두 바이트 동일(최대 차이 0), 알파 0 텍셀 2048개 유지. ORM 프리셋에 AO 10 / 러프니스 80 / 메탈릭 220을 넣으면 (10, 80, 220, 255). OpenGL ↔ DirectX는 초록만 다름. 점검 보고서의 alpha.zeroPixels가 시험 파일과 일치. Unity·Unreal·Godot 가져오기는 시도하지 않았으며, 배치는 아래 문서에서, Godot ORM 순서는 4.4 엔진 소스를 직접 읽어 확인했습니다.

참고한 공식 문서

자주 묻는 질문

sRGB와 리니어를 감지하나요?

프로필이나 감마를 해석하지 않습니다. 엔진이 어떤 맵을 색으로, 어떤 맵을 리니어 데이터로 기대하는지 알려 주고, PNG의 sRGB 청크는 사실로만 보고합니다.

점검만 해도 맵이 바뀌나요?

아니요. 점검은 픽셀을 읽기만 하며 내보내기 전에는 아무것도 쓰지 않습니다.

무료인가요? 계정이 필요한가요?

이 페이지의 기능은 모두 무료이며 계정 없이 쓸 수 있습니다. 워터마크나 막혀 있는 내보내기가 없습니다.

스프라이트가 업로드되나요?

아니요. Studio는 이 브라우저 탭 안에서 디코딩·패킹·내보내기를 합니다. 프로젝트는 브라우저(IndexedDB)에 자동 저장되며 .nerulio 파일로 저장할 수 있습니다.

Aseprite나 엔진 플러그인을 설치해야 하나요?

아니요. .aseprite 파일은 브라우저에서 읽고 씁니다. 엔진별 번들에는 그 엔진에 필요한 것이 들어 있습니다(Godot는 가져오기 설정과 씬, Unity와 Godot 타일셋은 작은 편집기 스크립트).