본문 바로가기
DirectX 12/Camera & Lighting

[DirectX12 - Camera & Lighting] Chapter 04. Normal Mapping

by song.ift 2023. 6. 22.

GitHub : https://github.com/developeSHG/DirectX12-Camera_Lighting/commits/04.Normal_Mapping

 

GitHub - developeSHG/DirectX12-Camera_Lighting: DirectX12 - Camera & Lighting

DirectX12 - Camera & Lighting. Contribute to developeSHG/DirectX12-Camera_Lighting development by creating an account on GitHub.

github.com

 

결과물

 

 


 

 


cube를 보면 각 버텍스 별로 노말벡터들이 동일하다.(어떻게 보면 면은 같은 곳을 바라보니 동일한 건 맞는얘기)
그러다보니 버텍스 쉐이더에서 계산해준 값을 나중에 레스터라이즈를 통해 각각 사이에 있는
모든 픽셀들에 대한 노말정보를 따로 추출해주겠지만, 아무리 보간을 해봤자 정점 노말 값이 똑같다면
내부에 있는 픽셀이 노말 벡터들도 동일한 값을 갖게 된다는 문제가 생긴다.
그렇게 되었을 때, 빛이 아무리 반사를 하고 연산을 해도 심심한 형태로 출력이 된다.

구 같은 경우는 정점 갯수가 훨씬 많았고, 세부적인 삼각형마다 노말 벡터를 다르게 주다보니까
빛의 반사되는 현상이 있었던 것이다.

큐브만 그런 문제가 발생하는 게 아니라, 나중에 메쉬에도 똑같은 현상이 발생한다.

그렇게되면 그냥 구처럼 당연히 큐브도 버텍스를 늘리면 되지 않느냐?
당연히 그렇게하면 노말벡터를 다르게 주니 빛 현상도 줄수 있겠다만은 
나비 효과로 인해 프로그램 실행속도도 느려지고, 연산량도 그만큼 기하급수적으로 늘어나게된다.
당연히 연산은 gpu한테 떠넘기는거지만, 그래도 버텍스를 늘리는 건 말이 안된다. (원론적인 문제를 해결못함)
비주얼적으로 좋게 하기위해 성능을 잡아먹는 트레이드는 좋지않다.

 


그래서 노말 매핑이 필요한 것.
정점을 늘려서 픽셀 단위에 노말값을 설정하는 게 아니라, 그냥 별도의 노말 이미지파일을 만들어서(노말맵이라함)
각각 픽셀에 해당하는 노말벡터값을 이미지 파일에 가지고있겠다는 걸 말한다.

사실 텍스쳐라는 거 자체가 어떠한 정보를 가지고 있다.
보통은 RGBA 정수값을 들고있는데, 그 값을 어떻게 분석해서 사용할지는 프로그래머의 마음이다.
정말 RGBA 값으로 색상을 입혀도 되겠지만, 그 정보를 다른 용도로 예를 들어 좌표로 사용해도 정당한 방법이다.
그래서 텍스쳐 매핑을 할 때, 각 삼각형마다 uv좌표를 이용해 텍스쳐를 입힌 것처럼
그거랑 똑같이 uv좌표에 해당하는 각각 픽쉘에다 노말 정보를 전달해주는 것이 핵심이다.
야매로 볼수 있지만, 버텍스를 늘리지 않고, 그렇게 사용하는 것이 노말 매핑.

 

VS_MAIN(버텍스 쉐이더) -> Rasterizer(레스터라이저 단계) -> PS_MAIN(픽쉘 쉐이더)
순서가 버텍스 쉐이더가 끝난 후, 레스터라이저 단계에서 열심히 보간해서 픽쉘 단위로 픽쉘 쉐이더에 넘기게 되는 것.
(uv 좌표도 넘겨줌. 픽쉘 쉐이더에서 uv좌표를 통해 노말맵에서 노말정보를 갖고오는 것)



근데 노말 텍스쳐는 다 푸른색으로 이루어져있다.
각각 노말 데이터도 다른데 왜 다 똑같을까? 각기 픽셀마다 다른색이여야 하지 않을까?
그 이유는 노말 텍스쳐는 로컬 좌표계, 오브젝트 기준 좌표를 사용하지 않는다.
별도의 좌표게를 쓴다.

왜 그러냐하면 메쉬를 생각해보면 된다.
메쉬도 가만히 있는 메쉬가 있지만, 나중엔 애니메이션이 있는 메쉬가 있다.
애니메이션 메쉬는 당연히 움직임에 따라 로컬 좌표도 변할 것이고, 그에 따른 노말값도 변해야 정상이다. (당연히 똑같으면 안돼지)
그러면 애니메이션 마다 텍스쳐를 매번 다른 준비해야하냐? 그것도 당연히 말이 안된다,
그래서 결국에는 노말매핑 할 때는, 노말 텍스쳐 자체가 플레이어 로컬 기준으로 하는게 아니라,
별도의 좌표계를 하나 더 가지고있는데 그게 탄젠트 스페이스라 한다.

 

 

탄젠트를 개념적으로 보면 접하는 평면. 접하다 라는 걸로 굉장히 단순하다.
노말 텍스쳐는 탄젠트 스페이스 기준으로 만들어졌다.
텍스쳐에는 각 점마다 T(탄젠트), B(바이노말), N(노말) 이 있다.

 

댓글