헛둘이 2023. 1. 27. 12:03

노멀 매핑 적용 전의 텍스쳐

- 한 면에 적용되는 네 점의 노멀 벡터를 모두 같게 세팅해줬는데, 그러다보니

- 그 면에 보여지는 무늬가 심심해진다

 

노멀 벡터란?

- 한 점에 접하는 평면과 수직인 벡터

 

 

- 정점을 더 세밀하게 나누면 좀 더 선명한 표현이 가능하지만 속도가 현저히 느려짐

 

노멀 매핑이란?

- 이 노멀 벡터들로 이루어진 노멀 맵을 만들어서 노멀값을 저장하겠다는 의미

- 그리고 이 노멀 맵을 텍스쳐에 매핑하는게 노멀 매핑임

 

노멀 텍스쳐

- 노멀 텍스쳐는 대부분 이렇게 청색 빛을 띠는데 왜 청색빛일까?

- 텍스쳐 자체가 이미지 파일이고 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 기준으로 변환해준다.

 

 

 

노멀 매핑 적용 후의 텍스쳐