Normal Cone

コーンの座標と法線をプログラムで計算します。

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

プログラムの説明

  1. Color Cone では、着色したコーンを描画しています。
    DirectX9 で自動生成した Teapot や Torus は、頂点座標と法線ベクトルで構成されていました。
    そこで今回は、頂点座標と法線ベクトルで構成するコーンのモデルをプログラムで計算して描画します。
    また、2D描画機能は不要なので削除して、領域の名前もふさわしいものに変更します。
  2. Windows 8.1 3D のプロジェクト を参照して 3D(XAML 無し)のプロジェクトを構築して下さい。
    2D描画機能は不要なので 空プロジェクト を参考にして削除して下さい。
    この状態でコンパイルして、頂点に色を設定した立方体が回転しながら描画されることを確認して下さい。
  3. Content\ShaderStructures.h を修正します。
    頂点データの形式を「頂点座標+色」から「頂点座標+法線」にします。
    色も法線も同じ XMFLOAT3 なので、領域の名前が変わるだけです。
    また構造体の名前も、色を設定しないので VertexPositionColor から VertexPosition にします。
        /*  struct VertexPositionColor
        {
            DirectX::XMFLOAT3 pos;
            DirectX::XMFLOAT3 color;
        };
        */
        struct VertexPosition
        {
            DirectX::XMFLOAT3 pos;
            DirectX::XMFLOAT3 norm;
        };
    
  4. Content\Sample3DSceneRenderer.cpp のソースコードを修正します。
    KAKU はコーンの角の数で、19 ぐらいに設定すると角がとれてかなり滑らかになります。
    #define  KAKU  19  // (pyramid の角の数+1)
    
  5. 生成したコーンは、立方体のモデルに比べて大きいようで画面からはみ出します。
    そこでカメラを引いて大きさを調整します。
        //static const XMVECTORF32 eye = { 0.0f, 0.7f, 1.5f, 0.0f };
        static const XMVECTORF32 eye = { 0.0f, 0.7f, 4.0f, 0.0f };
    
  6. D3D11_INPUT_ELEMENT_DESC を "COLOR" から "NORMAL" に修正します。
        //{ "COLOR",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0 },
        { "NORMAL",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0 },
    
  7. モデルの座標と法線の計算です。
    「static const VertexPositionColor cubeVertices[] = { ... }」 を削除して置き換えて下さい。
    .pos がコーンの座標で .norm が法線ベクトルです。
        static VertexPosition modelVertices[KAKU * 2];
        for (int slice = 0; slice<KAKU; slice++)
        {
            float v = (float)slice / (float)(KAKU - 1);
            float theta = v * 3.14f * 2;
            modelVertices[2 * slice + 0].pos = XMFLOAT3(sinf(theta), -1.0f, cosf(theta));
            modelVertices[2 * slice + 0].norm = XMFLOAT3(sinf(theta), 1.0f, cosf(theta));
            modelVertices[2 * slice + 1].pos = XMFLOAT3(0.0f, 1.0f, 0.0f);
            modelVertices[2 * slice + 1].norm = XMFLOAT3(sinf(theta), 1.0f, cosf(theta));
        }
    
  8. 頂点 Index の定義です。
    「static const unsigned short cubeIndices [] = { ... }」 を削除して置き換えて下さい。
    三角ポリゴンを組み合わせてコーンを作成します。
        static unsigned short modelIndices[KAKU*6];
        for(int slice=0; slice<(KAKU-1); slice++)
        {   modelIndices[3*slice+0] = slice*2+0;
            modelIndices[3*slice+1] = slice*2+1;
            modelIndices[3*slice+2] = slice*2+2;
            modelIndices[3*(KAKU+slice)+0] = slice*2+3;
            modelIndices[3*(KAKU+slice)+1] = slice*2+2;
            modelIndices[3*(KAKU+slice)+2] = slice*2+1;
        }
    
  9. 領域の名前を color から norm に、cube から model に変更したので、それに伴う修正をして下さい。
    コンパイルすればエラーが指摘されているので、ソースコードを見ればすぐわかると思います。
  10. Content\ に格納されている Shader を頂点座標+法線に対応するものに書き換えます。
    SamplePixelShader.hlsl のソースコードです。
    struct PixelShaderInput
    {
        float4 pos : SV_POSITION;
        float3 norm : NORMAL;
    };
    
    float4 main(PixelShaderInput input) : SV_TARGET
    {
        float3 lightDirection = normalize(float3(1, -1, 0));
        float lightMagnitude = 0.8f * saturate(dot( input.norm, -lightDirection)) + 0.2f;
        return float4(1,1,0.2,1) * lightMagnitude;
    }
    
  11. SampleVertexShader.hlsl のソースコードです。
    cbuffer ModelViewProjectionConstantBuffer : register(b0)
    {
        matrix model;
        matrix view;
        matrix projection;
    };
    
    struct VertexShaderInput
    {
        float3 pos : POSITION;
        float3 norm : NORMAL;
    };
    
    struct VertexShaderOutput
    {
        float4 pos : SV_POSITION;
        float3 norm : NORMAL;
    };
    
    VertexShaderOutput main(VertexShaderInput input)
    {
        VertexShaderOutput output;
        float4 pos = float4(input.pos, 1.0f);
    
        // Transform the vertex position into projected space.
        pos = mul(pos, model);
        pos = mul(pos, view);
        pos = mul(pos, projection);
        output.pos = pos;
    
        float4 norm = float4(normalize(input.norm), 0.0f);
        norm = mul(norm, model);
        output.norm = normalize(norm.xyz);
        return output;
    }
    
  12. コンパイル&実行すると、ページ先頭の画像のように法線ベクトルが設定されたコーンが回転しながら描画されます。
    コーンの角の数を変更して描画してみて下さい。

超初心者のプログラム入門(DirectX Store)