2

さまざまな 2D シミュレーションに使用したい、かなり単純な DirectX 11 フレームワークのセットアップがあります。現在、GPU で 2D 波動方程式を実装しようとしています。新しいタイムステップを計算するには、シミュレーションのグリッド状態を 2 つ前のタイムステップで維持する必要があります。

私がそれをどのように行ったかは、次のパブリックメソッドを持つ FrameBuffer というクラスがあります。

bool Initialize(D3DGraphicsObject* graphicsObject, int width, int height);

void BeginRender(float clearRed, float clearGreen, float clearBlue, float clearAlpha) const;
void EndRender() const;

// Return a pointer to the underlying texture resource
const ID3D11ShaderResourceView* GetTextureResource() const;

メインの描画ループには、これらのバッファーの 3 つの配列があります。ループごとに、前の 2 つのバッファーからのテクスチャを次のフレーム バッファーへの入力として使用し、ユーザー入力を描画してシミュレーションの状態を変更します。次に、結果を描画します。

    int nextStep = simStep+1;
    if (nextStep > 2)
        nextStep = 0;

    mFrameArray[nextStep]->BeginRender(0.0f,0.0f,0.0f,1.0f);
    {
        mGraphicsObj->SetZBufferState(false);
        mQuad->GetRenderer()->RenderBuffers(d3dGraphicsObj->GetDeviceContext());
        ID3D11ShaderResourceView* texArray[2] = { mFrameArray[simStep]->GetTextureResource(),
                                                  mFrameArray[prevStep]->GetTextureResource() };
        result = mWaveShader->Render(d3dGraphicsObj, mQuad->GetRenderer()->GetIndexCount(), texArray);
        if (!result)
            return false;
        // perform any extra input
        I_InputSystem *inputSystem = ServiceProvider::Instance().GetInputSystem();
        if (inputSystem->IsMouseLeftDown()) {
            int x,y;
            inputSystem->GetMousePos(x,y);
            int width,height;
            mGraphicsObj->GetScreenDimensions(width,height);
            float xPos = MapValue((float)x,0.0f,(float)width,-1.0f,1.0f);
            float yPos = MapValue((float)y,0.0f,(float)height,-1.0f,1.0f);
            mColorQuad->mTransform.position = Vector3f(xPos,-yPos,0);
            result = mColorQuad->Render(&viewMatrix,&orthoMatrix);
            if (!result)
                return false;
        }
        mGraphicsObj->SetZBufferState(true);
    }
    mFrameArray[nextStep]->EndRender();

    prevStep = simStep;
    simStep = nextStep;

    ID3D11ShaderResourceView* currTexture = mFrameArray[nextStep]->GetTextureResource();

    // Render texture to screen
    mGraphicsObj->SetZBufferState(false);
    mQuad->SetTexture(currTexture);
    result = mQuad->Render(&viewMatrix,&orthoMatrix);
    if (!result)
        return false;
    mGraphicsObj->SetZBufferState(true);

問題は、何も起きていないことです。描画したものはすべて画面に表示されますが (小さなクワッドを使用して描画します)、シミュレーションのどの部分も実際に実行されません。必要に応じてシェーダー コードを提供できますが、同じアルゴリズムを使用して以前に CPU に実装したことがあるため、機能することは確かです。D3D レンダー ターゲットがどの程度うまく機能するのか、フレームごとに間違って描画しているだけなのか、よくわかりません。

編集 1: フレーム バッファーの開始および終了レンダリング関数のコードは次のとおりです。

void D3DFrameBuffer::BeginRender(float clearRed, float clearGreen, float clearBlue, float clearAlpha) const {

  ID3D11DeviceContext *context = pD3dGraphicsObject->GetDeviceContext();

context->OMSetRenderTargets(1, &(mRenderTargetView._Myptr), pD3dGraphicsObject->GetDepthStencilView());

float color[4];

// Setup the color to clear the buffer to.
color[0] = clearRed;
color[1] = clearGreen;
color[2] = clearBlue;
color[3] = clearAlpha;

// Clear the back buffer.
context->ClearRenderTargetView(mRenderTargetView.get(), color);

// Clear the depth buffer.
context->ClearDepthStencilView(pD3dGraphicsObject->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0);

void D3DFrameBuffer::EndRender() const {
    pD3dGraphicsObject->SetBackBufferRenderTarget();
}

編集 2 OK、DirectX デバッグ レイヤーをセットアップした後、SRV をレンダー ターゲットとして使用していることに気付きましたが、SRV はシェーダーの外で Pixel ステージにまだバインドされています。ウェーブ シェーダーでレンダリングした後、シェーダー リソースを NULL に設定することでこれを修正しましたが、問題は解決せず、実際には何も実行または更新されません。ここからレンダー ターゲット コードを取得し、少し修正しました

4

1 に答える 1

3

さて、私が理解しているように、テクスチャにはマルチパスレンダリングが必要です。

基本的には、ここで説明したように行います:リンク

  • D3D11_BIND_SHADER_RESOURCEおよびD3D11_BIND_RENDER_TARGETbind フラグの両方を使用して SRV を作成します。
  • テクスチャからレンダー ターゲットを作成しています
  • 最初のテクスチャを入力 ( *SetShaderResources()) として、2 番目のテクスチャを出力 ( OMSetRenderTargets())として設定します。
  • 君はDraw()*
  • 次に、2 番目のテクスチャを入力としてバインドし、3 番目のテクスチャを出力としてバインドします。
  • Draw()*

追加のアドバイス:

  1. ターゲット GPU が非計算シェーダーから UAV に書き込むことができる場合は、それを使用できます。これははるかに単純で、エラーが発生しにくいです。
  2. ターゲット GPU が適している場合は、計算シェーダーの使用を検討してください。喜ばしいことだ。
  3. DirectX デバッグ レイヤーを有効にすることを忘れないでください。明らかなエラーが発生し、デバッグ出力がそれらを指摘する場合があります。
  4. グラフィック デバッガーを使用して、各描画呼び出しの後にテクスチャを確認します。

編集1:

BeginRenderご覧のとおり、 andは 1 回だけ呼び出すOMSetRenderTargetsので、すべてのレンダリングはmRenderTargetView. しかし、必要なのはインターリーブすることです:

SetSRV(texture1);
SetRT(texture2);
Draw();
SetSRV(texture2);
SetRT(texture3);
Draw();
SetSRV(texture3);
SetRT(backBuffer);
Draw();

また、まだ何があるかわかりmRenderTargetViewません。

だから、前に

result = mColorQuad->Render(&viewMatrix,&orthoMatrix);

どこかにあるはずですOMSetRenderTargets

おそらく、設計を見直してBegin()/End()、リソースのバインディングがより明確に見えるようにすることをお勧めします。

ハッピーコーディング!=)

于 2013-10-07T11:31:03.313 に答える