참고 영상
노말맵이란 무엇인가?

- 사용 단계 : 렌더링 파이프라인의 프래그먼트 셰이더(Fragment = Pixel Shader) 단계
- 역할 : 프래그먼트마다 조명을 계산할 때, 표면의 진짜 법선(Normal) 대신 텍스처에 저장된 가짜 법선 정보를 사용하여 디테일한 입체감을 만듭니다.
- 핵심 원리 (페이크) : 실제 모델의 형태를 바꾸는 것이 아니라, 빛이 표면에 반응하는 방식을 '속여서' 평평한 면이 울퉁불퉁하게 보이도록 만듭니다.
- 필요성 (가성비) : 적은 수의 폴리곤(로우폴리 모델)을 사용하면서도 하이폴리 모델처럼 디테일한 표면을 구현할 수 있습니다. 이는 게임과 같은 실시간 렌더링 환경, 특히 모바일에서 성능 비용을 획기적으로 절약하는 핵심 기술입니다.
노멀맵을 만드는 과정으로는
- 원본 (High-Poly) : 아주 많은 폴리곤을 사용해 디테일이 풍부하고 울퉁불퉁한 '하이폴리 모델'을 만듭니다.
- 사본 (Low-Poly) : 폴리곤 수를 획기적으로 줄인 '로우폴리 모델'을 만듭니다. (게임에서 실제 사용)
- 정보 저장 (Baking) : 하이폴리 모델의 복잡한 표면 방향 정보를 노말맵(텍스처)에 미리 구워서 저장합니다.
- 계산 시 사용 (Rendering) : 실제 게임에서는 로우폴리 모델을 띄우지만, 빛 계산을 할 때는 로우폴리 모델의 밋밋한 표면 방향 대신 노말맵에 저장된 복잡한 방향 값을 참조합니다.
결론적으로 "로우폴리 모델을 쓰면서도 라이팅 계산은 하이폴리 모델처럼" 하게 만드는 기술입니다. 그래서 빠른 속도와 높은 디테일을 둘 다 잡는 것입니다.
빛과 '노말(Normal)'의 관계



노말맵을 이해하려면 먼저 '노말'이 무엇인지 알아야 합니다.
- 노말(Normal)이란? : 면이 바라보는 '방향'을 의미하는 벡터(Vector) 값입니다.
- 라이팅 계산 : 표면의 밝기는 빛의 방향과 표면의 노말 방향이 이루는 각도에 따라 결정됩니다. 빛을 정면으로 받는 면은 밝고, 비스듬히 받는 면은 어두워집니다.
- 핵심 연산 (내적) : 컴퓨터 그래픽스에서는 이 밝기를 효율적으로 계산하기 위해 두 벡터(빛 방향, 표면 노말 방향)의 내적(
두 벡터가 얼마나 같은 방향을 바라보고 있는지를 구하는) 연산을 사용합니다.
노말맵은 왜 파란색인가?

노말맵 텍스처는 특유의 푸른색을 띱니다.
- 이유 (데이터 텍스처) : 노말맵은 눈에 보이는 색상(알베도)이 아니라, 방향 '데이터'를 저장하는 텍스처이기 때문입니다.
- RGB = XYZ : 텍스처의 R, G, B(Red, Green, Blue) 채널에 각각 벡터의 X, Y, Z 방향 값을 저장합니다.
- 푸른 이유 (Z축) : Z축(Blue 채널)은 '표면에서 바깥쪽을 향하는 방향'을 의미합니다. 대부분의 디테일은 표면에서 미세하게 튀어나온 형태이므로 Z값이 거의 항상 양수(0.5~1 사이)가 됩니다. 따라서 Blue 채널 값이 항상 높아 전체적으로 푸른색을 띠게 됩니다. (= 노말 벡터는 길이가 1(X²+Y²+Z²=1)이라는 특성을 이용해, X, Y값만 알면 Z값을 수학적으로 복원할 수 있기 때문입니다.)
핵심 이론 : 탄젠트 스페이스 (Tangent Space)


가장 중요하고 복잡한 개념입니다. 노말맵은 '표면 기준'으로 방향을 저장했는데, 3D 모델은 구부러져 있어 '월드(세상) 기준'의 방향과 다릅니다.
- 문제 제기 : 평평한 텍스처에 저장된 방향 값(예: "위로 튀어나옴")을 구부러진 모델 표면에 적용할 때, 각 지점의 '위'가 어디인지 알려줄 기준이 필요합니다.
- 해결책 (TBN) : 모델 표면의 각 지점(픽셀)마다 고유한 '좌표계(Tangent Space)'를 설정합니다.
- 좌표계 구성 (TBN 행렬) : 이 좌표계는 3개의 수직축으로 이루어집니다.
- Normal (N) : 원래 표면이 향하는 방향 (Z축 역할)
- Tangent (T) : UV 좌표의 U방향(가로)을 따르는 접선 (X축 역할)
- Bitangent (B) : N과 T에 모두 수직인 방향 (Y축 역할, '외적'으로 계산)
- 변환 : 쉐이더는 이 TBN 행렬(Matrix)을 사용해 노말맵 텍스처에 저장된 '표면 기준 방향'을 '월드 기준 방향'으로 변환시킵니다.
- 최종 계산 : 이렇게 변환된 최종 노말 값과 실제 조명(월드 기준)을 '내적'하여 올바른 표면 밝기를 계산합니다.
💡 쉽게 이해하기 (비유)
- 월드 스페이스 노말 (World Space) : "이 흉터는 북쪽을 향해 튀어나와 있어."라고 기록하는 방식입니다. -> 캐릭터가 남쪽으로 회전하면 흉터 방향 정보가 틀려서 사용할 수 없습니다.
- 탄젠트 스페이스 노말 (Tangent Space) : "이 흉터는 피부 표면에서 수직으로 튀어나와 있어."라고 기록하는 방식입니다. -> 캐릭터가 회전하든 덤블링을 하든, 흉터는 항상 피부 위에서 올바르게 튀어나와 보입니다. (재사용 가능)
유니티 노말맵 임포트와 압축
유니티에서 노말맵 텍스처는 반드시 "Normal Map" 타입으로 설정해야 합니다.
- 이유 1 (감마 보정 제외) : 노말맵은 색상이 아닌 '데이터'이므로, 사람의 눈에 맞게 밝기를 조절하는 '감마 보정(Gamma Correction)'을 건너뛰어야 벡터 값이 정확하게 유지됩니다.
- 이유 2 (고품질 압축 - Z축 복원) :
- 유니티는 노말 맵을 압축할 때(DXT5nm 등), R채널과 G채널(X, Y값)만 저장하고 B채널(Z값)은 버립니다.
- 복원 원리 : 벡터의 길이는 항상 1이라는 피타고라스 정리 (x^2 + y^2 + z^2 = 1)를 이용해, 쉐이더 내부에서 z = sqrt{1 - x^2 - y^2} 공식으로 Z값을 다시 만들어냅니다.
- 이렇게 하면 용량은 줄이면서도 Z축의 디테일을 잃지 않을 수 있습니다.
- 효과 : 2개 채널만 사용하므로 데이터를 더 효율적으로 압축(예: DXT5nm, ASTC)하여 용량을 줄이고 품질을 높일 수 있습니다.
다른 기술과의 비교


- 패럴랙스 맵핑 (Parallax) : 노말맵보다 깊이감을 더 주지만(하이트맵 사용), 연산 비용이 높고 시각적으로 불안정하여 '가성비'가 떨어집니다.
- 디스플레이스먼트 맵핑 (Displacement) : 실제로 정점(Vertex)을 이동시켜 가장 현실적입니다. 하지만 '테셀레이션' 기술이 필수라 하드웨어 요구 사양이 매우 높습니다.
- 결론 : 노말맵이 현재 모바일을 포함한 대부분의 실시간 렌더링 환경에서 '가성비(성능 대비 품질)'가 가장 좋은 기술입니다.
'CS > 그래픽스' 카테고리의 다른 글
| [Rendering Pipeline] Stage 3 : Tessellation (Hull Shader, Tessellator, Domain Shader) (0) | 2025.12.25 |
|---|---|
| [Rendering Pipeline] Stage 2 : Vertex Shader (0) | 2025.12.25 |
| [Rendering Pipeline] Stage 1 : Input Assembly (0) | 2025.12.25 |
| [Rendering Pipeline] Stage 0 : Vertex/index Buffer Preparation(Application Stage) (0) | 2025.12.25 |
| Anti-Aliasing (0) | 2025.11.11 |