17. Normal Mapping
노멀 매핑 적용 전의 텍스쳐
- 한 면에 적용되는 네 점의 노멀 벡터를 모두 같게 세팅해줬는데, 그러다보니
- 그 면에 보여지는 무늬가 심심해진다
노멀 벡터란?
- 한 점에 접하는 평면과 수직인 벡터
- 정점을 더 세밀하게 나누면 좀 더 선명한 표현이 가능하지만 속도가 현저히 느려짐
노멀 매핑이란?
- 이 노멀 벡터들로 이루어진 노멀 맵을 만들어서 노멀값을 저장하겠다는 의미
- 그리고 이 노멀 맵을 텍스쳐에 매핑하는게 노멀 매핑임
- 노멀 텍스쳐는 대부분 이렇게 청색 빛을 띠는데 왜 청색빛일까?
- 텍스쳐 자체가 이미지 파일이고 RGB로 이루어진 데이터이기 때문에
- XYZ에서 Z가 RGB의 BLUE와 대응되는 것
탄젠트 스페이스란?
- 노멀 맵은 오브젝트기준의 좌표계 (로컬)을 사용하지 않음
- 왜 별도의 좌표를 활용할까?
- 물체가 움직이지 않고 고정이면 로컬을 사용해도 상관없음
- 근데 텍스쳐가 로컬기준으로도 변화가 일어난다
- 검을 휘두르거나 이동하는 모션 등 원본 자체가 계속 변화가 일어난다는 것
- 그래서 하나의 상태에 대해 노멀을 지정하면 다른 상태에서 어색해보인다
- 그래서 노멀 자체가 별도의 좌표를 가지고 있는데 이 좌표계를 탄젠트 스페이스라고 한다
탄젠트 좌표계는 T(Tangent), B(Binormal), N(Normal)로 이루어져 있다.
T 는 X와 대응되고, B는 Y와 대응되고, N은 Z와 대응된다.
예제 코드는 뷰스페이스 기준으로 사용하므로, 탄젠트 스페이스에서 뷰 스페이스로 변환해줘야 한다
(픽셀마다 자기 자신의 탄젠트 스페이스를 가지고 있음)
좌표계 간 변환은 아래 링크에 있다.
https://dev-treadmill.tistory.com/110
10. 좌표계 변환 행렬
우리가 x, y라고 하는 것은 사실 해당 좌표계(A 좌표계)의 기저 벡터 u1, v2에 각각 x성분, y 성분을 곱한 것이다. 즉, (x, y) = (x * u1) + (y * v1)이라고 볼 수 있다. *기저 벡터 u1, v1은 그 좌표계의 x방향, y
dev-treadmill.tistory.com
VS_OUT VS_Main(VS_IN input)
{
VS_OUT output = (VS_OUT)0;
// input.pos, 1 에서 1이 있는 이유는 좌표이기 때문
// 1이 아니라 0이면 방향만 추출
output.pos = mul(float4(input.pos, 1.f), g_matWVP);
output.uv = input.uv;
output.viewPos = mul(float4(input.pos, 1.f), g_matWV).xyz;
output.viewNormal = normalize(mul(float4(input.normal, 0.f), g_matWV).xyz);
output.viewTangent = normalize(mul(float4(input.tangent, 0.f), g_matWV).xyz);
output.viewBinormal = normalize(cross(output.viewTangent, output.viewNormal));
return output;
}
- 버텍스 쉐이더에서 탄젠트와 바이노멀을 구해준다
- 기존의 노멀 벡터를 구한 것처럼 로컬 좌표에서 뷰 좌표로 변경해서 픽셀 쉐이더로 넘겨주는 것
- Binormal은 Normal과 Tanget의 외적을 계산해서 구할 수 있다.
float3 viewNormal = input.viewNormal;
if (g_tex_on_1 == 0)
{
// [0~255] 범위에서 [0~1]로 변환
float3 tangentSpaceNormal = g_tex_1.Sample(g_sam_0, input.uv).xyz;
// [0~1]을 [-1~1] 범위로 변환
tangentSpaceNormal = (tangentSpaceNormal - 0.5f) * 2.f;
// 좌표계 변환 행렬 계산
float3x3 matTBN = { input.viewTangent, input.viewBinormal, input.viewNormal };
viewNormal = normalize(mul(tangentSpaceNormal, matTBN));
}
- RGB값은 0~255로 이루어져 있으므로 이 값을 단위벡터로 바꿔줘야 한다 (-1~1)
- 그 단위벡터를 좌표계 변환 행렬로 View Space 기준으로 변환해준다.
노멀 매핑 적용 후의 텍스쳐