忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

DirectX10 + C++/CLI 色つき三角形を表示

前回は真っ白なポリゴンを表示しただけだったので、今回はそれに色をつけてみました。

前回とどこが違うのかというと、頂点に使う構造体です。
前回は3D座標だけが頂点のメンバでしたが、今回はそれに付け加え、色もメンバになっています。

そしてその影響で、インプット・レイアウトオブジェクトやHLSLで書くシェーダーが変更されます。

DX10Test.cpp
#using<System.Windows.Forms.dll>
#using<System.dll>

#include<d3d10.h>
#include<d3dx10.h>

using namespace System;
using namespace System::Windows::Forms;

struct VertexPositionColor
{
    D3DXVECTOR3 Position;
    D3DXVECTOR4 Color;
};

ref class Game : Form
{
    ID3D10Device* graphicsDevice;
    IDXGISwapChain* swapChain;
    ID3D10RenderTargetView* renderTargetView;


    ID3D10Effect *effect;
    ID3D10InputLayout* vertexLayout;
    ID3D10Buffer* vertexBuffer;

public:
    void Run()
    {
        InitDevice();
        Show();

        while(Created)
        {
            Draw();
            Application::DoEvents();
        }
    }

private:

    void InitDevice()
    {
        createGraphicsDevice();

        createRenderTargetView();

        setupViewport();

        LoadGraphicsContent();
    }


    void LoadGraphicsContent()
    {
        //シェーダーの設定
        ID3D10Effect* effect;
        HRESULT result = D3DX10CreateEffectFromFile(
            "MyShader.fx",
            NULL, 
            NULL,
            "fx_4_0",
            D3D10_SHADER_ENABLE_STRICTNESS,
            0,
            graphicsDevice,
            NULL,
            NULL,
            &effect,
            NULL,
            NULL
            );

        if(FAILED(result))
            throw gcnew Exception("couldn't create effect object");

        this->effect = effect;



        //描画のときデバイスに入力する頂点データのレイアウトの設定
        D3D10_INPUT_ELEMENT_DESC vertexElements[] = 
        {
            {"SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D10_INPUT_PER_VERTEX_DATA, 0},
            {"Color", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D10_INPUT_PER_VERTEX_DATA, 0}
        };

        D3D10_PASS_DESC passDesc;
        effect->GetTechniqueByName("MyTechnique")->GetPassByIndex(0)->GetDesc(&passDesc);

        ID3D10InputLayout *vertexLayout;
        result = graphicsDevice->CreateInputLayout(
            vertexElements,
            2,
            passDesc.pIAInputSignature,
            passDesc.IAInputSignatureSize,
            &vertexLayout
            );

        if(FAILED(result))
            throw gcnew Exception("couldn't create InputLayout");

        this->vertexLayout = vertexLayout;

        graphicsDevice->IASetInputLayout(vertexLayout);



        //頂点バッファの設定
        VertexPositionColor vertices[] = 
        {
            {D3DXVECTOR3(0, 0.5f, 0), D3DXVECTOR4(1, 1, 1, 1)},
            {D3DXVECTOR3(0.5f, 0, 0), D3DXVECTOR4(0, 0, 1, 1)},
            {D3DXVECTOR3(-0.5f, 0, 0), D3DXVECTOR4(1, 0, 0, 1)}
        };

        D3D10_SUBRESOURCE_DATA initData;
        initData.pSysMem = vertices;

        D3D10_BUFFER_DESC bufferDesc;
        ZeroMemory(&bufferDesc, sizeof(bufferDesc));
        bufferDesc.Usage = D3D10_USAGE_DEFAULT;
        bufferDesc.ByteWidth = sizeof(VertexPositionColor) * 3;
        bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;

        ID3D10Buffer *vertexBuffer;

        result = graphicsDevice->CreateBuffer(
            &bufferDesc,
            &initData,
            &vertexBuffer
            );

        if(FAILED(result))
            throw gcnew Exception("couldn't create Vertex Buffer");

        this->vertexBuffer = vertexBuffer;

        unsigned int stride = sizeof(VertexPositionColor);
        unsigned int offset = 0;
        graphicsDevice->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);



        //頂点バッファが三角形のリストとして描画されるようにセットします。
        graphicsDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    }

    ~Game(){ this->!Game(); }

    !Game()
    {
        if(graphicsDevice) graphicsDevice->ClearState();

        if(vertexBuffer) vertexBuffer->Release();
        if(vertexLayout) vertexLayout->Release();
        if(effect) effect->Release();

        if(renderTargetView) renderTargetView->Release();
        if(swapChain) swapChain->Release();
        if(graphicsDevice) graphicsDevice->Release();
    }

    void Draw()
    {
        float cornflowerBlue[] = {0.39, 0.58, 0.93, 1};
        graphicsDevice->ClearRenderTargetView(renderTargetView, cornflowerBlue);


        effect->GetTechniqueByName("MyTechnique")->GetPassByIndex(0)->Apply(0);
        graphicsDevice->Draw( 3, 0);

        swapChain->Present(0, 0);
    }

    void createGraphicsDevice()
    {
        DXGI_SWAP_CHAIN_DESC swapChainDescription;
        ZeroMemory( &swapChainDescription, sizeof(swapChainDescription) );
        swapChainDescription.BufferCount = 1;
        swapChainDescription.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDescription.OutputWindow = (HWND)(this->Handle.ToInt32());
        swapChainDescription.SampleDesc.Count = 1;
        swapChainDescription.Windowed = TRUE;



        ID3D10Device *graphicsDevice;
        IDXGISwapChain *swapChain;

        HRESULT result = D3D10CreateDeviceAndSwapChain(
            NULL,
            D3D10_DRIVER_TYPE_REFERENCE,
            NULL, 
            0, 
            D3D10_SDK_VERSION,
            &swapChainDescription,
            &swapChain,
            &graphicsDevice
            );

        if( FAILED(result) )
            throw gcnew Exception("Couldn't create Graphics Device");

        this->graphicsDevice = graphicsDevice;
        this->swapChain = swapChain;
    }

    void createRenderTargetView()
    {
        ID3D10Texture2D *backBuffer;
        HRESULT result = swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&backBuffer);

        if( FAILED(result) )
            throw gcnew Exception("Couldn't get BackBuffer from swap chain.");

        ID3D10RenderTargetView* renderTargetView;
        result = graphicsDevice->CreateRenderTargetView(backBuffer, NULL, &renderTargetView);
        backBuffer->Release();

        if( FAILED(result) )
            throw gcnew Exception("Couldn't create RenderTargetView.");

        this->renderTargetView = renderTargetView;

        graphicsDevice->OMSetRenderTargets(1, &renderTargetView, NULL);
    }

    void setupViewport()
    {
        D3D10_VIEWPORT viewport;
        viewport.Width = Width;
        viewport.Height = Height;
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        graphicsDevice->RSSetViewports( 1, &viewport );
    }
};

int main()
{
    Game ^game = gcnew Game();
    game->Run();
}


MyShader.fx
struct VertexPositionColor
{
    float4 Position : SV_Position;
    float4 Color : COLOR;
};

VertexPositionColor MyVertexShader(VertexPositionColor input)
{
    return input;
}

float4 MyPixelShader(VertexPositionColor input) : SV_Target
{
    return input.Color;
}

technique10 MyTechnique
{
    pass
    {
        SetVertexShader(CompileShader(vs_4_0, MyVertexShader()));
        SetPixelShader(CompileShader(ps_4_0, MyPixelShader()));
    }
}


coloredTriangle.jpg
色が付いてカラフルになりました。
ついでに背景を、XNAのサンプルでしょっちゅう使われているコーンフラワーブルーにしました。(三角形の3つの色とかぶらないようにしないと見にくくなってしまうからです。)

拍手[0回]

PR