キューブにテクスチャを貼り付ける

キューブにテクスチャを貼り付ける

キューブにテクスチャを貼り付けて色を変えながら描画します。

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

プロジェクトの説明

  1. プロジェクトの作成方法は 空のプロジェクトから構築する を参照して下さい。
    プロジェクトのフォルダーに次のファイルを格納して下さい。
    ファイル名 説明
    EmptyTex.zip 圧縮ファイル
    今回はリソースファイルもアイコンも削除して、シンプルなプロジェクトを作成します。
    プロジェクトに必要なファイルは、次の4個だけです。
  2. ソリューションエクスプローラのソースファイルを選択して[プロジェクト][既存項目の追加]から Main.cpp を追加します。
    [プロジェクト/Main のプロパティ/構成プロパティ/文字セット]から「Unicode文字セットを使用する」を選択します。
    コンパイル&実行で、テクスチャを貼り付けたキューブが回転しながら色を変えて描画されます。
  3. キューブを描画するプログラムファイル(Main.cpp)です。
    ライブラリは #pragma を使って取り込んでいます。
    SimpleVertex では頂点座標とテクスチャ座標を定義します.
    g_pTextureRV に貼り付けるテクスチャ(画像)を設定します。
    /*****************************************/
    /*  DirectX10 Texture Maping    前田 稔  */
    /*****************************************/
    #include <windows.h>
    #include <d3d10.h>
    #include <d3dx10.h>
    
    #pragma once
    #pragma comment(lib,"d3d10.lib")
    #pragma comment(lib,"d3dx10.lib")
    
    // Structures
    struct SimpleVertex
    {
        D3DXVECTOR3 Pos; 
        D3DXVECTOR2 Tex; 
    };
    
    // Global Variables
    HINSTANCE                           g_hInst = NULL;
    HWND                                g_hWnd = NULL;
    D3D10_DRIVER_TYPE                   g_driverType = D3D10_DRIVER_TYPE_NULL;
    ID3D10Device*                       g_pd3dDevice = NULL;
    IDXGISwapChain*                     g_pSwapChain = NULL;
    ID3D10RenderTargetView*             g_pRenderTargetView = NULL;
    ID3D10Effect*                       g_pEffect = NULL;
    ID3D10EffectTechnique*              g_pTechnique = NULL;
    ID3D10InputLayout*                  g_pVertexLayout = NULL;
    ID3D10Buffer*                       g_pVertexBuffer = NULL;
    ID3D10Buffer*                       g_pIndexBuffer = NULL;
    ID3D10ShaderResourceView*           g_pTextureRV = NULL;
    ID3D10EffectMatrixVariable*         g_pWorldVariable = NULL;
    ID3D10EffectMatrixVariable*         g_pViewVariable = NULL;
    ID3D10EffectMatrixVariable*         g_pProjectionVariable = NULL;
    ID3D10EffectVectorVariable*         g_pMeshColorVariable = NULL;
    ID3D10EffectShaderResourceVariable* g_pDiffuseVariable = NULL;
    D3DXMATRIX                          g_World;
    D3DXMATRIX                          g_View;
    D3DXMATRIX                          g_Projection;
    D3DXVECTOR4                         g_vMeshColor( 0.7f, 0.7f, 0.7f, 1.0f );
    
  4. 今回はアイコンを省略しました。
    HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
    {
        // Register class
        WNDCLASSEX wcex =
        {   sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL,
            LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW+1), NULL, L"WindowClass"
        };
            ・・・
    
  5. InitDevice() で Direct 3D の Device と swap chain を設定します。
    g_pd3dDevice に Direct 3D の Device を取得します。
    L"Tutorial07.fx" を入力して Shader を作成します。
    "Render", "World", "View", "Projection", "vMeshColor", "txDiffuse" を設定します。
    layout で頂点座標と色を設定します。
    vertices[] が頂点座標の定義で、indices[] がその Index です。
    L"c:\\data\\test\\ayu.jpg" がキューブに貼り付ける画像です。
    256ピクセル程度の大きさの適当な画像(JPEG, BMP, DDS)を調達して下さい。
    テクスチャの説明は 矩形に Texture を貼り付ける を参照して下さい。
    &g_View, &g_Projection, g_pTextureRV を設定します。
    // Create Direct3D device and swap chain
    HRESULT InitDevice()
    {
        HRESULT hr = S_OK;
            ・・・
        D3D10_DRIVER_TYPE driverTypes[] = 
        {
            D3D10_DRIVER_TYPE_HARDWARE,
            D3D10_DRIVER_TYPE_REFERENCE,
        };
        UINT numDriverTypes = sizeof(driverTypes) / sizeof(driverTypes[0]);
            ・・・
        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;
            ・・・
        hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID*)&pBuffer );
        if( FAILED(hr) )    return hr;
            ・・・
        // Create the effect
        DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
        hr = D3DX10CreateEffectFromFile( L"Tutorial07.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0,
                g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL );
            ・・・
        // Obtain the technique
        g_pTechnique = 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_pMeshColorVariable = g_pEffect->GetVariableByName( "vMeshColor" )->AsVector();
        g_pDiffuseVariable = g_pEffect->GetVariableByName( "txDiffuse" )->AsShaderResource();
    
        // Define the input layout
        D3D10_INPUT_ELEMENT_DESC layout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },  
            { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 
        };
        UINT numElements = sizeof(layout)/sizeof(layout[0]);
            ・・・
        // Create vertex buffer
        SimpleVertex vertices[] =
        {
            { D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
            { D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
            { D3DXVECTOR3(  1.0f,  1.0f,  1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
            { D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
                ・・・
            { D3DXVECTOR3( -1.0f,  1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
        };
                ・・・
        // Create index buffer
        DWORD indices[] =
        {
            3,1,0,
            2,1,3,
            ・・・
        // Load the Texture
        hr = D3DX10CreateShaderResourceViewFromFile( g_pd3dDevice, L"c:\\data\\test\\ayu.jpg",
            NULL, NULL, &g_pTextureRV, NULL );
            ・・・
        // Initialize the world matrices
        D3DXMatrixIdentity( &g_World );
    
        // Initialize the view matrix
        D3DXVECTOR3 Eye( 0.0f, 3.0f, -6.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 );
    
        // Update Variables that never change
        g_pViewVariable->SetMatrix( (float*)&g_View );
        g_pProjectionVariable->SetMatrix( (float*)&g_Projection );
        g_pDiffuseVariable->SetResource( g_pTextureRV );
    
        return S_OK;
    }
    
  6. モデルを描画する Render() 関数です。
    D3DXMatrixRotationY() でY軸を中心に自動回転しながら描画します。
    // Modify the color の行からがモデルの色を変更するソースコードです。
    // 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 );
    
        // Modify the color
        g_vMeshColor.x = ( sinf( t * 1.0f ) + 1.0f ) * 0.5f;
        g_vMeshColor.y = ( cosf( t * 3.0f ) + 1.0f ) * 0.5f;
        g_vMeshColor.z = ( sinf( t * 5.0f ) + 1.0f ) * 0.5f;
    
        // 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 );
    
        // Update variables that change once per frame
        g_pWorldVariable->SetMatrix( (float*)&g_World );
        g_pMeshColorVariable->SetFloatVector( (float*)g_vMeshColor );
    
        // Render the cube
        D3D10_TECHNIQUE_DESC techDesc;
        g_pTechnique->GetDesc( &techDesc );
        for( UINT p = 0; p < techDesc.Passes; ++p )
        {
            g_pTechnique->GetPassByIndex( p )->Apply(0);
            g_pd3dDevice->DrawIndexed( 36, 0, 0 );
        }
    
        // Present our back buffer to our front buffer
        g_pSwapChain->Present( 0, 0 );
    }
    

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