2

我有一个相当简单的 DirectX 11 框架设置,我想将其用于各种 2D 模拟。我目前正在尝试在 GPU 上实现 2D Wave Equation。它要求我将模拟的网格状态保持在前 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好的,在设置 DirectX 调试层后,我看到我使用 SRV 作为渲染目标,而它仍然绑定到着色器中的像素阶段。在使用波形着色器渲染后,我通过将着色器资源设置为 NULL 来解决此问题,但问题仍然存在 - 实际上没有运行或更新任何内容。我从这里获取了渲染目标代码并稍微修改了它,如果有帮助的话:http ://rastertek.com/dx11tut22.html

4

1 回答 1

3

好的,据我了解,您需要对纹理进行多通道渲染。

基本上你会像我在这里描述的那样做:link

  • 您使用两者D3D11_BIND_SHADER_RESOURCED3D11_BIND_RENDER_TARGET绑定标志创建 SRV。
  • 您从纹理中处理渲染目标
  • 您将第一个纹理设置为输入 ( *SetShaderResources()),将第二个纹理设置为输出 ( OMSetRenderTargets())
  • Draw()*
  • 然后你绑定第二个纹理作为输入,第三个作为输出
  • Draw()*
  • 等等

附加建议:

  1. 如果您的目标 GPU 能够从非计算着色器写入 UAV,则可以使用它。它更简单,更不容易出错。
  2. 如果您的目标 GPU 合适,请考虑使用计算着色器。是一份荣幸。
  3. 不要忘记启用 DirectX 调试层。有时我们会犯明显的错误,调试输出可以指向它们。
  4. 每次绘制调用后使用图形调试器检查您的纹理。

编辑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()设计,以使资源绑定更清晰可见。

快乐编码!=)

于 2013-10-07T11:31:03.313 回答