空から構築する

空のプロジェクトから構築して、三角形ポリゴンを表示します。
この方法を取ると、極めてシンプルなプロジェクトを構築することが出来ます。

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

プロジェクトの説明

  1. Sample Brower を使うと便利なのですが、直接関係しないファイルや余分なフォルダーが組み込まれてしまいます。
    その内これらのフォルダーやファイルでハードディスクが占有されることになりかねません。
    そこで空から構築したシンプルなプロジェクトを丸ごとコピーして、名前を変えて使用します。
    プロジェクトの作成方法は 空のプロジェクトから構築する を参照して下さい。
  2. プロジェクトのフォルダーに次のファイルを格納して下さい。
    ファイル名 説明 取得
    Main.cpp 三角ポリゴンを描画するプログラムファイル この後に掲載しています
    Tutorial02.fx 三角形を描画する Shader この後に掲載しています
    Main.rc リソースファイル この後に掲載しています
    directx.ico プログラムのアイコン そのへんに沢山転がっています
  3. ソリューションエクスプローラのソースファイルを選択して[プロジェクト][既存項目の追加]から次のファイルを追加します。
    ・Main.cpp
    ・Main.rc
  4. [プロジェクト/Main のプロパティ/構成プロパティ/文字セット]から「Unicode文字セットを使用する」を選択します。
    コンパイル&実行で、三角ポリゴンが描画されます。
  5. 三角ポリゴンを描画するプログラムファイル(Main.cpp)です。
    ライブラリは #pragma を使って取り込んでいます。
    アイコンは resource.h を使わずに、ID(L"IDI_MYICON")を直接指定しています。
    ポリゴンの描画は 三角形を表示する を参照して下さい。
    /**********************************************************/
    /*  DirectX10 Graphics   三角形ポリゴンを描画    前田 稔  */
    /**********************************************************/
    #include <windows.h>
    #include <d3d10.h>
    #include <d3dx10.h>
    
    #pragma once
    #pragma comment(lib,"d3d10.lib")
    #pragma comment(lib,"d3dx10.lib")
    
    // 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;
    
    // 頂点フォーマット
    struct SimpleVertex
    {
        D3DXVECTOR3 Pos;
    };
    
    // Function Prototype
    HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
    HRESULT InitDevice();
    void CleanupDevice();
    LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );
    void Render();
    
    //★ Win Main
    int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
    {
        if( FAILED( InitWindow( hInstance, nCmdShow ) ) )   return 0;
    
        if( FAILED( InitDevice() ) )
        {   CleanupDevice();
            return 0;
        }
    
        // Main message loop
        MSG msg = {0};
        while( WM_QUIT != msg.message )
        {   if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
            {   TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
            else
            {   Render();  }
        }
        CleanupDevice();
    
        return ( int )msg.wParam;
    }
    
    // Window の初期化
    HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
    {
        // Register class
        WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, 
                          hInstance, LoadIcon(hInstance, L"IDI_MYICON"), LoadCursor(NULL, IDC_ARROW),
                          (HBRUSH)(COLOR_WINDOW+1), NULL, L"WindowClass", LoadIcon(hInstance, L"IDI_MYICON")
                        };
        if( !RegisterClassEx( &wc ) )   return E_FAIL;
    
        // Create window
        g_hInst = hInstance;
        RECT rc = { 0, 0, 640, 480 };
        AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
        g_hWnd = CreateWindow( L"WindowClass", L"Direct3D 10 Rendering a Triangle",
                               WS_OVERLAPPEDWINDOW,
                               CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL,
                               hInstance, NULL );
        if( !g_hWnd )   return E_FAIL;
        ShowWindow( g_hWnd, nCmdShow );
    
        return S_OK;
    }
    
    // Create Direct3D device
    HRESULT InitDevice()
    {
        HRESULT hr = S_OK;
    
        RECT rc;
        GetClientRect( g_hWnd, &rc );
        UINT width = rc.right - rc.left;
        UINT height = rc.bottom - rc.top;
    
        UINT createDeviceFlags = 0;
    #ifdef _DEBUG
        createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
    #endif
    
        D3D10_DRIVER_TYPE driverTypes[] =
        {
            D3D10_DRIVER_TYPE_HARDWARE,
            D3D10_DRIVER_TYPE_REFERENCE,
        };
        UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] );
    
        DXGI_SWAP_CHAIN_DESC sd;
        ZeroMemory( &sd, sizeof( sd ) );
        sd.BufferCount = 1;
        sd.BufferDesc.Width = width;
        sd.BufferDesc.Height = height;
        sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        sd.BufferDesc.RefreshRate.Numerator = 60;
        sd.BufferDesc.RefreshRate.Denominator = 1;
        sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        sd.OutputWindow = g_hWnd;
        sd.SampleDesc.Count = 1;
        sd.SampleDesc.Quality = 0;
        sd.Windowed = TRUE;
    
        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;
    
        g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );
    
        // Setup the viewport
        D3D10_VIEWPORT vp;
        vp.Width = width;
        vp.Height = height;
        vp.MinDepth = 0.0f;
        vp.MaxDepth = 1.0f;
        vp.TopLeftX = 0;
        vp.TopLeftY = 0;
        g_pd3dDevice->RSSetViewports( 1, &vp );
    
        // Create the effect
        DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
    #if defined( DEBUG ) || defined( _DEBUG )
        dwShaderFlags |= D3D10_SHADER_DEBUG;
    #endif
        hr = D3DX10CreateEffectFromFile( L"Tutorial02.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0,
                                             g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL );
        if( FAILED( hr ) )
        {   MessageBox( NULL,
                        L"The FX file cannot be located.  Please run this executable from the directory that contains the FX file.",
                        L"Error", MB_OK );
            return hr;
        }
    
        // Obtain the technique
        g_pTechnique = g_pEffect->GetTechniqueByName( "Render" );
    
        // Define the input layout
        D3D10_INPUT_ELEMENT_DESC layout[] =
        {   { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
        };
        UINT numElements = sizeof( layout ) / sizeof( layout[0] );
    
        // Create the input layout
        D3D10_PASS_DESC PassDesc;
        g_pTechnique->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 );
    
        // Create vertex buffer
        SimpleVertex vertices[] =
        {   D3DXVECTOR3( 0.0f, 0.5f, 0.5f ),
            D3DXVECTOR3( 0.5f, -0.5f, 0.5f ),
            D3DXVECTOR3( -0.5f, -0.5f, 0.5f ),
        };
        D3D10_BUFFER_DESC bd;
        bd.Usage = D3D10_USAGE_DEFAULT;
        bd.ByteWidth = sizeof( SimpleVertex ) * 3;
        bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
        bd.CPUAccessFlags = 0;
        bd.MiscFlags = 0;
        D3D10_SUBRESOURCE_DATA InitData;
        InitData.pSysMem = vertices;
        hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
        if( FAILED( hr ) )  return hr;
    
        // Set vertex buffer
        UINT stride = sizeof( SimpleVertex );
        UINT offset = 0;
        g_pd3dDevice->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
    
        // Set primitive topology
        g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
    
        return S_OK;
    }
    
    // Clean up the objects we've created
    void CleanupDevice()
    {
        if( g_pd3dDevice ) g_pd3dDevice->ClearState();
        if( g_pVertexBuffer ) g_pVertexBuffer->Release();
        if( g_pVertexLayout ) g_pVertexLayout->Release();
        if( g_pEffect ) g_pEffect->Release();
        if( g_pRenderTargetView ) g_pRenderTargetView->Release();
        if( g_pSwapChain ) g_pSwapChain->Release();
        if( g_pd3dDevice ) g_pd3dDevice->Release();
    }
    
    // Called every time the application receives a message
    LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
    {
        PAINTSTRUCT ps;
        HDC hdc;
    
        switch( message )
        {  case WM_PAINT:
                hdc = BeginPaint( hWnd, &ps );
                EndPaint( hWnd, &ps );
                break;
            case WM_DESTROY:
                PostQuitMessage( 0 );
                break;
            default:
                return DefWindowProc( hWnd, message, wParam, lParam );
        }
    
        return 0;
    }
    
    // Render a frame
    void Render()
    {
        // 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 );
    
        // Render a triangle
        D3D10_TECHNIQUE_DESC techDesc;
        g_pTechnique->GetDesc( &techDesc );
        for( UINT p = 0; p < techDesc.Passes; ++p )
        {   g_pTechnique->GetPassByIndex( p )->Apply( 0 );
            g_pd3dDevice->Draw( 3, 0 );
        }
    
        // Present the information rendered to the back buffer to the front buffer (the screen)
        g_pSwapChain->Present( 0, 0 );
    }
    
  6. Shader のプログラム(Tutorial02.fx) です。
    //--------------------------------------------------------------------------------------
    // File: Tutorial02.fx
    //
    // Copyright (c) Microsoft Corporation. All rights reserved.
    //--------------------------------------------------------------------------------------
    
    //--------------------------------------------------------------------------------------
    // Vertex Shader
    //--------------------------------------------------------------------------------------
    float4 VS( float4 Pos : POSITION ) : SV_POSITION
    {
        return Pos;
    }
    
    
    //--------------------------------------------------------------------------------------
    // Pixel Shader
    //--------------------------------------------------------------------------------------
    float4 PS( float4 Pos : SV_POSITION ) : SV_Target
    {
        return float4( 1.0f, 1.0f, 0.0f, 1.0f );    // Yellow, with Alpha = 1
    }
    
    
    //--------------------------------------------------------------------------------------
    technique10 Render
    {
        pass P0
        {
            SetVertexShader( CompileShader( vs_4_0, VS() ) );
            SetGeometryShader( NULL );
            SetPixelShader( CompileShader( ps_4_0, PS() ) );
        }
    }
    
  7. リソースファイル(Main.rc) です。
    Sample Brower で作成したファイルは結構長いのですが、本当に必要なのはコメントを除けば一行だけです。
    また IDI_MYICON を直接記述するので、resource.h は不要です。
    /////////////////////////////////////////////////////////////////////////////
    //
    // Icon
    //
    
    IDI_MYICON              ICON    DISCARDABLE     "directx.ico"
    

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