벽돌의 요철을 전부 메시로 만들지 않아도 조명에 따라 울퉁불퉁해 보이게 할 수 있습니다. 노말맵은 표면의 방향을 픽셀 단위로 바꿔 조명 계산에 사용합니다. 모델의 외곽선은 그대로라는 점이 중요한 차이입니다. 벽을 옆에서 보면 평평한데 정면에서는 굴곡이 보이는 이유도 여기에 있습니다.
처음에는 슬롯에 넣기만 하면 될 것 같지만, 막상 적용하면 홈이 돌출부처럼 보이거나 UV 경계가 눈에 띄기도 합니다. 이럴 때 강도부터 높이면 원인을 더 찾기 어려워집니다.
파란색은 방향을 숫자로 저장한 결과다
일반적인 탄젠트 공간 노말맵의 평평한 부분은 대략 RGB=(0.5, 0.5, 1)입니다. 표면 기준 방향 (0,0,1)을 음수가 없는 색 범위에 넣으면 그렇게 됩니다. 개념적으로는 encoded = normal * 0.5 + 0.5, 복원할 때는 반대 연산을 합니다.
다만 이것을 모든 노말맵 포맷의 저장 규칙으로 생각하면 안 됩니다. GPU 압축과 채널 재배치 방식에 따라 실제 데이터가 달라질 수 있습니다. 셰이더에서는 해당 파이프라인의 노말 언팩 함수를 사용하는 이유입니다. 일반적인 양의 Z 반구를 가정한 두 채널 표현에서는 나머지 성분을 sqrt(max(0, 1 - x*x - y*y))로 복원할 수 있습니다.
텍스처가 무조건 음수를 저장할 수 없는 것도 아닙니다. 부동소수점·부호 있는 포맷도 있습니다. 여기의 색 변환은 흔히 보는 정규화된 RGB 이미지 표현에 대한 설명입니다.
뒤집힌 굴곡을 확인하는 순서
Unity 6의 Normal Map 임포트와 기본 Lit 계열 머티리얼을 출발점으로 두고 비교합니다.
- 텍스처의 Texture Type이 Normal Map인지 확인합니다. 단순 색상 텍스처처럼 해석하지 않도록 합니다.
- 같은 머티리얼에서 노말맵을 빼고 조명을 움직여 봅니다. 원래 메시 노말부터 이상한지 구분합니다.
- 소스가 사용한 Y 방향을 확인합니다. Unity는 Y+ 관례를 사용하므로 반대 관례로 만든 맵이면 그린 채널 반전 여부를 비교합니다.
- UV 경계에서만 문제가 나면 메시의 노말·탄젠트와 베이킹 때 사용한 기준을 확인합니다.
- 작은 블록 무늬가 보이면 해상도를 고정한 채 압축 품질만 바꿔 봅니다.
그린 채널을 뒤집었을 때 좋아졌다는 이유만으로 항상 같은 설정을 적용하지는 않습니다. 전체 조명이 뒤집힌 문제와 일부 UV 심의 문제는 다릅니다. 커스텀 셰이더라면 노말과 광원 방향이 같은 공간인지도 먼저 확인해야 합니다.
노말맵이 해주지 않는 일
큰 돌출부의 실루엣, 실제 충돌 모양, 옆에서 보는 깊이까지 필요하면 메시나 다른 표현이 필요합니다. 패럴랙스는 높이 정보로 텍스처 좌표를 조절하고, 디스플레이스먼트는 실제 정점을 움직이는 방식이라 목적과 비용이 다릅니다. 어느 하나가 항상 정답은 아닙니다.
성능도 마찬가지입니다. 폴리곤을 줄이는 대신 텍스처 읽기와 픽셀 단위 연산, 메모리 비용이 생깁니다. 화면을 크게 덮는 물체에서는 픽셀 비용이 중요할 수 있고, 멀리 있는 작은 물체는 노말 디테일이 거의 보이지 않을 수 있습니다.
판단할 때는 같은 카메라 위치에서 노말맵을 켠 버전과 끈 버전을 비교하고, 대상 기기의 GPU 시간과 텍스처 메모리를 함께 기록합니다. 지오메트리도 동시에 바꾸면 어느 변경이 이득이었는지 알기 어렵습니다. 텍스처 용량 계산 글은 이때 메모리 예상값을 잡는 데 쓸 수 있습니다.
