MRT

MRT 설명은 http://marupeke296.com/DXG_No50_MultiPassRendering.html 내용을 가지고 와서 정리한것이다.

MRT는 Multiple Render Target의 약자로 그래픽 카드는 여러개의 렌더타겟을 가질수 있다.
지연 렌더링을 위해서는 MRT를 이해 해야한다.

1. 렌더타겟 최대 갯수 체크

자신의 GPU가 최대 몇개의 렌더타겟을 지원하는지 체크한다.

   D3DCAPS9 Caps;
   g_pD3DDev->GetDeviceCaps( &Caps );
   DWORD RT = Caps.NumSimultaneousRTs;

2. 렌더 타겟 설정


첫번째 인자로 렌더 타겟을 지정하고, 렌더 타겟의 서피스를 넘겨준다.

HRESULT SetRenderTarget ( DWORD RenderTargetIndex, Direct3DSurface9 *pRenderTarget);

3. 렌더 타겟 생성 순서


D3DUSAGE_RENDERTARGET로 렌더타겟 텍스쳐를 만든다.
렌더타겟 텍스쳐의 표면을 얻어온다.
렌더타겟 텍스쳐의 표면으로 렌더타겟을 설정한다.

IDirect3DTexture9 *pAlphaTex = 0;
IDirect3DSurface9 *pAlphaSurf = 0;

g_pD3DDev->CreateTexture( 640, 480, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pAlphaTex, 0 );
pAlphaTex->GetSurfaceLevel( 0, &pAlphaSurf );
g_pD3DDev->SetRenderTarget( 1, pAlphaSurf );

4. 백버퍼 얻어오기


0번 인덱스에 SetRenderTarget 하기 전에 GetRenderTarget으로 기존의 서피스를 미리 구해 놓는다.

IDirect3DSurface9 *pBackBuffer = 0;
g_pD3DDev->GetRenderTarget( 0, &pBackBuffer );

5. HLSL에서 지정한 렌더타겟에 그리기


원하는 렌더타겟에 그리기 위해서는 셰이더를 이용해야 한다.
픽셀세이더에서 COLOR[n]으로 접근 한다.

렌더 타겟 0번에 그리는 경우
float4 Test_PS (float2 texCoord : TEXCOORD0) : COLOR0
{
   float outColor
   // .....
   return outColor;
}

렌더 타겟 1번에 그리는 경우
float4 Test_PS (float2 texCoord : TEXCOORD0) : COLOR1
{
   float outColor
   // .....
   return outColor;
}

렌더 타겟 0번과 1번 동시에 그리는 경우
struct OUTPUT_PS {
   float4 color0 : COLOR0;
   float4 color1 : COLOR1;
};

OutPS Test_PS( float2 texCoord : TEXCOORD0 )
{
   OutPS outColor
   // ....
   return outColor;
}

렌더 타겟 갯수에 따라 OUTPUT_PS 구조체에 color[n]을 늘리면 된다.

6. HLSL에서 MRT 예제


비행기를 RGBA 색상과 알파값으로 분리하여 별도의 텍스처에 한번에 그리고 있다.
결과를 RGBA --> 알파값으로 바꾸면서 화면에 보여준다.

//RGBAndAlphaMPR.fx
float4x4 WVP;   // WorldViewProjection Matrix
texture Tex;    // Texture
sampler2D TexSampler = sampler_state {    Texture = (Tex); };

struct OUTPUT_VS
{
    float4 pos      : POSITION;
    float2 texCoord : TEXCOORD0;
};

struct OUTPUT_PS
{
    float4 color : COLOR0;
    float4 alpha : COLOR1;
};

OUTPUT_VS SimpleVS( float4 inPos : POSITION, float2 inTexCoord : TEXCOORD0 )
{
    OUTPUT_VS outVS = (OUTPUT_VS)0;
    outVS.pos = mul( inPos, WVP );
    outVS.texCoord = inTexCoord;
    return outVS;
}

OUTPUT_PS RGBAndAlphaMPR_PS( float2 texCoord : TEXCOORD0 )
{
    OUTPUT_PS PSout = (OUTPUT_PS)0;
    PSout.color = tex2D(TexSampler, texCoord);
    PSout.alpha = PSout.color.a;
    PSout.alpha.a = 1.0f;    
    return PSout;
}

투명 텍스쳐를 처리하기 위해 렌더링 스테이트를 다음과 같이 설정한다.

//RGBAndAlphaMPR.fx
technique RGBAndAlphaMPR
{
    pass p0
    {
        //렌더링 스테이트 설정
        AlphaBlendEnable = TRUE;
        SrcBlend = SRCALPHA;
        DestBlend = INVSRCALPHA;
        ColorOp[0] = SELECTARG1;
        ColorArg1[0] = TEXTURE;
        ColorArg2[0] = DIFFUSE;
        AlphaOp[0] = SELECTARG1;
        AlphaArg1[0] = TEXTURE;
        AlphaArg2[0] = DIFFUSE;
        ColorOp[1] = DISABLE;
        AlphaOp[1] = DISABLE;

        //쉐이더
        VertexShader = compile vs_2_0 SimpleVS();
        PixelShader = compile ps_2_0 RGBAndAlphaMPR_PS();
    }
}

실행 결과 : 두개의 이미지가 교체 된다.





비쥬얼스튜디오에서 hlsl 에러 발생할때

비쥬얼스튜디오 2013에서 프로젝트에 FX 파일을 추가 후 빌드하면 다음의 에러가 발생한다.

error X3501: 'main': entrypoint not found

비쥬얼스튜디오 2012 이후 버전에서 이 에러를 없애기 위해서는 프로젝트 속성 "HLSL Compiler"에서 다음과 같이 설정 한다.

프로젝트 속성 > 구성 속성 > HLSL 컴파일러 > 일반   이동
셰이더 형식을 "효과(/fx)", 셰이더 모델을 적당한걸로 선택한다.



소스 :
main.cpp
RGBAndAlphaMPR.fx
mrt_vs2013.zip


참조 )
http://marupeke296.com/DXG_No50_MultiPassRendering.html