さまざまな 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 に設定することでこれを修正しましたが、問題は解決せず、実際には何も実行または更新されません。ここからレンダー ターゲット コードを取得し、少し修正しました。