立方体に法線ベクトルと色を設定する

DirectX10 で立方体に法線ベクトルと色を設定して、光源で照らして回転しながら描画します。
LIGHTWAVE などのツールを使って、ポリゴンに色を設定したモデルは、一般的にこの形式で作成されます。

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

プロジェクトの説明

  1. DirectX Sample Browser で EmptyProject10 のプロジェクトを作成して下さい。
    EmptyProject10 のプロジェクトをコンパイルして、空のウインドウが表示される事を確かめて下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
  2. EmptyProject10.cpp を修正して立方体に法線ベクトルと色を設定して、回転しながら描画します。
    今回のプログラムは 立方体を回転しながら描画する立方体を光源で照らして描画する の組み合わせです。
    プログラムにも慣れてきた頃だと思うので、説明を参照しながら各自で作成して下さい。
    完成したプログラムをコピー&ペーストするのは誰でも出来ますが、自分で組むとなると意外と難しいものです。
  3. EmptyProject10.cpp を修正します。
    VER_N は頂点フォーマットを定義する配列 vertices[] の大きさです。
    IDX_N は頂点フォーマットの index を定義する配列 indices[] の大きさです。
    SimpleVertex は頂点フォーマットの形式で、三次元座標と法線ベクトルと面の色を定義します。
    立方体の6個の面(矩形)と法線ベクトルと各面の色を定義します。
    indices[] に vertices[] の頂点番号を設定して、立方体を定義します。
    各面は二個の三角形(TRIANGLELIST)を組み合わせて定義します。
    // Vertex(頂点座標) の定義
    #define VER_N   24
    #define IDX_N   36
    
    struct SimpleVertex
    {
        D3DXVECTOR3 Pos;  
        D3DXVECTOR3 Normal; 
        D3DXVECTOR4 Color; 
    };
    SimpleVertex vertices[VER_N] =
    {
        { D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ) },   //上面 白
        { D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ) },
                :
                :
        { D3DXVECTOR3(  1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ) },
        { D3DXVECTOR3( -1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ) },
    };
    
    DWORD indices[IDX_N] =
    {
        3,1,0,
          :
          :
        23,20,22
    };
    
  4. g_pLayout は頂点座標の Layout を設定する領域です。
    g_pVertexBuffer は頂点データを格納する VertexBuffer です。
    g_pIndexBuffer は頂点データの Index を格納する VertexBuffer です。
    g_pEffect は Shader の Object です。
    Shader の説明は 立方体を光源で照らして描画する を参照して下さい。
    g_World はワールド座標の変換行列です。
    g_View はビュー座標の変換行列です。
    g_Projection はプロジェクションの変換行列です。
    ID3D10InputLayout*          g_pLayout = NULL;
    ID3D10Buffer*               g_pVertexBuffer = NULL;
    ID3D10Buffer*               g_pIndexBuffer = NULL;
    ID3D10Effect*               g_pEffect = NULL;
    ID3D10EffectTechnique*      g_pRender = NULL;
    ID3D10EffectMatrixVariable* g_pWorldVariable = NULL;
    ID3D10EffectMatrixVariable* g_pViewVariable = NULL;
    ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL;
    D3DXMATRIX                  g_World;
    D3DXMATRIX                  g_View;
    D3DXMATRIX                  g_Projection;
    
  5. DirectX の主要な処理は CALLBACK 関数で行います。
    OnD3D10CreateDevice() はデバイスを生成するときに呼ばれます。
    D3DX10CreateEffectFromFile() で BoxCol.fx を入力して Shader を作成します。
    g_pRender, g_pWorldVariable, g_pViewVariable, g_pProjectionVariable を設定します。
    "Render","World","View","Projection" は Shader の中で定義します。
    続いて input layout を設定します。
    今回の頂点データは、三次元座標と法線ベクトルと面の色を定義しています。
    vertices[VER_N] で定義した頂点座標を VertexBuffer を取得して格納します。
    indices[IDX_N] で定義した index を VertexBuffer に格納します。
    立方体の各面は、二個の三角形を組み合わせた TRIANGLELIST で定義しています。
    g_World, g_View, g_Projection にレンダリング環境の初期値を設定します。
    HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
                                          void* pUserContext )
    {
        HRESULT hr = S_OK;
            :
            :
        // Define the input layout
        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]);
            :
            :
    
  6. OnD3D10FrameRender() は Rendering を行う CALLBACK 関数です。
    fTime の値でY軸を中心に World 座標を回転しながら描画します。
    Shader に g_pWorldVariable, g_pViewVariable, g_pProjectionVariable を設定して描画します。
    void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
    {
        // Update our time
        D3DXMatrixRotationY( &g_World, (float)fTime/2.0f );
            :
            :
        // Update variables
        g_pWorldVariable->SetMatrix( (float*)&g_World );
        g_pViewVariable->SetMatrix( (float*)&g_View );
        g_pProjectionVariable->SetMatrix( (float*)&g_Projection );
            :
            :
    
  7. OnD3D10DestroyDevice() では取得した Object を開放して下さい。
  8. "POSITION", "NORMAL", "COLOR" で定義されたモデルを、光源を設定して描画する Shader(BoxCol.fx) です。
    //--------------------------------------------------------------------------------------
    // File: Main.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() ) );
        }
    }
    

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