~プログラミング~ DirectX 11で三角形を表示しよう(ソースコード)


CD3DTest.h

#define SAFE_RELEASE(p)      { if( NULL != p ) { p->Release(); p = NULL; } }


class CD3DTest {
public:
    ID3D11Device*           m_pDevice;
    ID3D11DeviceContext*    m_pImmediateContext;
    IDXGISwapChain*         m_pSwapChain;
    ID3D11Texture2D*        m_pDepthStencilTexture;
    ID3D11RenderTargetView* m_pRenderTargetView;
    ID3D11DepthStencilView* m_pDepthStencilView;
    ID3D11Buffer*           m_pVertexBuffer;
    ID3D11InputLayout*      m_pInputLayout;
    ID3D11VertexShader*     m_pVertexShader;
    ID3D11PixelShader*      m_pPixelShader;
    D3D11_VIEWPORT          m_Viewport;

public:
            CD3DTest();
    virtual ~CD3DTest();
    virtual HRESULT Create( HWND hwnd );
    virtual void    Release();
    virtual void    Render();
};

CD3DTest.cpp

#include "stdafx.h"


struct Vertex {
    float pos[ 3 ];
    float col[ 4 ];
};

Vertex g_VertexList[] {
    { { -0.5f,  0.5f, 0.5f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
    { {  0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
    { { -0.5f, -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
};

D3D11_INPUT_ELEMENT_DESC g_VertexDesc[] {
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0,                            0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};





CD3DTest::CD3DTest()
{
    m_pDevice              = NULL;
    m_pImmediateContext    = NULL;
    m_pSwapChain           = NULL;
    m_pDepthStencilTexture = NULL;
    m_pRenderTargetView    = NULL;
    m_pDepthStencilView    = NULL;
    m_pVertexBuffer        = NULL;
    m_pInputLayout         = NULL;
    m_pVertexShader        = NULL;
    m_pPixelShader         = NULL;
}

CD3DTest::~CD3DTest()
{
    Release();
}

HRESULT CD3DTest::Create( HWND hwnd )
{
    Release();

    HRESULT              hr;
    CRect                rect;
    DXGI_SWAP_CHAIN_DESC scDesc;

    ::GetClientRect( hwnd, &rect );
    ::ZeroMemory( &scDesc, sizeof( scDesc ) );
    scDesc.BufferCount        = 1;
    scDesc.BufferDesc.Width   = rect.Width();
    scDesc.BufferDesc.Height  = rect.Height();
    scDesc.BufferDesc.Format  = DXGI_FORMAT_R8G8B8A8_UNORM;
    scDesc.BufferUsage        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    scDesc.OutputWindow       = hwnd;
    scDesc.SampleDesc.Count   = 1;
    scDesc.SampleDesc.Quality = 0;
    scDesc.Windowed           = TRUE;

    UINT flags = 0;
#ifdef _DEBUG
    flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    D3D_FEATURE_LEVEL pLevels[] = { D3D_FEATURE_LEVEL_11_0 };
    D3D_FEATURE_LEVEL level;

    hr = D3D11CreateDeviceAndSwapChain( NULL,
                                        D3D_DRIVER_TYPE_HARDWARE,
                                        NULL,
                                        flags,
                                        pLevels,
                                        1,
                                        D3D11_SDK_VERSION,
                                        &scDesc,
                                        &m_pSwapChain,
                                        &m_pDevice,
                                        &level,
                                        &m_pImmediateContext );
    if ( FAILED( hr ) )
        return hr;


    ID3D11Texture2D* pBackBuffer;

    hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer );
    if ( FAILED( hr ) )
        return hr;

    hr = m_pDevice->CreateRenderTargetView( pBackBuffer, NULL, &m_pRenderTargetView );
    pBackBuffer->Release();
    if ( FAILED( hr ) )
        return hr;



    //深度ステンシルバッファ作成
    D3D11_TEXTURE2D_DESC txDesc;
    ZeroMemory( &txDesc, sizeof( txDesc ) );
    txDesc.Width              = rect.Width();
    txDesc.Height             = rect.Height();
    txDesc.MipLevels          = 1;
    txDesc.ArraySize          = 1;
    txDesc.Format             = DXGI_FORMAT_D24_UNORM_S8_UINT;
    txDesc.SampleDesc.Count   = 1;
    txDesc.SampleDesc.Quality = 0;
    txDesc.Usage              = D3D11_USAGE_DEFAULT;
    txDesc.BindFlags          = D3D11_BIND_DEPTH_STENCIL;
    txDesc.CPUAccessFlags     = 0;
    txDesc.MiscFlags          = 0;
    hr = m_pDevice->CreateTexture2D( &txDesc, NULL, &m_pDepthStencilTexture );
    if ( FAILED( hr ) )
        return hr;

    D3D11_DEPTH_STENCIL_VIEW_DESC dsDesc;
    ZeroMemory( &dsDesc, sizeof( dsDesc ) );
    dsDesc.Format             = txDesc.Format;
    dsDesc.ViewDimension      = D3D11_DSV_DIMENSION_TEXTURE2D;
    dsDesc.Texture2D.MipSlice = 0;
    hr = m_pDevice->CreateDepthStencilView( m_pDepthStencilTexture, &dsDesc, &m_pDepthStencilView );
    if ( FAILED( hr ) )
        return hr;



    //頂点バッファ作成
    D3D11_BUFFER_DESC bufferDesc;
    bufferDesc.ByteWidth           = sizeof( Vertex ) * 3;
    bufferDesc.Usage               = D3D11_USAGE_DEFAULT;
    bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
    bufferDesc.CPUAccessFlags      = 0;
    bufferDesc.MiscFlags           = 0;
    bufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA subResourceData;
    subResourceData.pSysMem          = g_VertexList;
    subResourceData.SysMemPitch      = 0;
    subResourceData.SysMemSlicePitch = 0;

    hr = m_pDevice->CreateBuffer( &bufferDesc, &subResourceData, &m_pVertexBuffer );
    if ( FAILED( hr ) )
        return hr;



    //頂点レイアウト作成
    hr = m_pDevice->CreateInputLayout( g_VertexDesc, ARRAYSIZE( g_VertexDesc ),
                                       g_vs_main, sizeof( g_vs_main ), &m_pInputLayout );
    if ( FAILED( hr ) )
        return hr;

    //頂点シェーダー生成
    hr = m_pDevice->CreateVertexShader( &g_vs_main, sizeof( g_vs_main ), NULL, &m_pVertexShader );
    if ( FAILED( hr ) )
        return hr;

    //ピクセルシェーダー生成
    hr = m_pDevice->CreatePixelShader( &g_ps_main, sizeof( g_ps_main ), NULL, &m_pPixelShader );
    if ( FAILED( hr ) )
        return hr;


    //ビューポート設定
    m_Viewport.TopLeftX = 0;
    m_Viewport.TopLeftY = 0;
    m_Viewport.Width    = (FLOAT)rect.Width();
    m_Viewport.Height   = (FLOAT)rect.Height();
    m_Viewport.MinDepth = 0.0f;
    m_Viewport.MaxDepth = 1.0f;

    return hr;
}

void CD3DTest::Release()
{
    if( m_pImmediateContext ) {
        m_pImmediateContext->ClearState();
    }
    SAFE_RELEASE( m_pVertexBuffer );
    SAFE_RELEASE( m_pInputLayout );
    SAFE_RELEASE( m_pVertexShader );
    SAFE_RELEASE( m_pPixelShader );
    SAFE_RELEASE( m_pRenderTargetView );
    SAFE_RELEASE( m_pDepthStencilView );
    SAFE_RELEASE( m_pDepthStencilTexture );
    SAFE_RELEASE( m_pSwapChain );
    SAFE_RELEASE( m_pImmediateContext );
    SAFE_RELEASE( m_pDevice );
}

void CD3DTest::Render()
{
    float clearColor[ 4 ] = { 0.0f, 0.0f, 0.0f, 1.0f }; //red,green,blue,alpha

    UINT strides = sizeof( Vertex );
    UINT offsets = 0;
    m_pImmediateContext->IASetInputLayout( m_pInputLayout );
    m_pImmediateContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &strides, &offsets );
    m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
    m_pImmediateContext->VSSetShader( m_pVertexShader, NULL, 0 );
    m_pImmediateContext->RSSetViewports( 1, &m_Viewport );
    m_pImmediateContext->PSSetShader( m_pPixelShader, NULL, 0 );
    m_pImmediateContext->OMSetRenderTargets( 1, &m_pRenderTargetView, m_pDepthStencilView );

    m_pImmediateContext->ClearRenderTargetView( m_pRenderTargetView, clearColor );
    m_pImmediateContext->ClearDepthStencilView( m_pDepthStencilView,
                                      D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
    m_pImmediateContext->Draw( 4, 0 );

    m_pSwapChain->Present( 0, 0 );
}

vs_test.vsh

struct VS_IN
{
    float4 pos : POSITION0;
    float4 col : COLOR0;
};

struct VS_OUT
{
    float4 pos : SV_POSITION;
    float4 col : COLOR0;
};


VS_OUT vs_main( VS_IN input )
{
    VS_OUT output;

    output.pos = input.pos;
    output.col = input.col;
    return output;
}

ps_test.psh

struct PS_IN
{
    float4 pos : SV_POSITION;
    float4 col : COLOR0;
};


float4 ps_main( PS_IN input ) : SV_Target
{
    return input.col;
}

コメントをお書きください

コメント: 19
  • #1

    jikoryuu (水曜日, 28 3月 2018 16:33)

    ソースコードを提供していただいてありがとうござます。
    このコードを実際に実行してみたいと思っているのですがどのようにすればよいのか判りません。たぶんVisualStudioで作成するのでしょうが、どのテンプレートでどのように設定してよいのか判りませんでした。
    指導していただければ幸いです。

  • #2

    AraramiStudio (木曜日, 29 3月 2018 17:47)

    jikoryuuさん
    コメントありがとうございます。

    サンプルの作成にはVisual Studioを使用しています。
    作成の方法はいろいろとあると思いますが、このサンプルについては「MFCアプリケーション」のテンプレートを使用しました。設定などについては長くなってしまいそうなので改めて記事に出来たらと考えています。
    記事が投稿できるまで少しお時間を頂ければと思います。

  • #3

    jikoryuu (木曜日, 29 3月 2018 19:45)

    AraramiStudioさん
    回答ありがとうございます。
    投稿していただけるなんて夢のようです。
    他のサンプルプログラムは構造が複雑でなかなか理解できないで挫折しかかっていたところ、このページを見つけて理解できるようになって涙が出そうでした。判りやすい説明ありがとうございます。昔にDirectXのプログラムをVisualBasicで組んだことがあるのですが(約15年前)、初期化は本に付いていたものを使っていたのでさっぱりでした。しかしバージョンアップでずいぶん様変わりしたように思います。C++でDirectXを組むのは初めてなのでこのページが大変役に立っています。
    これからも頑張ってください。

  • #4

    AraramiStudio (金曜日, 30 3月 2018 19:19)

    jikoryuuさん

    MFCアプリケーションからDirectXを使うサンプルについて記事にしてみました。
    大雑把な解説ですがお役に立てれば幸いです。

    https://araramistudio.jimdo.com/2018/03/30/プログラミング-directx-11をmfcアプリケーションで使ってみる/

  • #5

    jikoryuu (日曜日, 01 4月 2018 00:14)

    AraramiStudioさん

    MFCアプリケーションからの記事大変参考になりました。記事の通りにやってみた結果、無事プログラムを走らせることができました。しかし残念ながら例の様には表示されず、真っ白な画面で表示されてしまいました。環境が悪いのでしょうか、原因は不明です。何度も作り直してみたのですが上手くいかないようです。現在VisualStudio2015でやってみたのですが、明日にでもVisualStudio2017で再作成して様子を見たいと思います。それからソリューションプラットホームはx86ではコンパイルエラーとなったのでx64でコンパイルしました。

  • #6

    jikoryuu (日曜日, 01 4月 2018 13:18)

    出来ました!!
    すみません、私がCD3DTest.cppに余計なコードを付け加えていたためにエラーが発生していたようです。その後x86でもx64でのコンパイルでもうまくいきました。感涙しました。ご丁寧な解説ありがとうございました。これを機にDirectXプログラミングを深めていこうと思います。大変ありがとうございました。

  • #7

    AraramiStudio (月曜日, 02 4月 2018 11:53)

    jikoryuuさん

    うまく動いたようで何よりです。
    微力ながらお力になれて良かったです。

  • #8

    ぬぬぬ (土曜日, 13 4月 2019 18:37)

    頂点シェーダ作成の所の
    g_vs_mainは、どこで作ってますか?

  • #9

    AraramiStudio (月曜日, 15 4月 2019 09:29)

    ぬぬぬさん
    コメントありがとうございます。

    g_vs_mainはシェーダーをコンパイルする事で作る事が出来ます。
    以下のページを参考にしてみて下さい。
    https://araramistudio.jimdo.com/2017/08/17/プログラミング-directx-11でシェーダーをコンパイルしよう/
    https://araramistudio.jimdo.com/2017/08/18/プログラミング-directx-11で三角形を表示しよう/

  • #10

    aaa (火曜日, 04 8月 2020 00:16)

    Test.cppやsanmple.cppにあるCRectはどこで作成していますか?

  • #11

    AraramiStudio (火曜日, 04 8月 2020 09:33)

    aaaさん
    コメントありがとうございます。

    CRectクラスはVisual Studio(Visual C++)に付属するATLというライブラリで提供されている物を利用していて、atltypes.hで定義されているものになります。

  • #12

    rookie (火曜日, 17 8月 2021 21:52)

    初めまして。DirectX11でゲーム制作をする際に、こちらのサイトを拝見し、参考にさせてもらいながら制作しているのですが、今回のソースコードで書かれている「CD3DTest.cpp」内でIncludeしているstdafx.hはどちらのページから解説が見れますでしょうか。
    ご教示いただけますと幸いです。

  • #13

    AraramiStudio (火曜日, 17 8月 2021 22:45)

    rookieさん
    コメントありがとうございます。

    stdafx.hは Visual Studio でプロジェクトを作成すると自動で生成されるもので「プリコンパイル済みヘッダファイル」と呼ばれるものです。
    コンパイル時間を短縮するための仕組みで、標準ライブラリなどのヘッダーファイルのincludeを1か所にまとめて記述したヘッダーファイルという感じでしょうか。

    stdafx.h の代わりに、標準ライブラリなどの必要なヘッダーファイルのincludeへ置き換えてもらえればよいと思います。

  • #14

    rookie (火曜日, 17 8月 2021)

    AraramiStudio様
    返信並びにご教示くださりありがとうございます。
    承知いたしました。

  • #15

    study (日曜日, 22 8月 2021 01:08)

    こんばんは!DirectX11で初めて制作をしていて、こちらのサイトを拝見させていただいてます。
    今回の三角形の描画について質問なのですが、ウインドウの作成(他サイトを見て作った)と、シェーダファイルのコンパイル(このサイトを拝見しながら作りました)までは出来たのですが、
    三角形の描画が行えないのです。
    コンパイルしたシェーダファイルをインクルードしたり、ビューポートなどの設定を見直したりしたのですが…
    恐縮ですが、三角形描画で可能性が高いミスを教えていただけませんでしょうか。

  • #16

    abcde (日曜日, 22 8月 2021 16:30)

    ソースコードを提供してくださり、ありがとうございます!
    現在、こちらのソースコードを見ながら三角形描画を行っていて、CD3DTest.cppのRender関数内のClearcolor[4]を数値を使って背景色を変えるところまでは出来ているのですが、三角形がどうしても表示されないのです。
    恐縮ですが、この状態を解決する方法を教えていただけませんでしょうか。

    現在のRender関数内でブレークポイントを使って調べたところ、m_pVertexBuffer、offsets、m_pVertexShader、m_pDepthStencilViewがNULLで、m_pRenderTargetViewが、情報はありません。D3D11.dllのシンボルが読み込まれていません。という状態だったのですが、
    私のVisualStudioの設定などが間違っているから起こっているのでしょうか。

  • #17

    AraramiStudio (月曜日, 23 8月 2021 11:15)

    studyさん
    コメントありがとうございます。

    原因がどかかを推測するのはなかなか難しいですが、
    Visual Studioの「MFCアプリケーション」テンプレートを使って作成する場合の解説がありますので以下のURLを参照してみてください。
    https://araramistudio.jimdo.com/2018/03/30/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-directx-11%E3%82%92mfc%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B/

  • #18

    AraramiStudio (月曜日, 23 8月 2021 11:26)

    abcdeさん
    コメントありがとうございます。

    m_pVertexBuffer、offsets、m_pVertexShader、m_pDepthStencilViewなどのインスタンスは、CD3DTest::Createメソッドで生成しています。
    CD3DTest::Createメソッドのどこかでエラーが起きていると思われるので、メソッド内で呼び出しているいくつかのm_pDevice->Create・・・の戻り値を確認してみてください。

  • #19

    abcde (月曜日, 23 8月 2021 17:55)

    AraramiStudio様
    返信ありがとうございます。長文になってしまいますが、ご容赦ください。

    AraramiStudio様にアドバイスを頂き、戻り値確認のために
    D3D11CreateDeviceAndSwapChain関数とその引数のm_pDevice、m_pDeviceContext、
    Create関数内で書かれているm_pDevice->Create...の部分にブレークポイントを置いてみました。

    確認したところ、AraramiStudio様のエラーが起きていると思われるというアドバイス通り、Create関数内で処理がスキップされている部分がありました。

    m_pDevice->各Create関数を呼び出しているところでは、m_pDeviceの中に0x009dce(実行するたびに中身の英数字が変わる)が入っていたのですが、d3d11.dllの情報が読み込まれていません。というメッセージが横に並んでいる状態で、

    CreateDepthStencilView関数、CreateBuffer関数、頂点シェーダ、ピクセルシェーダ作成、頂点レイアウト生成、ビューポート設定の処理部分にブレークポイントを貼っていたのですが、通っていない状態でした。
    上記の処理が通らない場合、どこに問題があるか教えていただいてもよろしいでしょうか。

    追加の質問で恐縮なのですが、
    D3D11CreateDeviceAndSwapChain関数と、引数のDevice,Contextにブレークポイントを置くと、D3D11CreateDeviceAndSwapChain関数を呼び出している部分で止まったので、そのまま続行させると、if (FAILED(hr)) { return hr; }のところに行き、hrの中身を見るとS_OKが入っていたのですが、この関数に関しては正常に初期化ができているということでよろしいのでしょうか。