Color sdkmesh を描画

Color sdkmesh を描画

色を設定した SDK Mesh を描画します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. X-FILE に代わる物として DirectX10 から登場したの DXUT メッシュ形式(.sdkmesh)です。
    今回は「頂点座標と法線ベクトルと色」で構成されるメシュを描画します。
    sdkmesh のモデルは DirectX SDK (June 2010) の下記のフォルダーに格納されているので、適当に選んで下さい。
    C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\Media\
    また meshconvert を使って X-FILE を DXUT メッシュ形式に変換することが出来ます。
    meshconvert の説明は X-FILE を sdkmesh にコンバートして描画 を参照して下さい。
  2. DirectX10 のプロジェクトなので MultiMon10 を使うことにします。
    以前に作成した .sdkmesh を描画 を元に修正するので準備して下さい。
    Shader は、このページの後部に掲載します。
  3. g_Mesh が DXUT メッシュです。
    DXUTCreateTeapot() で生成したときは ID3DX10Mesh* でしたが .sdkmesh では CDXUTSDKMesh を使っています。
    CDXUTSDKMesh は SDK Mesh の API をラップした便利なクラスです。
    g_Camera がモデルを回転する CModelViewerCamera です。
    ID3D10Effect*                   g_pEffect = NULL;
    ID3D10InputLayout*              g_pLayout = NULL;
    ID3D10EffectTechnique*          g_pRender = NULL;
    CDXUTSDKMesh                    g_Mesh;
    ID3D10EffectMatrixVariable*     g_pWorldVariable = NULL;
    ID3D10EffectMatrixVariable*     g_pViewVariable = NULL;
    ID3D10EffectMatrixVariable*     g_pProjectionVariable = NULL;
    CModelViewerCamera              g_Camera;
    
  4. OnD3D10FrameRender() の修正は、色を設定する g_pColorVariable を削除するだけです。
    タイマーで World を自動的に回転した値と g_Camera.GetWorld を掛け合わせます。
    g_Camera で回転すると g_Camera 中の World 座標と View 座標が回転します。
    g_Camera の領域から g_pWorld, g_View, g_Projection を Shader に設定して描画します。
    CDXUTSDKMesh を使うと描画は簡単で g_Mesh.Render() の一行だけです。
    //g_pColorVariable = g_pEffect->GetVariableByName( "Color" )->AsVector();
  5. OnD3D10CreateDevice() はデバイスを生成するときに呼ばれます。
    Shader は頂点座標と法線ベクトルと色で構成されるモデルを描画するものを使用します。
    g_Mesh.Create() で .sdkmesh をロードします。
    CDXUTSDKMesh を使うとロードも簡単で g_Mesh.Create() の一行で、マテリアルからテクスチャまで全て面倒を見てくれます。
    このプログラムでは "C:\\DATA\\Sdkmesh" のフォルダーに格納されている "bigship1.sdkmesh" をロードしています。
    モデルは C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\Media\ から取得して下さい。
    HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice,
                 const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
    {
        HRESULT hr;
            :
            :
        V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"Color.fx" ) );
        DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
    
        V_RETURN( D3DX10CreateEffectFromFile( str, NULL, NULL, "fx_4_0",
            dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ) );
    
        // Obtain the technique
        g_pRender = g_pEffect->GetTechniqueByName( "Render" );
        g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix();
        g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix();
        g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix();
    
        // Define the input layout
        const D3D10_INPUT_ELEMENT_DESC layout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
        };
        UINT numElements = sizeof( layout ) / sizeof( layout[0] );
    
        // Create the input layout
        D3D10_PASS_DESC PassDesc;
        g_pRender->GetPassByIndex( 0 )->GetDesc( &PassDesc );
        V_RETURN( pd3dDevice->CreateInputLayout( layout, numElements,
            PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pLayout ) );
    
        // Set the input layout
        pd3dDevice->IASetInputLayout( g_pLayout );
    
        // Load the mesh
        SetCurrentDirectory(L"C:\\DATA\\Sdkmesh");
        V_RETURN( g_Mesh.Create( pd3dDevice, L"bigship1.sdkmesh", true ) );
            :
            :
    
  6. 頂点座標と法線ベクトルと色で構成されるモデルを描画する "Color.fx" です。
    //--------------------------------------------------------------------------------------
    // File: Color.fx    頂点座標+法線ベクトル+色       前田 稔
    //--------------------------------------------------------------------------------------
    
    //--------------------------------------------------------------------------------------
    // Constant Buffer Variables
    //--------------------------------------------------------------------------------------
    matrix World;
    matrix View;
    matrix Projection;
    
    //--------------------------------------------------------------------------------------
    // Global variables
    //--------------------------------------------------------------------------------------
    cbuffer cb0
    {
        float3 g_vLightDir = float3(-0.707,0.707,-0.5); // 光源の座標
    };
    
    //--------------------------------------------------------------------------------------
    // Vertex shader output structure
    //--------------------------------------------------------------------------------------
    struct VS_INPUT
    {
        float4 Pos : POSITION;
        float4 Norm : NORMAL;
        float4 Color : COLOR0;
    };
    
    struct PS_INPUT
    {
        float4 Pos : SV_POSITION;
        float4 Norm : NORMAL;
        float4 Color : COLOR0;
    };
    
    //--------------------------------------------------------------------------------------
    // Vertex Shader
    //--------------------------------------------------------------------------------------
    PS_INPUT VS( VS_INPUT input )
    {
        PS_INPUT output = (PS_INPUT)0;
        output.Pos = mul( input.Pos, World );
        output.Pos = mul( output.Pos, View );
        output.Pos = mul( output.Pos, Projection );
        output.Norm = mul( input.Norm, World );
        output.Color = input.Color;
    
        return output;
    }
    
    //--------------------------------------------------------------------------------------
    float4 PS( PS_INPUT input ) : SV_Target
    { 
        return input.Color * saturate( dot( normalize(input.Norm), g_vLightDir ) );
    }
    
    //--------------------------------------------------------------------------------------
    technique10 Render
    {
        pass P0
        {
            SetVertexShader( CompileShader( vs_4_0, VS() ) );
            SetGeometryShader( NULL );
            SetPixelShader( CompileShader( ps_4_0, PS() ) );
        }
    }
    
  7. "carinnards.sdkmesh" 以外にも幾つかのモデルが格納されているので試して下さい。
    このプログラムで正常に描画できるのは、頂点座標と法線ベクトルと色で構成されたモデルです。

【NOTE】

  1. Samples\Media\ のフォルダーに格納されているモデルを適当に選んで試してみて下さい。
    「頂点座標と法線ベクトルと色」以外で構成されるモデルでも、エラーにならずに描画されるでしょう。
    モデルによっては、本来の姿よりカラフルで綺麗に描画されるかも知れません。 (^_^;)
  2. layout では Shader に渡す頂点データの形式を定義します。
        const D3D10_INPUT_ELEMENT_DESC layout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
        };
        
    VS_INPUT でこれを受ける形式(構造体)を定義します。
    layout と VS_INPUT の形式は一致していなければなりません。
        struct VS_INPUT
        {
            float4 Pos : POSITION;
            float4 Norm : NORMAL;
            float4 Color : COLOR0;
        };
        
  3. この後の説明は、私の推測で正しいとは限らないので念のため。
    VS_INPUT には頂点を構成する構造体の先頭ポインタが渡されます。
    "teapot.sdkmesh" のように「頂点座標と法線ベクトル」で構成されるモデルには、色情報がありません。
    色情報の場所には、パディングまたは次の頂点データが格納されています。
    また「頂点座標と法線ベクトルとテクスチャ」で構成されるモデルでは、COLOR の場所にはテクスチャ座標が格納されています。
    Shader 側では COLOR の場所に格納されているものを色情報として処理するので、思わぬカラフルな描画を楽しむことが出来ます。
    Samples\Media\ から選んだモデルの中に、色情報と誤解するようなカラフルなモデルが存在するようです。

超初心者のプログラム入門(DirectX10 game program)