在DirectX 11中使用一次渲染来渲染多个纹理

13
我试图使用C++ DirectX 11 SDK 一次性渲染到两个纹理,我想让一个纹理包含结果图像每个像素的颜色(通常在渲染3D场景时看到屏幕上的内容),并且另一个纹理包含每个像素的法线和深度(法线用3个浮点数表示,深度用1个浮点数表示)。目前,我能想到的是创建两个渲染目标,第一次渲染输出颜色,第二次渲染输出法线和深度到各自的渲染目标。但是,这似乎很浪费时间,因为我可以在第一次渲染中得到每个像素的颜色、法线和深度信息。所以有没有一种方法可以通过像素着色器输出两个纹理呢?
任何帮助都将不胜感激。
P.S. 我正在考虑类似于像素着色器中的RWTexture2D或RWStructuredBuffer。一些背景信息:我需要进一步处理这两个图像,用于计算着色器。这引出了一个附带问题:由于像素着色器(与计算着色器不同)每次写入一个像素,如何知道像素着色器何时完成,并告诉计算着色器开始图像后处理?
1个回答

22

您需要使用MRT(多重渲染目标)在一次渲染中进行渲染。

您可以使用OMSetRenderTargets将两个目标绑定为输出。

http://msdn.microsoft.com/en-us/library/windows/desktop/ff476464(v=vs.85).aspx

以下是需要翻译的内容:

http://hieroglyph3.codeplex.com/(DefferedRendering)中有一个例子,然后展示了如何同时写入两个纹理。

这里是一个小样例:

ID3D11DeviceContext* deviceContext; //Your immediate context

ID3D11RenderTargetView* m_pRenderViews[2]; //Not more than D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT (8)
m_pRenderViews[0] = pRTV1; //First target
m_pRenderViews[1] = pRTV2; //second target

deviceContext->OMSetRenderTargets(2, &m_pRenderViews[0], NULL); //NULL means no depth stencil attached

然后,您的像素着色器需要输出一个结构体而不是单个颜色:
struct PS_OUTPUT
{
    float4 Color: SV_Target0;
    float4 Normal: SV_Target1;
};

PS_OUTPUT PS(float4 p: SV_Position, float2 uv : TEXCOORD0)
{
      PS_OUTPUT output;
      output.Color = //Set first output
      output.Normal= //Set second output
      return output;
}

在DirectX11中,您不需要将深度写入常规缓冲区,只需使用深度缓冲区即可。
对于像素/计算着色器同步,您不能在同一设备上同时运行像素着色器和计算着色器,因此当绘制调用完成时,纹理已准备好在计算中进行分派。

谢谢。特别是那些链接非常有用,你无法想象它们对我有多大帮助。再次感谢。顺便问一下,“depth buffer”指的是像素着色器的SV_Depth值吗?(我好像在某个地方读到过,但不太确定。)+1和接受的答案。 - l3utterfly
没问题。SV_Depth 是用于编写自己的深度值的,它在某些情况下很有用(来自 PixelShader 光线追踪器的深度,或一些纹理数组操作)。我的意思是 DepthStencil 资源也可以绑定为 Shader Resource View,所以既然您还将绑定一个深度缓冲区到场景中,您也可以重复使用它,这是免费的 :) - mrvux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接