newhaneul

[Multimedia] Lecture 10. Normal Mapping 본문

4. University Study/Multimedia

[Multimedia] Lecture 10. Normal Mapping

뉴하늘 2026. 4. 10. 18:30
728x90

본 포스팅은 인하대학교 안남혁 교수님의 [202601-EEC4410-001] Multimedia을 수강하고 공부한 내용을 정리하기 위한 포스팅입니다.

 

1. 노멀 매핑의 기본 개념 및 필요성 (Normal Mapping)

 

  • 고해상도의 정밀한 폴리곤 메쉬(High-resolution mesh)를 렌더링하는 것은 계산 비용이 매우 많이 들어 비효율적이다.
  • 반면 계산 비용이 적은 저해상도의 메쉬(Low-resolution mesh)를 사용하면 표면의 울퉁불퉁한 기하학적 디테일(Bumpy features)을 제대로 표현하지 못하는 한계가 있다.
  • 이를 해결하기 위해 고해상도 표면의 법선 벡터(Normal vector)를 미리 계산한 후, '노멀 맵(Normal map)'이라는 특별한 텍스처에 저장하는 방식을 사용한다.
  • 런타임 시에는 연산량이 적은 베이스 표면(Base surface)을 렌더링하면서, 조명 연산을 할 때는 노멀 맵에서 저장해둔 고해상도의 법선 벡터를 읽어와 사용함으로써 기하학적 디테일을 추가하지 않고도 울퉁불퉁한 착시 효과를 효율적으로 낼 수 있다.

 

 

 

  • 핵심 원리: 고해상도 표면에서 나타나는 정밀한 법선 벡터(표면의 방향 정보)들만 따로 추출해서, 이를 노멀 맵(Normal map)이라는 특별한 이미지 텍스처에 미리 저장(Pre-compute)해 둔다.
  • 런타임 적용: 실제 렌더링을 돌릴 때는 가벼운 저해상도 표면(Base surface)을 화면에 띄워 둔다.
  • 착시 효과 생성: 조명(Lighting) 연산을 할 때 밋밋한 저해상도 표면의 원래 법선을 무시하고, 미리 만들어둔 노멀 맵에서 고해상도의 법선 벡터 정보를 실시간으로 읽어와서 빛의 반사를 계산하게 된다.

 

 

2. 높이 맵(Height Map)과 노멀 맵 생성 알고리즘 

노멀 맵은 보통 높이 맵(Height map)으로부터 생성되며, 이 변환 과정에 사용되는 수식은 매우 중요하다.

        • 높이 맵(Height Map): 표면을 나타내는 연속 함수 $h(x,y)$를 사용해, $(x, y)$ 좌표에 따른 높이(z축 값)를 2D 배열의 형태로 기록한 텍스처이다. 보통 0(가장 낮음, 검은색)에서 255(가장 높음, 흰색) 사이의 그레이스케일로 표현된다.
        • 높이 맵에서 노멀 벡터 구하기: 주어진 $(x, y)$ 좌표에서 x축 및 y축 방향의 높이 변화량(gradient)을 먼저 구한다.
          • $\delta h_x = h(x+1, y) - h(x-1, y)$
          • $\delta h_y = h(x, y+1) - h(x, y-1)$
        • 위에서 구한 변화량을 이용해 외적(Cross product)을 수행하여 해당 위치에서의 노멀 벡터를 계산한다.
          • $$\frac{(-2\delta h_x, -2\delta h_y, 4)}{||(-2\delta h_x, -2\delta h_y, 4)||}$$
        • RGB 범위 변환: 위에서 계산된 노멀 벡터의 각 성분 값은 $[-1, 1]$의 범위를 가지지만, 이를 텍스처의 색상 값으로 저장하기 위해서는 $[0, 1]$ 범위로 정규화해주어야 한다.
          • $R = (n_x + 1) / 2$
          • $G = (n_y + 1) / 2$
          • $B = (n_z + 1) / 2$

높이 맵 (Height Map)의 개념

 노멀 맵을 생성하기 위한 가장 보편적인 원본 데이터는 높이 맵이다.

  • 표면의 기하학적 굴곡을 $(x, y)$ 평면 좌표에 따른 높이 값 $z$를 반환하는 연속 함수 $h(x,y)$로 정의할 수 있다.
  • 이 함수를 일정한 간격의 2D 격자 형태로 샘플링하여 텍스처 배열에 저장한 것이 바로 높이 맵이다.
  • 시각적으로는 흑백(Grayscale) 이미지로 표현되며, 높이 범위를 [0, 255]로 환산했을 때 가장 낮은 곳은 0(검은색), 가장 높은 곳은 255(흰색)로 나타낸다.

 

일반 이미지 텍스처에서 높이 맵 생성

 복잡한 3D 모델링 과정 없이, 일반적인 2D 이미지 텍스처로부터 간편하게 높이 맵을 만들어내는 방법이다.

  • 돌바닥 같은 이미지의 RGB 색상 값을 평균 내어($(R+G+B)/3$) 흑백 이미지로 변환한다.
  • 이후 필요에 따라 수작업(Hand-edit)으로 이미지의 대비를 조절하여 굴곡을 더 뚜렷하게 만든다.
  • 이 방식은 실제 고해상도 기하학 구조(High-frequency mesh)에서 수치적으로 정확하게 추출한 높이 맵보다는 덜 정교하지만, 제작 비용이 압도적으로 저렴하고 매우 쉽다는 장점이 있다.

높이 맵을 노멀 맵으로 변환하는 수학적 원리

 앞서 만든 흑백의 높이 맵에서 각 픽셀이 바라보는 표면 방향(노멀 벡터)을 계산하여 최종적인 노멀 맵을 생성하는 수학적 과정이다.

  • 기울기 및 외적 계산: 현재 픽셀을 중심으로 인접한 상하좌우 픽셀과의 높이 차이를 계산하여 x축 방향의 변화량($\delta h_x$)과 y축 방향의 변화량($\delta h_y$)을 구한다. 이 기울기 값들을 이용해 외적(Cross product) 연산을 수행하면, 해당 지점의 법선 벡터인 $\frac{(-2\delta h_x, -2\delta h_y, 4)}{||(-2\delta h_x, -2\delta h_y, 4)||}$를 얻을 수 있다.
  • RGB 색상 데이터로 변환 (정규화): 계산된 법선 벡터의 방향 성분(x, y, z)은 각각 $[-1, 1]$의 수학적 범위를 갖는다. 그러나 이를 이미지 파일인 텍스처에 저장하려면 색상 값 범위인 $[0, 1]$로 형태를 변환해주어야 한다.
  • 따라서 $R = (n_x + 1)/2$, $G = (n_y + 1)/2$, $B = (n_z + 1)/2$와 같이 각각 1을 더하고 2로 나누는 스케일링을 거친다. 이 변환식 때문에 z축(위쪽)을 향하는 기본 법선 성분이 Blue 채널에 강하게 맵핑되어 노멀 맵이 특유의 푸르스름한 보라색 띠게 된다.

고해상도 메쉬에서 직접 노멀 맵 추출 (대안적 방법)

높이 맵을 거치지 않고 정밀하게 조각된 고해상도 원본 메쉬(High-poly)에서 직접 노멀 맵을 구워내는(Baking) 방법이다.

  • N x N 해상도의 텍스처 각 픽셀 위치에서 수직으로 광선(Ray)을 쏴서 교차하는 고해상도 폴리곤 조각을 찾는다.
  • 교차된 폴리곤 조각은 삼각형이므로 3개의 정점을 가지며, 각 정점에는 고유한 법선 벡터($n_a, n_b, n_c$)가 존재한다.
  • 무게중심 보간(Barycentric Interpolation): 교차점의 정확한 법선을 구하기 위해, 세 정점의 법선 벡터에 픽셀 위치에 따른 가중치($u, v, w$)를 곱해 더하는 방식($n_p = u n_a + v n_b + w n_c$)으로 최종 법선 $n_p$를 산출해낸다.

렌더링 시 노멀 매핑의 적용 과정 (Runtime)

 준비된 노멀 맵을 실제 실시간 렌더링 파이프라인에서 어떻게 적용하는지 보여준다.

  • 3D 그래픽카드가 형태가 단순한 저해상도 폴리곤을 화면의 픽셀 단위로 쪼개는 래스터화(Rasterization) 단계를 거칠 때, 스캔라인을 따라 각 픽셀에 고유한 텍스처 좌표 $(s, t)$가 매핑된다.
  • 렌더링 프로그램은 이 $(s, t)$ 좌표를 가지고 기본 이미지 텍스처(표면의 색상)와 노멀 맵(표면의 굴곡 방향) 양쪽에서 데이터를 동시에 필터링하여 읽어 들인다.
  • 이렇게 픽셀마다 읽어 들인 노멀 벡터를 조명 계산식(Phong Reflection Model 등)에 집어넣어 그림자와 빛 반사를 계산함으로써 최종 렌더링 이미지를 완성한다.

 

 

3. 퐁 조명 모델에서의 노멀 매핑 적용 (Phong Model)

  • 렌더링 과정에서 폴리곤 메쉬가 래스터화(Rasterized)될 때, 텍스처 좌표 $(s, t)$를 사용하여 노멀 맵에 접근하여 해당 위치의 법선 벡터 $n$을 얻는다.
  • 추출한 법선 벡터 $n$은 기존 퐁 조명 모델의 난반사(Diffuse) 및 정반사(Specular) 항을 계산할 때 사용된다. 조명 모델의 최종 수식은 다음과 같다.
    • $$max(n \cdot l, 0)s_d \otimes m_d + (max(r \cdot v, 0))^{sh}s_s \otimes m_s + s_a \otimes m_a + m_e$$

 

조명 공식에서의 노멀 매핑 (Normal Mapping)

 위의 식은 퐁 조명 모델(Phong lighting model) 중 난반사(Diffuse reflection) 항을 보여준다.

  • 공식: $max(n \cdot l, 0) s_d \otimes m_d$
  • 여기서 원래 기하학적 폴리곤이 가지고 있던 밋밋한 법선 벡터를 무시하고, 노멀 맵 텍스처에서 새로 읽어 들인 정밀한 법선 벡터 $n$을 공식에 대입한다.
  • 이렇게 하면 빛 벡터 $l$과 새로운 법선 벡터 $n$ 사이의 각도 $\theta$가 픽셀마다 세밀하게 달라지므로, 평평한 바닥(Base surface)이라도 매우 오밀조밀하고 사실적인 그림자가 계산된다.

노멀 매핑의 시각적 장단점

  • 효율성(Efficient): 실제 3D 모델의 구조(Geometry)를 전혀 복잡하게 만들지 않고도 빛과 그림자의 착시만으로 고해상도의 디테일(High-frequency detail)을 흉내 낼 수 있어 성능 면에서 매우 유리하다.
  • 시각적 한계: 하지만 노멀 매핑은 어디까지나 눈속임일 뿐, 모델의 실제 형태를 변형시키지는 않는다. 따라서 결과 이미지(하단)를 보면 표면은 울퉁불퉁해 보이지만, 모델의 가장자리 외곽선(Linear edges)은 여전히 자로 잰 듯 반듯한 직선 형태를 띠고 있어 완전히 자연스럽지는 않다는 한계가 있다.

현재 노멀 매핑 방식의 치명적인 한계 (Limitation)

 '접선 공간(Tangent Space)'의 필요성

  • 텍스처링이란 결국 이미지를 물체의 표면에 '포장지처럼 감싸서 붙이는(Pasting)' 작업이다. 따라서 평면뿐만 아니라 임의의 방향으로 기울어진 면이나, 둥글게 휘어진 곡면에도 텍스처를 자연스럽게 붙일 수 있어야 한다.
  • 하지만 지금까지 만든 노멀 맵은 처음 만들어질 당시의 기준 공간(보통 오브젝트의 기본 좌표계)에 맞춰 벡터 방향(예: 모두 위를 향함)이 고정되어 있다.
  • 슬라이드 우측 그림처럼, 이 고정된 노멀 맵을 기울어진 면이나 둥근 곡면에 그대로 가져다 붙이면 법선 벡터들이 표면의 방향을 따라 회전하지 않고 여전히 원래 방향(위쪽)만 가리키게 된다. 이렇게 되면 빛 반사 계산이 완전히 엉망이 된다.
  • 이 문제를 해결하기 위해 표면이 휘어지거나 회전하는 것에 맞춰 노멀 맵의 벡터들도 함께 회전시켜주는 추가적인 수학적 처리 공간이 필요한데, 그것이 바로 접선 공간(Tangent Space) 노멀 매핑이다.

 

 

4. 접선 공간 노멀 매핑 (Tangent Space Normal Mapping) 

일반적인 노멀 매핑의 한계를 극복하기 위해 도입된 공간 변환 개념으로, 동작 원리와 TBN 행렬을 이해해야 한다.

  • 접선 공간(Tangent Space)의 도입: 표면의 각 정점(Vertex)마다 접선(Tangent, T), 종법선(Bi-tangent, B), 법선(Normal, N)이라는 세 개의 직교 기저 벡터로 이루어진 독립적인 공간을 정의한다.
  • 접선 공간 노멀 매핑을 적용하면, 노멀 맵에서 읽어온 벡터 $n$은 항상 현재 픽셀이 속한 정점의 접선 공간 기준으로 해석된다.
  • 조명 연산의 공간 불일치 해결: 빛 벡터 $l$은 월드 공간(World space)에 정의되어 있지만, 추출한 노멀 벡터 $n$은 접선 공간에 있으므로 조명 연산을 위해 두 벡터의 공간을 일치시켜야 한다.
  • 일반적으로 월드 공간의 빛 벡터 $l$과 뷰 벡터 $v$를 접선 공간으로 변환하는 방식을 사용한다. 이때 사용되는 변환 매트릭스(TBN Matrix)는 다음과 같다.
    • $$\begin{pmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \\ N_x & N_y & N_z \end{pmatrix}$$

접선 공간(Tangent Space)의 도입 

 물체의 형태가 변형되거나 회전하면 기존의 Object Space 기준 노멀 맵은 더 이상 사용할 수 없게 된다. 이 문제를 해결하기 위해 3D 모델 표면의 각 정점(Vertex)마다 물체의 굴곡을 따라 흐르는 지역적인 좌표계를 새로 구축하는데, 이것이 바로 접선 공간이다.

  • 기저 벡터 구성: 접선 공간은 표면에 접하는 접선(Tangent, $T$), 종법선(Bi-tangent, $B$), 표면에 수직인 법선(Normal, $N$)이라는 세 개의 직교 벡터($TBN$)로 이루어진다.
  • 이 Tangent Space은 물체의 표면이 휘어지면 그 곡면을 따라 마치 카펫처럼 함께 휘어지며 방향이 변한다.
  • Tangent Space 기반의 노멀 맵을 사용하면, 노멀 맵에서 읽어온 법선 $n(s_p, t_p)$는 절대적인 공간 방향이 아니라, 현재 정점의 표면(접선 공간 내의 $z$축 방향, 즉 $(0,0,1)$)을 기준으로 '얼마나 요철이 기울어져 있는가(Perturbed)'를 나타내는 상댓값으로 취급된다.
  •  $T, B, N$ 벡터 데이터는 보통 렌더링 전 모델링 단계에서 미리 계산되어 정점 배열(Vertex array)에 위치(P), 텍스처 좌표(s, t)와 함께 저장된다.

TBN 행렬과 공간의 불일치 해결

 가장 중요한 조명 연산 적용 단계이다. 난반사 조명 공식 $\max(n \cdot l, 0)s_d \otimes m_d$을 계산할 때 치명적인 모순이 발생한다.

  • 빛을 쏘는 광원의 위치 방향 벡터 $l$은 전체 세계 기준인 월드 공간(World Space)에 존재한다.
  • 노멀 맵에서 픽셀별로 읽어온 법선 벡터 $n$은 표면 기준인 접선 공간(Tangent Space)에 존재한다.
  • 두 벡터의 기준 공간이 다르므로 그대로 내적($n \cdot l$) 연산을 수행할 수 없다. 따라서 빛 벡터 $l$을 Tangent Space으로 끌고 오거나, 법선 벡터 $n$을 World Space으로 내보내는 변환 과정이 반드시 필요하다.

 

 두 가지 방법이 있지만, 보통은 빛 벡터 $l$을 Tangent Space으로 변환하는 방식을 채택한다.

  • 만약 법선 벡터를 Tangent Space에서 World Space으로 변환하는 방식을 채택한다면, 수많은 법선 벡터들을 Pixel Shader 단계에서 매번 World Space으로 변환해야 하므로 비효율적이다.
  • 반면, 빛 벡터 $l$이나 카메라를 향하는 뷰 벡터 $v$는 Vertex Shader 단계에서 각 정점에 대해 계산된 $TBN$ 행렬을 사용해 Tangent Space으로 단 한번만 변환해두면 되기 때문에 연산 효율 면에서 압도적으로 유리하다.
    • World Space에 있는 빛 벡터 $l$을 해당 정점의 Tangent Space으로 회전시켜주는 TBN 변환 행렬은 아래와 같다.
      $$\begin{pmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \\ N_x & N_y & N_z \end{pmatrix}$$
       

 

 

 

5. 오브젝트 공간 vs 접선 공간 노멀 맵 요약 (Object-Space vs. Tangent-Space)

  • 오브젝트 공간(Object-Space) 노멀 맵: 오브젝트가 회전하거나 변형되지 않는다는 전제가 있을 때 사용한다. 구현이 매우 직관적이고 쉽다는 장점이 있다.
  • 접선 공간(Tangent-Space) 노멀 맵: 오브젝트의 회전 및 변형이 일어나거나, 비슷한 형태의 다른 오브젝트에 노멀 맵을 재사용하고자 할 때 필수적으로 사용한다. TBN 벡터를 계산하고 적용해야 하므로 구현이 어렵지만 범용성이 뛰어나다. Tangent Space normal map의 법선 기준 방향(z축)이 텍스처로 변환될 때 Blue 채널 값(1.0)에 매핑되기 때문에, 시각적으로 늘 푸르스름한 색을 띠게 된다.

노멀 맵이 푸르스름한 이유 (Why normal map always looks like bluish-color?)

 가장 핵심적인 이유는 접선 공간 노멀 맵이 "표면에서 수직으로 뻗어나가는 방향"을 기본 상태로 삼기 때문이다.

  • 수학적 변환: 노멀 맵은 $x, y, z$ 축의 방향 벡터 값을 이미지의 $R, G, B$ 색상 채널에 저장한다. 방향 벡터는 $[-1, 1]$의 범위를 가지는데, 텍스처 이미지의 색상 값은 $[0, 1]$ 범위여야 하므로 $0.5$를 더하고 $0.5$를 곱하는 식의 정규화 과정을 거친다.
  • 기본 법선 방향: 접선 공간(Tangent Space)에서 표면에 완전히 평평하고 수직으로 뻗어나가는 기본 법선 벡터는 $z$축 방향인 $(0, 0, 1)$이다.
  • 색상 매핑: 이 기본 방향 $(0, 0, 1)$을 앞서 말한 변환식에 대입하면,
    • $R = (0 + 1) / 2 = 0.5$ (중간 톤의 빨간색)
    • $G = (0 + 1) / 2 = 0.5$ (중간 톤의 초록색)
    • $B = (1 + 1) / 2 = 1.0$ (최대치의 파란색)
  • 결과: $RGB$ 값이 $(0.5, 0.5, 1.0)$이 되며, 이 색상이 바로 우리가 노멀 맵에서 흔히 보는 밝은 하늘색 내지는 연보라색 톤이다. 굴곡이 심할수록 $x, y$ 값이 커지면서 빨간색이나 녹색이 섞여 무지갯빛이 나타나지만, 기본적으로 표면을 위로 향하는 성향이 강하기 때문에 전체적으로 푸른빛이 감도는 것이다. 반면, 절대 좌표계를 따르는 오브젝트 공간 노멀 맵(위쪽 이미지의 좌측 다채로운 색상)은 면이 향하는 방향에 따라 색이 제각각으로 나타난다.

 

 Object Space vs Tangent Space Normal Map의 선택 기준

  • 시나리오 1: Object Space Normal Mapping
    • 언제 쓰나: 건물, 지형, 벽면처럼 게임 내에서 절대 움직이지 않거나 회전, 형태 변형(Deform)이 일어나지 않는 고정된 물체에 사용한다.
    • 장단점: 구현이 직관적이고 렌더링 시 $TBN$ 행렬 같은 복잡한 공간 변환 계산이 필요 없어 연산이 매우 빠르다. 하지만 형태가 조금이라도 변하거나 다른 모델에 재사용할 수는 없다.
  •  시나리오 2: Tangent Space Normal Mapping
    • 언제 쓰나: 사람, 몬스터의 관절이 꺾이거나 얼굴 표정이 변하는 등 형태 변형(Deform)이 일어나거나 회전하는 애니메이션 객체에 필수적이다. 또한 하나의 가죽 질감 노멀 맵을 여러 다른 갑옷 모델에 재사용하고 싶을 때도 사용한다.
    • 장단점: 표면의 곡률을 따라가는 $TBN$ 기저 벡터를 정점마다 계산하고 빛 벡터의 공간을 일치시키는 추가 연산이 필요해 구현이 다소 복잡하다. 하지만 모델이 아무리 구부러지고 회전해도 노멀 맵을 새로 구울 필요 없이 조명 계산이 정확하게 이루어지는 압도적인 범용성을 갖는다.

 

** 2024-2 중간고사, 2025-1 중간고사 **

  • 정답: Tangent Space 

 

** 2024-2 퀴즈 **

  • 정답: O

 

**2024-2 퀴즈 **

  • 정답: 
    • Object space normal map은 물체(Object) 자체의 중심 좌표계를 기준으로 normal 방향을 기록한다. 좌표 변환 연산이 적어 가볍고 빠르지만, 물체가 변형되면 기준 방향이 틀어져 버리기 때문에 움직임이 없는 물체에 주로 사용한다.
    • Tangent space normal map은 물체의 표면을 기준으로 한 Tangent space 좌표계를 사용하여 normal 방향을 기록한다. 렌더링 시 연산량이 더 발생하지만, 물체가 회전하거나 변형되어도 표면을 따라 normal 정보가 유지되므로 범용적으로 사용된다.
728x90