コーンを描画する

コーンを描画する

DXUT を使わずに CreateCylinder() でコーンのメッシュを生成して描画します。

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

プロジェクトの説明

  1. メッシュを生成する関数は DXUTShapes.cpp, DXUTShapes.h で定義されています。
    DXUT を組み込むとプロジェクトが大きくなるので、その中からコーンを生成する関数だけを抜き出してみました。
    最も苦労したのが、DXUT を使わずに ID3DX10Mesh* を描画する方法です。
    メッシュの描画には ID3D10RenderTargetView と ID3D10DepthStencilView を使うらしく、その生成が課題でした。
    DXUT を組み込んだメッシュの描画は ティーポットを回転しながら描画する を参照して下さい。
  2. プロジェクトの作成方法は 空のプロジェクトから構築する を参照して下さい。
    プロジェクトのフォルダーに次のファイルを格納して下さい。
    directx.ico はその辺に転がっているのを拾ってきて下さい。
    ファイル名 説明
    EmptyCone.zip 圧縮ファイル
  3. ソリューションエクスプローラのソースファイルを選択して[プロジェクト][既存項目の追加]から次のファイルを追加します。
    ・Main.cpp
    ・Main.rc
    [プロジェクト/Main のプロパティ/構成プロパティ/文字セット]から「Unicode文字セットを使用する」を選択します。
    コンパイル&実行で、コーンが回転しながら描画されます。
  4. メッシュを描画するプログラムファイル(Main.cpp)です。
    ライブラリは #pragma を使って取り込んでいます。
    VERTEX では頂点座標と法線ベクトルを定義します.
    #include <windows.h>
    #include <d3d10.h>
    #include <d3dx10.h>
    
    #pragma once
    #pragma comment(lib,"d3d10.lib")
    #pragma comment(lib,"d3dx10d.lib")
    
    #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
    
    //--------------------------------------------------------------------------------------
    // Structures
    //--------------------------------------------------------------------------------------
    struct VERTEX
    {
        D3DXVECTOR3 pos;
        D3DXVECTOR3 norm;
    };
    
    static 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 },
    };
    
  5. g_pMesh がメッシュを格納する領域です。
    メッシュの描画には g_pRenderTargetView と g_pDepthStencilView が必要です。
    ステンシルバッファは、描画の際に色を画面に表示するかしないかを決める「マスク」の役目を成します。
    これはポリゴンの前後関係を保持するZバッファよりももっと直接的な作用です。
    マスクですから「描画したくない部分」を明確に定義できます。
    // Global Variables
    HINSTANCE                   g_hInst = NULL;
    HWND                        g_hWnd = NULL;
    ID3DX10Mesh*                g_pMesh = NULL;
    
    D3D10_DRIVER_TYPE           g_driverType = D3D10_DRIVER_TYPE_NULL;
    ID3D10Device*               g_pd3dDevice = NULL;
    IDXGISwapChain*             g_pSwapChain = NULL;
    ID3D10RenderTargetView*     g_pRenderTargetView = NULL;
    ID3D10Texture2D*            g_pDepthStencil = NULL;
    ID3D10DepthStencilView*     g_pDepthStencilView = NULL;
    ID3D10Effect*               g_pEffect = NULL;
    ID3D10EffectTechnique*      g_pTechniqueRender = NULL;
    ID3D10InputLayout*          g_pVertexLayout = NULL;
    
    ID3D10EffectMatrixVariable* g_pWorldVariable = NULL;
    ID3D10EffectMatrixVariable* g_pViewVariable = NULL;
    ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL;
    ID3D10EffectVectorVariable* g_pColorVariable = NULL;
    
    D3DXMATRIX                  g_World;
    D3DXMATRIX                  g_View;
    D3DXMATRIX                  g_Projection;
    D3DXVECTOR4                 g_Colors = D3DXVECTOR4( 1.0f, 1.0f, 0.2f, 1.0f );
    
  6. InitDevice() で Direct 3D の Device と swap chain を設定します。
    g_pd3dDevice に Direct 3D の Device を取得します。
    // Create a render target view から g_pRenderTargetView を生成しています。
    // Create depth stencil texture から g_pDepthStencilView を生成しています。
    L"Normal.fx" を入力して Shader を作成します。
    "Render", "World", "View", "Projection", "Color" を設定します。
    layout で頂点座標と色を設定します。
    CreateCylinder( g_pd3dDevice, 1.0f, 0.0f, 2.0f, 20, 20, &g_pMesh ); でコーンを生成します。
    // Create Direct3D device and swap chain
    HRESULT InitDevice()
    {
        HRESULT hr = S_OK;
            ・・・
        for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
        {
            g_driverType = driverTypes[driverTypeIndex];
            hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags,
    			D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice );
            if( SUCCEEDED( hr ) )	break;
        }
        if( FAILED( hr ) )	return hr;
    
        // Create a render target view
        ID3D10Texture2D* pBuffer;
        hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), ( LPVOID* )&pBuffer );
        if( FAILED( hr ) )	return hr;
    
        hr = g_pd3dDevice->CreateRenderTargetView( pBuffer, NULL, &g_pRenderTargetView );
        pBuffer->Release();
        if( FAILED( hr ) )	return hr;
    
        // Create depth stencil texture
        D3D10_TEXTURE2D_DESC descDepth;
            ・・・
        hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );
        if( FAILED( hr ) )	return hr;
    
        g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView );
            ・・・
        // Create the effect
        DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
        hr = D3DX10CreateEffectFromFile( L"Normal.fx", NULL, NULL, "fx_4_0",
        	dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL );
            ・・・
        // Obtain the techniques
        g_pTechniqueRender = g_pEffect->GetTechniqueByName( "Render" );
    
        // Obtain the variables
        g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix();
        g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix();
        g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix();
        g_pColorVariable = g_pEffect->GetVariableByName( "Color" )->AsVector();
            ・・・
        // Create the input Layout
        D3D10_PASS_DESC PassDesc;
        g_pTechniqueRender->GetPassByIndex( 0 )->GetDesc( &PassDesc );
        hr = g_pd3dDevice->CreateInputLayout( Layout, numElements, PassDesc.pIAInputSignature,
    		PassDesc.IAInputSignatureSize, &g_pVertexLayout );
        if( FAILED( hr ) )	return hr;
    
        // Set the input Layout
        g_pd3dDevice->IASetInputLayout( g_pVertexLayout );
    
        // Initialize the world matrices
        D3DXMatrixIdentity( &g_World );
    
        // Initialize the view matrix
        D3DXVECTOR3 Eye( 0.0f, 4.0f, -10.0f );
        D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f );
        D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );
        D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up );
    
        // Initialize the projection matrix
        D3DXMatrixPerspectiveFovLH( &g_Projection, ( float )D3DX_PI * 0.25f,
        	width / ( FLOAT )height, 0.1f, 100.0f );
        CreateCylinder( g_pd3dDevice, 1.0f, 0.0f, 2.0f, 20, 20, &g_pMesh );
    
        return TRUE;
    }
    
  7. メッシュを描画する Render() 関数です。
    D3DXMatrixRotationY() でY軸を中心に回転します。
    g_pd3dDevice->ClearRenderTargetView() で g_pRenderTargetView を設定します。
    g_pd3dDevice->ClearDepthStencilView() で g_pDepthStencilView を設定します。
    g_pMesh->DrawSubset(s) でポリゴンを描画します。
    // Render a frame
    void Render()
    {
        // Update our time
        static float t = 0.0f;
        if( g_driverType == D3D10_DRIVER_TYPE_REFERENCE )
        {   t += ( float )D3DX_PI * 0.0125f;  }
        else
        {   static DWORD dwTimeStart = 0;
            DWORD dwTimeCur = GetTickCount();
            if( dwTimeStart == 0 )  dwTimeStart = dwTimeCur;
            t = ( dwTimeCur - dwTimeStart ) / 1000.0f;
        }
    
        // Rotate cube around the origin
        D3DXMatrixRotationY( &g_World, t );
    
        // Clear the back buffer
        float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
        g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
    
        // Clear the depth buffer to 1.0 (max depth)
        g_pd3dDevice->ClearDepthStencilView( g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 );
    
        // Update matrix variables
        g_pWorldVariable->SetMatrix( ( float* )&g_World );
        g_pViewVariable->SetMatrix( ( float* )&g_View );
        g_pProjectionVariable->SetMatrix( ( float* )&g_Projection );
        g_pColorVariable->SetFloatVector( (float*)&g_Colors );
    
        D3D10_TECHNIQUE_DESC techDesc;
        g_pTechniqueRender->GetDesc( &techDesc );
        UINT NumSubsets;
        g_pMesh->GetAttributeTable( NULL, &NumSubsets );
    
        for( UINT p = 0; p < techDesc.Passes; p++ )
        {   g_pTechniqueRender->GetPassByIndex( p )->Apply( 0 );
            for( UINT s = 0; s < NumSubsets; s++ )
            {   g_pMesh->DrawSubset( s );  }
        }
    
        // Present our back buffer to our front buffer
        g_pSwapChain->Present( 0, 0 );
    }
    
  8. 「//☆+++ Mesh を生成する」以降が DXUTShapes.cpp から抜き出した関数です。
    CreateCylinder( ) がコーンを生成する関数です。
    //--------------------------------------------------------------------------------------
    //☆+++ Mesh を生成する
    //--------------------------------------------------------------------------------------
    static inline void sincosf( float angle, float* psin, float* pcos )
    {
            ・・・
    //----------------------------------------------------------------------------
    // DXUTCreateCylinder - create a cylinder mesh
    //----------------------------------------------------------------------------
    static HRESULT CreateCylinder( ID3D10Device* pDevice, float fRadius1, float fRadius2, float fLength,
            UINT uSlices, UINT uStacks, ID3DX10Mesh** ppMesh )
    {
            ・・・
    

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