Normal mapping

ㅋㅋ·2022년 7월 25일
0

DirectX12강의

목록 보기
24/39

Normal mapping (bump mapping)

rasterizer 단계에서 정점과 정점 사이를 보간할 때 텍스쳐가 밋밋하게 보이는 단점이 있음

이를 방지하려면 정점 개수를 늘리면 되지만, 그렇게 되면 성능이 크게 떨어질 수 있음

color 텍스쳐의 uv 좌표에 해당하는 normal 벡터들을 다른 텍스쳐로 저장

raterizer 때 해당 color와 대응하는 normal 벡터를 이용하여 빛을 계산하여 음영을 나타냄

노말맵 텍스쳐가 대부분 파란색인 이유

=> 노말맵은 물체의 접하는 면을 기준으로 하는 좌표계(tangent space) 사용

=> x,y,z = T, B, N

=> 접하는 면을 만드는 T와 B 벡터는 특정 공식을 이용하여 도출

=> T와 B에 직각인 N을 기저로 함

=> 벡터 값들을 rgb로 나타낼 때 b값이 크기 때문


TS -> VS
RGB 0 ~ 255 데이터들을 방향 벡터로 만들기 위해 -1.0 ~ 1.0으로 변환

TBN을 기저로하는 좌표계를 XYZ로 하는 좌표계로 회전 변환 행렬 사용하여 좌표 추출


쉐이더 파일에서는 널 체크 불가능

=>

사용 여부를 데이터로 넘겨줌

cbuffer MATERIAL_PARAMS : register(b2)
{
    ...
    
    int     g_text_on_0;
    int     g_text_on_1;
    int     g_text_on_2;
    int     g_text_on_3;
    int     g_text_on_4;
};

material 파라미터에 texture 사용 여부 데이터 추가


struct VS_IN
{
    float3 pos : POSITION;
    float2 uv : TEXCOORD;
    float3 normal : NORMAL;
    float3 tangent : TANGENT;
};

struct VS_OUT
{
    float4 pos : SV_Position;
    float2 uv : TEXCOORD;
    float3 viewPos : POSITION;
    float3 viewNormal : NORMAL;
    float3 viewTangent : TANGENT;
    float3 viewBinormal : BINORMAL;
};

vertex shader 입력 데이터에 tangent 추가

출력 데이터에 tangent와 binormal 벡터 추가


VS_OUT VS_Main(VS_IN input)
{
    ...
    
    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;
}

vertex shader에서 tangent와 binormal 벡터를 구하도록 구현

binormal을 구할 때 벡터 순서에 따라 방향이 바뀜을 주의


float4 PS_Main(VS_OUT input) : SV_Target
{
    float4 color = float4(1.f, 1.f, 1.f, 1.f);
    if (g_tex_on_0)
    {
        color = g_tex_0.Sample(g_sam_0, input.uv);
    }

    float3 viewNormal = input.viewNormal;
    if (g_tex_on_1)
    {
        float3 tangentSpaceNormal = g_tex_1.Sample(g_sam_0, input.uv).xyz;
        tangentSpaceNormal = (tangentSpaceNormal - 0.5f) * 2.f;
        float3x3 matTBN = { input.viewTangent, input.viewBinormal, input.viewNormal };
        viewNormal = normalize(mul(tangentSpaceNormal, matTBN));
    }

    ...
}

pixel shader에서 텍스쳐 사용 유무 데이터를 통하여 텍스쳐를 덮어쓰도록 구현

샘플러를 통하여 샘플링 시 데이터 값이 0.0 ~ 1.0 사이 값으로 나옴

해당 값을 방향 벡터로 사용하기 위하여

-1 ~ 1 사이로 나오도록 조정하여 tangentSpaceNormal 대입

해당 방향 벡터를 변환 행렬로 곱하여 view space로 좌표계 변환

0개의 댓글