【问题标题】:How to implement a "render-to-texture" pipeline in Direct3D 11?如何在 Direct3D 11 中实现“渲染到纹理”管道?
【发布时间】:2013-07-24 15:46:23
【问题描述】:

我正在尝试使用 HLSL 和 Direct3D 11 进行一些 GPGPU 计算。 我的目标是按顺序计算多张图像(每张图像一次渲染),然后将它们相加。

为了实现这一点,我创建了三个纹理:一个是输入,两个用于汇总结果。我正在尝试的方法:首先我渲染到纹理 2(我使用纹理和纹理 3 纹理作为输入),然后我使用稍微修改的像素着色器渲染到纹理 3(我使用纹理和纹理 2 纹理作为输入)。在此之后,我将纹理转储到 PNG 文件中。我的问题是,不知何故,第二个像素着色器没有得到第一个着色器(纹理2)的结果,而是原始的空纹理。我使用 D3D11_USAGE_DEFAULT 和 D3D11_BIND_RENDER_TARGET | 定义了纹理、纹理 2 和纹理 3。 D3D11_BIND_SHADER_RESOURCE 绑定标志。

我的 HLSL 着色器(shader1):

float4 main(PS_INPUT input) : SV_TARGET
{
...
float4 val5 = 0.25F * (val + val2 + val3 + val4) + tex3.Sample(sam, input.Tex4);
return val5;
}

另一个着色器(shader2):

float4 main(PS_INPUT input) : SV_TARGET
{
...
float4 val5 = 0.25F * (val + val2 + val3 + val4) + tex2.Sample(sam, input.Tex4);
return val5;
}

执行纹理渲染和转储的代码:

context->OMSetRenderTargets(1, &targetViewTexture2, NULL);

float z = 280.0F;
GenMatrix(z);
context->VSSetShader(vs, NULL, 0);
context->PSSetShader(ps, NULL, 0);
context->PSSetSamplers(0, 1, &state);
context->VSSetConstantBuffers(0, 1, &cbuf);
context->Draw(6, 0);
swapChain->Present(0, 0);

context->OMSetRenderTargets(1, &targetViewTexture3, NULL);
z = 0.0F;
GenMatrix(z);
context->VSSetShader(vs, NULL, 0);
context->PSSetShader(ps2, NULL, 0);
context->PSSetSamplers(0, 1, &state);
context->VSSetConstantBuffers(0, 1, &cbuf);
context->Draw(6, 0);
swapChain->Present(0, 0);
DirectX::ScratchImage im;
DirectX::CaptureTexture(device, context, texture3, im);
const DirectX::Image *realImage = im.GetImage(0, 0, 0);
HRESULT hr2 = DirectX::SaveToWICFile(*realImage, DirectX::WIC_FLAGS_NONE, GUID_ContainerFormatPng, L"output_tex3.png", NULL);
DirectX::CaptureTexture(device, context, texture2, im);
realImage = im.GetImage(0, 0, 0);
hr2 = DirectX::SaveToWICFile(*realImage, DirectX::WIC_FLAGS_NONE, GUID_ContainerFormatPng, L"output_tex2.png", NULL);

第一遍(ps)的输出是正确的,但第二遍不是。如果我只留下着色器代码:

    float4 val5 = tex2.Sample(sam, input.Tex4);

我得到一个空图像。我错过了什么吗?我是否必须调用一些方法才能在第二个像素着色器中使用纹理?我想我指出了我的大型代码库的相关部分,但如果您需要更多信息,请在评论部分询问。

【问题讨论】:

  • 您使用的是 Visual Studio 2012 吗?因为它有非常强大的图形调试工具。
  • 为什么你的代码中有swapChain->Present
  • 我之前有swapChain->Present,因为我用屏幕看每一步的结果(我现在注释掉了)。我用的是VS2012,但是不知道怎么下手;因为纹理似乎在第一次 Draw 调用后被填充,但在第二次调用时似乎是空的。
  • 您是否尝试过使用 Visual Studio 2012 图形调试工具?在Debug->Graphics->Start Diagnostics.
  • 我得到了一个有趣的结果:使用您提到的调试工具,我查看了输入纹理,它实际上不是空的,而是包含正确的值。由于其他问题,输出可能不正确。

标签: directx direct3d hlsl


【解决方案1】:

问题是我将纹理同时用作输入和输出。您可以一次性使用纹理作为输入或渲染目标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 2013-02-24
    • 1970-01-01
    相关资源
    最近更新 更多