マルチレンダーターゲット

DirectX SDKの「Post Process」的なものを作るために、
まずはマルチレンダーターゲットを試してみました。
1パスで同時に3つのテクスチャに描き込んでいます。

左上から通常のシーン、Normal Map(法線マップ)、Position Map(位置マップ)、
位置マップを加工した視点からの深度マップです。

サンプル

Multiple Render Targets(MRTs)のサポートを確認

  • NumberSimultaneousRtsが3以上であれば、1パスで描画するためのテクニックを選択
  • サポートしていなければ、3パスで描画
if( device.DeviceCaps.NumberSimultaneousRts >= 3 )
{
    use_pass = 1;
    use_MRTs = 3;
    technique = "render_scene";
}
else
{
    use_pass = 3;
    use_MRTs = 1;
    technique = "render_scene_3_pass";
}
scene.fx
//--------------------------------------------------------------------
//頂点シェーダ
//--------------------------------------------------------------------
void VS_RenderScene(
    float4 pos : POSITION,
    float3 normal : NORMAL,
    float2 tex : TEXCOORD0,
    out float4 out_pos : POSITION,
    out float4 out_diffuse : COLOR,
    out float2 out_tex : TEXCOORD0,
    out float3 out_normal : TEXCOORD1,
    out float4 out_view_pos : TEXCOORD2
    )
{
/*...*/
}

//--------------------------------------------------------------------
//ピクセルシェーダ
//--------------------------------------------------------------------
//1パス用
void PS_RenderScene(
    float4 diffuse : COLOR,
    float2 tex : TEXCOORD0,
    float3 normal : TEXCOORD1,
    float3 pos : TEXCOORD2,
    out float4 out_color : COLOR0,
    out float4 out_normal : COLOR1,
    out float4 out_pos : COLOR2
    )
{
/*...*/
}

//1パス目
void PS_RenderScene_Color(
    float4 diffuse : COLOR,
    float2 tex : TEXCOORD0,
    float3 normal : TEXCOORD1,
    float3 pos : TEXCOORD2,
    out float4 out_color : COLOR
    )
{
/*...*/
}

//2パス目
void PS_RenderScene_Normal(
    float4 diffuse : COLOR,
    float2 tex : TEXCOORD0,
    float3 normal : TEXCOORD1,
    float3 pos : TEXCOORD2,
    out float4 out_normal : COLOR
    )
{
/*...*/
}

//3パス目
void PS_RenderScene_Pos(
    float4 diffuse : COLOR,
    float2 tex : TEXCOORD0,
    float3 normal : TEXCOORD1,
    float3 pos : TEXCOORD2,
    out float4 out_pos : COLOR
    )
{
/*...*/
}

//--------------------------------------------------------------------
//テクニック
//--------------------------------------------------------------------
technique render_scene
{
    pass p0
    {
        VertexShader = compile vs_2_0 VS_RenderScene();
        PixelShader = compile ps_2_0 PS_RenderScene();
    }
}

technique render_scene_3_pass
{
    pass p0
    {
        VertexShader = compile vs_2_0 VS_RenderScene();
        PixelShader = compile ps_2_0 PS_RenderScene_Color();
    }

    pass p1
    {
        VertexShader = compile vs_2_0 VS_RenderScene();
        PixelShader = compile ps_2_0 PS_RenderScene_Normal();
    }

    pass p2
    {
        VertexShader = compile vs_2_0 VS_RenderScene();
        PixelShader = compile ps_2_0 PS_RenderScene_Pos();
    }
}

複数のレンダーターゲットにシーンを描画する

effect_scene.Technique = technique;
//バックバッファを取得
using( RenderTarget backbuffer = new RenderTarget( device ) )
{
    int n = effect_scene.Begin( FX.None );
    for( int pass = 0; pass < n; pass ++ )
    {
         //1パスで可能であれば3つのレンダーターゲットをセット
         //3パスの場合は1つずつセット
         SetRenderTarget( pass );

         device.Clear( ClearFlags.Target | ClearFlags.ZBuffer,
             Color.FromArgb( 0, 0, 0 ), 1.0f, 0 );
         effect_scene.BeginPass( pass );

         //シーンの描画
         mesh.DrawSubset( 0 );
                    
         effect_scene.EndPass();
    }
    effect_scene.End();

    //レンダーターゲットをバックバッファに戻す
    backbuffer.Set( device );
}