我有一个相当简单的DirectX 11框架设置,我想用于各种2D模拟。我目前正在尝试在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个缓冲区的数组。每个循环我使用前两个缓冲区中的纹理作为下一个帧缓冲区的输入,我还绘制任何用户输入来更改模拟状态。然后我画出结果。
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 好的,我在设置DirectX调试层之后,我看到我使用SRV作为渲染目标,而它仍然在着色器中绑定到Pixel阶段。我通过使用wave着色器渲染后将着色器资源设置为NULL来修复此问题,但问题仍然存在 - 实际上没有任何内容被运行或更新。我从这里获取了渲染目标代码并稍微修改了它,如果有任何帮助:http://rastertek.com/dx11tut22.html
答案 0 :(得分:2)
好的,据我所知,你需要对纹理进行多次渲染。
基本上你就像我在这里描述的那样:link
D3D11_BIND_SHADER_RESOURCE
和D3D11_BIND_RENDER_TARGET
绑定标记创建SRV。*SetShaderResources()
),将第二个纹理设置为输出(OMSetRenderTargets()
)Draw()*
Draw()*
其他建议:
修改1:
如我所见,您只需拨打BeginRender
和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()
设计,以便更清晰地看到资源绑定。
快乐的编码! =)