[눈의 착각]

 

물체에 굴곡이 있다면 빛의 입사에 대한 반사각도가 달라지게 됩니다. 이렇게 반사된 빛이 얼마만큼 눈에 들어오는지에 따라 음영이 인식되면서 굴곡을 인식하게 됩니다. 하지만 사람의 눈은 생각보다 정교하게 물체를 인식하지 않기 때문에 단순한 눈속임으로도 충분히 굴곡이 있음을 인식키실 수도 있습니다.

격자 착시

 

눈의 착각을 활용하는 방법 중 가장 대표적인 것은 착시 현상입니다. 노말 매핑은 이런 단순한 속임수를 활용하는 방법이라고 볼 수 있겠습니다.

 

 

[노말 매핑]

 

특정 메시에 굴곡이 있을 때, 굴곡을 모두 폴리곤으로 표현한다면 메시의 폴리곤 수가 그만큼 늘어나게 될 것이고, 이걸 계산하거나 저장하기 위해 많은 컴퓨터 자원을 필요로 할 것입니다. 하지만 굴곡 표현을 텍스쳐 하나로 대체하는 방법이 있습니다.

 

위 그림을 확인해보시면 텍스쳐 한 장이 있고 없고의 차이가 확연하게 느껴지실 겁니다. 이때 사용하는 텍스쳐를 노말맵이라고 하고, 이 텍스쳐를 활용해서 굴곡을 표현하는 기법을 노말 매핑이라고 합니다. 노말 매핑을 활용하면 위에서 말한 것과 같이 메시의 폴리곤 수를 압도적으로 줄일 수 있습니다.

 

초기의 매핑은 높이 정보를 갖는 흑백 텍스쳐를 활용했습니다. 하지만 이러한 텍스쳐는 높은 해상도를 요구하며, 저해상도로 떨어질 경우 표현 가능한 세부 사항이 제한되는 등 문제가 있어 높이가 아닌 표면의 법선 벡터 정보를 활용하는 방식으로 변경되었습니다.

 

 

[노말 매핑을 위한 스페이스]

 

노말 맵은 월드 스페이스 노말맵(World Space Normal Map)과 탄젠트 스페이스 노말맵(Tangent-Space Normal Map)이 있습니다. 둘의 가장 큰 차이는 "어떤 좌표계 기준"으로 노말을 저장하고 불러오느냐에 있습니다.

 

 

1. 월드 스페이스 노말맵

 

노말맵 텍스쳐 안의 RGB값 자체가 월드 좌표계에서의 노말 방향(x, y, z)를 저장하고 있습니다. 그래서 셰이더에서 단순히 이 값을 활용할 경우에는 다음과 같이 사용하면 됩니다.

float3 Sampled = NormalTex.Sample(BaseSampler, uv).xyz; // ∈ [0,1]
float3 WorldSpaceNormal = normalize(Sampled * 2.0f - 1.0f); // ∈ [−1,1]

 

+) 텍스쳐에서 얻어온 Sampled 값(x, y, z)는 모두 0.0에서 1.0사이로 정규화된 값입니다. 하지만 실제 노말 벡터는 -1.0에서 +1.0 사이의 범위에서 기울어짐이 표현되어야 합니다. 따라서 리맵핑을 실시합니다. 이 리맵핑에 필요한 공식이 [Sampled * 2.f - 1.f]라는것 정도만 알고계시면 될 것 같습니다.

 

월드 스페이스 노말 맵은 정적인 오브젝트에 주로 활용됩니다. 이유는 월드 스페이스 노말맵이 단순히 특정 형태로 고정된 메시에 대해, 그 상태에서의 법선 벡터들을 저장한 값이기 때문입니다. 그림으로 예시를 들자면 다음과 같습니다.

그림과 같은 형태의 구체 메시가 있다고 가정해봅시다. 여기서 각 선은 월드 스페이스 노말맵에 저장된 법선 벡터입니다. 여기서 만약 구체가 회전하면 어떻게 될까요?

예상은 그림과 같이 법선 벡터도 이동된 뒤 정상 적용되는 것이지만, 실제로는 다릅니다.

월드 스페이스 노말맵은 특정 형태에 대해 저장된 뒤, 고정된 법선 벡터값을 갖기 때문에 단순히 회전만 할 경우에는 의도치않은 렌더링 결과가 발생하게 됩니다. 물론 회전을 따로 처리하거나 하는 방식으로 노말값을 재정렬할 순 있지만, 그냥 정적인 오브젝트에만 사용하는 것이 좋습니다.

 

2. 탄젠트 스페이스 노말맵

 

탄젠트 스페이스 노말맵에 저장된 값 (nx, ny, nz)들은 텍스쳐 좌표(UV) 기준으로 얼마나 기울어져있는가를 저장한 정보들입니다. 예를 들어 평평한 면을 위에서 내려다본다고 했을 때, U, V가 다음과 같다고 가정해보겠습니다.

 

- 텍스쳐의 가로축(U)이 월드 상에서 오른쪽 방향(→)을 가리킨다.

- 텍스쳐의 세로축(V)이 월드 상에서 위쪽 방향(↑)을 가리킨다.

 

이 조건에서 노말맵 텍스쳐에 저장된 (nx, ny, nz)는 텍스쳐 좌표(UV) 공간에서 볼 때, 각 값이 의미하는 바는 다음과 같습니다.

 

- nx : 표면이 얼마나 U축으로 기울어져 있는가

- ny : 표면이 얼마나 V축으로 기울어져 있는가

- nz : 원래 법선 방향이 Z축으로 얼마나 세워져 있는가

 

이제 이 값을 월드 좌표계로 옮겨줘야합니다. 이때 사용하는 행령이 TBN 행렬입니다. 각 정점(or 픽셀)마다 세 가지 축을 가져옵니다.

 

- Tangent : 이 지점의 텍스쳐 U축이 월드에서는 어느 방향인지

- Binormal : 이 지점의 텍스쳐 V축이 월드에서는 어느 방향인지

- Normal  : 이 지점의 텍스쳐 평면에서의 법선은 월드에서는 어느 방향인지

 

이 세 벡터를 각각 월드 공간으로 변환한 뒤, 노말 텍스쳐에서 읽어들인 값과 mul하면, 텍스쳐 공간 기준 기울기가 월드 공간 기준 기울기로 변환됩니다. 이렇게 매 순간 변환되기 때문에 움직이는 물체에서도 탄젠트 스페이스 노말을 활용하면 노말 매핑을 문제없이 활용할 수 있습니다.

 

실제로 근래의 메시들은 다이나믹 메시가 아니더라도 탄젠트, 바이노말 값을 가지고 있고 노말 텍스쳐도 기본적으로는 탄젠트 스페이스 노말 텍스쳐입니다.

'DirectX11 > 그래픽스' 카테고리의 다른 글

[Graphics] Rendering Pipeline  (0) 2025.06.18
[Graphics] 드로우콜(Draw Call)  (0) 2025.06.11
[Graphics] 포워드 렌더링, 디퍼드 렌더링  (0) 2025.06.11
[Graphics] Normal  (0) 2025.06.06
[Graphics] Lighting  (2) 2025.06.05

+ Recent posts