Texture Cylinder

プログラムで生成したシリンダーにテクスチャを張り付けます。

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

プログラムの説明

  1. Texture Cube では、キューブの頂点データを配列で定義しました。
    今回はテクスチャ座標を設定したシリンダーをプログラムで生成して描画します。
    頂点データや頂点Indexの配列に代えて、STL(Standard Template Library) の vector コンテナを使います。
    STL の vector は、C/C++2倍すると最後尾の数字が先頭に を参照して下さい。
  2. Texture のプロジェクトをベースにします。
    Content\ のフォルダには、次のファイルが格納されています。
    Shader は Texture を張り付けて描画するものです。
  3. Ayu.jpg(特に画像は問わない)をフォルダのルートにコピーします。
    ソリューションエクスプローラでプロジェクトに追加すると Assets\Ayu.jpg に登録されます。
    但し、呼び出すときはそのまま L"Ayu.jpg" とします。
  4. Content\Sample3DSceneRenderer.h に頂点データと頂点Index を vector で定義します。
    #include <vector>
    using namespace std;
    
        vector<VertexPosition> m_modelVertices;
        vector<unsigned short> m_modelIndices;
    
  5. Content\Sample3DSceneRenderer.cpp を修正します。
    ヘッダーの追加です。
    #include "TextureLoader.h"
    #define  KAKU  20       //(Cylinder の画数)
    
    カメラを引いて、モデルの大きさを調整します。
    static const XMVECTORF32 eye = { 0.0f, 0.7f, 4.0f, 0.0f };
    
    プログラムでシリンダーを生成します。
    キューブの定義は削除して下さい。
    auto createCubeTask = (createPSTask && createVSTask).then([this] ()
    {   int i;
        static VertexPosition VP[2];
        for(i = 0; i<KAKU; i++)
        {   float v = (float)i / (float)(KAKU - 1);
            float theta = v * 3.14f * 2;
            VP[0].pos = XMFLOAT3(sinf(theta), -1.5f, cosf(theta));
            VP[0].norm = XMFLOAT3(sinf(theta), 1.0f, cosf(theta));
            VP[0].tex.x = (float)i / (KAKU - 1);
            VP[0].tex.y = 1.0f;
            VP[1].pos = XMFLOAT3(sinf(theta), 1.5f, cosf(theta));
            VP[1].norm = XMFLOAT3(sinf(theta), 1.0f, cosf(theta));
            VP[1].tex.x = (float)i / (KAKU - 1);
            VP[1].tex.y = 0.0f;
            m_modelVertices.push_back(VP[0]);
            m_modelVertices.push_back(VP[1]);
        }
    
    頂点Index の計算です。
    キューブの定義は削除して下さい。
        for(i = 0; i<KAKU; i++)
        {   m_modelIndices.push_back(i*2+0);
            m_modelIndices.push_back(i*2+1);
            m_modelIndices.push_back(i*2+2);
        }
        for(i=0; i<KAKU; i++)
        {   m_modelIndices.push_back(i*2+3);
            m_modelIndices.push_back(i*2+2);
            m_modelIndices.push_back(i*2+1);
        }
    
    メッシュを生成するために、vector 領域を配列に変換します。
        int VTnum = m_modelVertices.size();
        int IDXnum = m_modelIndices.size();
        m_indexCount = IDXnum;
        VertexPosition *Vertices = new VertexPosition[VTnum];
        unsigned short *Indices = new unsigned short[IDXnum];
        for(int i=0; i<VTnum; i++) Vertices[i] = m_modelVertices[i];
        for(int i=0; i<IDXnum; i++) Indices[i] = m_modelIndices[i];
    
    モデルデータを参照してメッシュを生成します。
        D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
        vertexBufferData.pSysMem = Vertices;
        vertexBufferData.SysMemPitch = 0;
        vertexBufferData.SysMemSlicePitch = 0;
        CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPosition)*VTnum, D3D11_BIND_VERTEX_BUFFER);
    
        DX::ThrowIfFailed(
            m_deviceResources->GetD3DDevice()->CreateBuffer(
                &vertexBufferDesc, &vertexBufferData, &m_vertexBuffer ));
    
        D3D11_SUBRESOURCE_DATA indexBufferData = {0};
        indexBufferData.pSysMem = Indices;
        indexBufferData.SysMemPitch = 0;
        indexBufferData.SysMemSlicePitch = 0;
        CD3D11_BUFFER_DESC indexBufferDesc(sizeof(unsigned short)*IDXnum, D3D11_BIND_INDEX_BUFFER);
    
        DX::ThrowIfFailed(
            m_deviceResources->GetD3DDevice()->CreateBuffer(
                &indexBufferDesc, &indexBufferData, &m_indexBuffer ));
    
        // 領域の解放
        if (Vertices)   delete Vertices;
        if (Indices)    delete Indices;
    });
    
    // モデルが生成出来たら、オブジェクトを描画する準備が完了します。
    createCubeTask.then([this] () {
        m_loadingComplete = true;
    });
    
    続いて Texture をロードします。
    "Ayu.jpg" がロードされて m_textureSRV に設定されます。
        TextureLoader^ loader = ref new TextureLoader(m_deviceResources->GetD3DDevice());
        loader->LoadTexture(L"Ayu.jpg", nullptr, &m_textureSRV);
    
  6. Content\Sample3DSceneRenderer.cpp の Render() メソッドで描画します。
        context->PSSetShaderResources(0, 1, m_textureSRV.GetAddressOf());
        context->PSSetSamplers(0, 1, m_sampler.GetAddressOf());
        //※この位置(DrawIndexed の直前)に追加
        context->DrawIndexed(m_indexCount, 0, 0);
    
    説明不足の所は Texture を参照して下さい。
    コンパイルして実行すると、ページ先頭の画像のようにテクスチャを張り付けて描画されます。

【NOTE】

vector 領域からモデルデータを直接参照することも出来るようです。
但し、領域が配列と同様に連続していることが条件で、あまりお勧めはできません。
直接参照する場合は、次のようになります。
    D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
    vertexBufferData.pSysMem = m_modelVertices.data();
    vertexBufferData.SysMemPitch = 0;
    vertexBufferData.SysMemSlicePitch = 0;
    CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPosition)*KAKU*2, D3D11_BIND_VERTEX_BUFFER);

超初心者のプログラム入門(DirectX Store)