• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

Direct3D11 공부 43일차(Projector)

05 Aug 2021

Reading time ~1 minute

Projector

그림자를 만들기 위해서 투영을 이해해야 한다.

일반적인 Texture를 그리는 방식은 그리려는 물체에 UV를 씌우는 빙식이지만, Projection Texture는 그렇게 하지 않는다.

일반적으로 불체에 Texture를 그리기 위해선 VS에서 WVP 변환을 하고 WVP변환한 Position값을 SV_Position시맨틱에 의해 PS로 return 한다. 그리고 Viewport에 의해 2D로 변환하기 위해 NDC공간으로 바뀌는 절차를 거친다.

하지만, 투영 텍스처는 WVP변환을 해서 3D에서 2D로 준비가 완료된 상태에서 레스터라이저를 통해 2D로 투영된다.(Viewport는 거치치 않는다.)

Shader

00_Light.fx
struct ProjectorDesc
{
    matrix View;
    matrix Projection;
    
    float4 Color;
};

cbuffer CB_Projector
{
    ProjectorDesc Projector;
};

void VS_Projector(inout float4 wvp, float4 oPosition)
{
    wvp = WorldPosition(oPosition);
    wvp = mul(wvp, Projector.View);
    wvp = mul(wvp, Projector.Projection);
}

void PS_Projector(inout float4 color, float4 wvp)
{
    float3 uvw = 0;
    
    uvw.x = wvp.x / wvp.w * 0.5f + 0.5f;
    uvw.y = -wvp.y / wvp.w * 0.5f + 0.5f;
    uvw.z = wvp.z / wvp.w;
    
    [flatten]
    if (saturate(uvw.x) == uvw.x && saturate(uvw.y) == uvw.y && saturate(uvw.z) == uvw.z)
    {
        float4 map = ProjectorMap.Sample(LinearSampler, uvw.xy);
        
        map.rgb *= Projector.Color.rgb;
        color = lerp(color, map, map.a);
    }
}

위에서 말한 것처럼 받은 위치를 통해서 W(world)V(view)P(projection)행렬을 구해준다.

그리고 구한 wvp는 -1~1의 값이기 때문에 그 값을 ndc로 변환하기 위해 0~1의 값으로 변환해준다.

111_Projection.fx
#include "00_Global.fx"
#include "00_Light.fx"
#include "00_Render.fx"

MeshOutput VS_Mesh_Projector(VertexMesh input)
{
    MeshOutput output = VS_Mesh(input);
    VS_Projector(output.wvpPosition_Sub, input.Position);

    return output;
}

MeshOutput VS_Model_Projector(VertexModel input)
{
    MeshOutput output = VS_Model(input);
    VS_Projector(output.wvpPosition_Sub, input.Position);

    return output;
}

MeshOutput VS_Animation_Projector(VertexModel input)
{
    MeshOutput output = VS_Animation(input);
    VS_Projector(output.wvpPosition_Sub, input.Position);

    return output;
}

float4 PS(MeshOutput input) : SV_Target
{
    float4 color = PS_AllLight(input);
    PS_Projector(color, input.wvpPosition_Sub);
    
    return color;
}

technique11 T0
{ 
    // Render
    P_VP(P1, VS_Mesh_Projector, PS)
    P_VP(P2, VS_Model_Projector, PS)
    P_VP(P3, VS_Animation_Projector, PS)
}

이 것을 활용해서 쉐이더를 만들어 주자



DirectX Share Tweet +1