초록 채널만 반전해 OpenGL(+Y)과 DirectX(−Y) 노멀 맵을 서로 변환하세요.
OpenGL 방식 노멀맵(Y+, 초록이 위쪽 — Unity·Godot·glTF가 기대하는 방식)과 DirectX 방식(Y−, 초록이 아래쪽)은 초록 채널만 다릅니다. 한쪽을 다른 쪽으로 바꾸는 것은 모든 텍셀의 g → 255 − g이며 빨강·파랑·알파는 그대로이고, 두 번 하면 원래 바이트로 돌아옵니다. Nerulio 변환기는 브라우저에서 PNG에 정확히 이 계산을 적용하고 단위 길이 점검을 보여 줍니다. 파일이 어느 규약인지는 추측하지 않으며, 그 판별은 측정 근거가 있는 Studio 텍스처 작업 공간의 감지기가 합니다.
이미지을(를) 여기에 놓으세요여러 개를 한 번에 처리할 수 있습니다업로드 없음 · 이 기기에서 처리
초록 채널의 의미와 반전의 효과
탄젠트 공간 노멀맵은 텍셀마다 단위 벡터 하나를 저장합니다. 빨강은 X(이미지 오른쪽), 초록은 Y, 파랑은 Z(표면 바깥)이며 각각 (n + 1) / 2 × 255로 인코딩합니다. 평평한 텍셀은 (128, 128, 255)입니다. 두 규약은 X와 Z에서는 같고, 이미지에서 +Y가 어느 쪽인지만 다릅니다. OpenGL은 위, DirectX는 아래입니다.
반대 규약의 맵을 넣으면 세로 방향 기울기가 모두 뒤집힙니다. 위에서 비추면 요철의 위쪽이 아니라 아래쪽 가장자리가 밝아져 튀어나온 곳이 들어가 보이거나 빛이 아래에서 오는 듯 보입니다. 가로 기울기는 맞기 때문에 텍스처 문제가 아니라 조명 문제처럼 보이기도 합니다.
해결은 다시 굽는 것이 아니라 산수입니다. y → −y는 g → 255 − g이고, 이 연산은 자기 자신이 역연산입니다. Unity 매뉴얼은 Unity가 Y+(OpenGL) 노멀맵을 쓴다고, Godot 매뉴얼은 X+·Y+·Z+("OpenGL 방식")가 필요하다고 적고, glTF 2.0은 +X 오른쪽·+Y 위쪽으로 정합니다. Unreal은 Epic이 간접적으로만 밝히기 때문에 랩에서 DirectX(−Y)에 "추정" 표시를 붙입니다.
이 파일은 어느 규약일까? 둘 다 올바른 노멀맵이라 랩은 추측하지 않습니다. Studio 텍스처 작업 공간은 표면 자체(기울기들이 서로 모순 없는지, 스프라이트라면 실루엣까지)로 추정해 신뢰도와 함께 보여 주며, 확인하기 전에는 판정을 적용하지 않습니다. 이 점검은 OpenGL인가 DirectX인가를 보세요.
평평한 텍셀은 (128, 127, 255)가 되고 다시 변환하면 (128, 128, 255)로 돌아옵니다. 한 단계 차이는 8비트 인코딩의 중심 때문이지 손실이 아닙니다. 투명한 가장자리가 없으면 빨강이 뒤집힌 맵은 감지기에서 DirectX로 읽히며, Studio는 그 사실을 알려 줍니다.
채널마다 바뀌는 것
채널
OpenGL (Y+)
변환기
DirectX (Y−)
R (X)
이미지 오른쪽
그대로
이미지 오른쪽
G (Y)
이미지 위쪽
255 − g
이미지 아래쪽
B (Z)
표면 바깥, 128 이상
그대로
표면 바깥, 128 이상
A
파일에 있던 값
그대로
그대로
ambientCG 파일 이름
_NormalGL
—
_NormalDX
Studio 텍스처 작업 공간은 파일 이름의 _NormalGL·_NormalDX를 선언된 규약으로 읽습니다. 랩은 둘 다 그냥 노멀맵으로 분류하며, 그 밖의 이름은 규약에 대해 아무것도 알려 주지 않습니다.
받게 되는 파일
파일
용도
rock_normal-directx.png
변환한 맵. 이름은 입력이 OpenGL이라고 가정합니다. DirectX 맵을 변환했다면 내용은 OpenGL이므로 헷갈리지 않게 이름을 바꾸세요.
texture-report.json
선택: 점검 단계에서 세트의 노멀맵마다 normalCheck.meanLength, unitLength, blueNonNegative.
변환한 맵을 엔진에서 쓰기
엔진 설정은 각 문서를 따른 것이며 Nerulio가 이 가져오기를 실행하지는 않았습니다.
Unity 6: OpenGL 맵을 가져와 Texture Type을 Normal map으로 둡니다. DirectX 맵만 있다면 변환하지 않고 같은 임포터의 Flip Green Channel을 체크해도 됩니다.
Godot 4: 머티리얼의 Normal Map을 켜고 OpenGL 맵을 지정합니다. DirectX 맵이라면 가져오기 독에서 Process › Normal Map Invert Y를 켜고 Reimport하는 방법도 있습니다.
glTF 2.0: 노멀 텍스처는 +X 오른쪽·+Y 위쪽이어야 하므로 DirectX 맵은 내보내기 전에 변환합니다.
DirectX 방식 대상: 변환한 -directx.png를 쓰고 그 엔진의 가져오기 문서를 따릅니다.
머티리얼을 위에서 비추고 튀어나온 부분의 위쪽 가장자리가 밝은지 확인합니다.
결과 확인
노멀 단계에 평균 벡터 길이와 최대 오차가 나옵니다. 올바른 맵은 1에 가깝습니다.
저장한 파일을 원본과 채널별로 비교합니다(채널 단계). R·B·A는 같고 G = 255 − g여야 합니다.
결과를 한 번 더 변환하면 원래 바이트가 돌아옵니다.
문제 해결
증상
유력한 원인
확인 방법
해결
튀어나온 곳이 들어가 보이고 빛이 아래에서 오는 듯함
맵이 반대 규약
위에서 비출 때 어느 가장자리가 밝은가
여기서 변환하거나 Unity Flip Green Channel·Godot Normal Map Invert Y 사용
텍스처 랩에서 측정(docs/TEXTURE-LAB.md): 두 다운로드를 채널별로 비교하면 정확히 dx.g == 255 − gl.g, R·B·A는 동일. 변환한 맵은 평균 길이 1.0001, 최대 오차 0.0002로 디코딩됐습니다. 감지 수치는 규약을 아는 실제 맵으로 한 Studio 평가에서 나왔습니다(docs/STUDIO-TEXTURE.md, 2026-09-24). 엔진 규약은 아래 문서에서 인용했으며, 변환한 파일의 엔진 가져오기는 실행하지 않았습니다.