2

DirectX 11の使用と学習を簡単にするために、独自の「Engine」クラスを作成しています。その「エンジン」には、レンダリングするオブジェクトのリストがあります。それらのいくつかは「プリミティブ」(独自のBoxクラス)です。

問題は、Box :: render()が関数呼び出しごとにバッファーを作成することです。

関数呼び出しごとに計算しないように何かを変更できますか?

たぶん、コンストラクターでg_pIndexBufferを1回だけ計算し、ボックスごとに保持する必要がありますか?しかし、g_pVertexBufferとg_pConstantBufferはどうでしょうか?

私は箱を求めているだけでなく、もっと一般的です-他のプリミティブやメッシュを描きたいときに状況は変わりますか?(Boxの場合、g_pVertexBufferを1回計算でき、マトリックスを使用してオブジェクトをスケーリングするだけではないと思います)。

コードは次のようになります(ここではコードの一部をスキップしました。コードはDirectX SDKのチュートリアルに基づいています)。

Box::render(
    XMFLOAT4X4 &viewM, 
    XMFLOAT4X4 &projectionM, 
    ID3D11Buffer* g_pConstantBuffer, ID3D11DeviceContext* g_pImmediateContext,
    ID3D11VertexShader* g_pVertexShader,
    ID3D11PixelShader* g_pPixelShader,
    ID3D11Device * g_pd3dDevice,
    ID3D11Buffer* g_pIndexBuffer){

    ...
    // Create vertex buffer
    SimpleVertex vertices[] =
{
    { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT4( 1.0f, 0.0f, 0.0f, 1.0f ) },
    { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 0.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 1.0f, 0.0f, 1.0f ) },
    { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f ) },
    { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) },
};

    D3D11_BUFFER_DESC bd;
    ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( SimpleVertex ) * 8;
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    D3D11_SUBRESOURCE_DATA InitData;
    ZeroMemory( &InitData, sizeof(InitData) );
    InitData.pSysMem = vertices;
ID3D11Buffer* g_pVertexBuffer;
HRESULT hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );

    // Set vertex buffer
UINT stride = sizeof( SimpleVertex );
    UINT offset = 0;
    g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset);

    WORD indices[] =
    {
    3,1,0, 2,1,3,
    0,5,4, 1,5,0,
    3,4,7, 0,4,3,
    1,6,5, 2,6,1,
    2,7,6, 3,7,2,
    6,4,5, 7,4,6,
    };


    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( WORD ) * 36; // 36 vertices needed for 12 triangles in a triangle list
    bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
    InitData.pSysMem = indices;
    hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer );


    // Set index buffer
    g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );

    // Set primitive topology
    g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

// Create the constant buffer
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(ConstantBuffer2);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
    hr = g_pd3dDevice->CreateBuffer( &bd, NULL, &g_pConstantBuffer );

    ...
    XMMATRIX mSpin = XMMatrixRotationZ( a );
    XMMATRIX mOrbit = XMMatrixRotationY( b );
    XMMATRIX mTranslate = XMMatrixTranslation( c, d, e );
    XMMATRIX mScale = XMMatrixScaling( f, g, h );

    XMMATRIX g_World = mScale * mSpin * mTranslate * mOrbit;

    ConstantBuffer2 cb1;
    cb1.mWorld = XMMatrixTranspose( g_World );

    XMMATRIX g_View = XMLoadFloat4x4(&viewM);
    XMMATRIX g_Projection = XMLoadFloat4x4(&projectionM);
    cb1.mView = XMMatrixTranspose( g_View );
    cb1.mProjection = XMMatrixTranspose( g_Projection );
    g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cb1, 0, 0 );

    g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
    g_pImmediateContext->VSSetConstantBuffers( 0, 1, &g_pConstantBuffer );
    g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
    g_pImmediateContext->DrawIndexed( 36, 0, 0 );
}
4

1 に答える 1

2

あなたの質問に対する答えは、バッファのタイプによって異なります。そしてもちろん、作成しているアプリケーションの種類についても。

頂点バッファとインデックスバッファは一度だけ作成し、できるだけ頻繁に再利用する必要があります。作成に適した場所は、オブジェクトを表すクラスのコンストラクターです。さらに、オブジェクト間で共有ジオメトリがある場合は、ジオメトリクラス(MeshDX 9までのバージョンのようなもの)の作成を検討できます。次に、geometryクラスのコンストラクターでバッファーを1回作成し、オブジェクトから適切なgeometryインスタンスを参照します。

もちろん、特に頂点バッファがアプリケーション全体で変更される可能性がある状況もあります。ただし、それでも、最初に一度作成し、必要に応じて書き直す必要があります。しかし、それは可能な限り発生しないはずです。頂点バッファに変更された多くの変更は、適切なシェーダで行うことができます。

定数バッファの場合、これは少し注意が必要です。一定のバッファーは、以下を変更するデータに分割する必要があります。

  • 一度もない
  • フレームあたり
  • フレームごとおよびオブジェクトごと。
  • そして多分必要に応じて他の人

そして、それはそれらが作成されるべき位置を意味します。変更しないバッファは、アプリケーションの開始時に一度作成する必要があります(頂点およびインデックスバッファと同様)。フレームごとのバッファは新しいフレームの開始時に作成する必要があり、オブジェクトごとのバッファはオブジェクトのレンダリング時に作成する必要があります。

バッファは、現在のバッファとして設定されていなくても存在できることに注意してください。バッファのライフサイクルは次のようになります。

  • 頂点、インデックスを作成し、定数バッファを変更しない
  • フレームごとに
    • フレームごとの定数バッファを作成します
    • オブジェクトごとに
      • オブジェクトごとの定数バッファを作成します
      • 頂点、インデックス、およびすべての定数バッファを設定します
      • オブジェクトをレンダリングする

このガイドラインは、進行するにつれて多少変化します。たとえば、シェーダーやジオメトリなどでオブジェクトを並べ替え、それに応じてバッファを設定できます。

于 2012-07-03T19:17:24.730 に答える