【问题标题】:How to render a 2D UI on top of a 3D scene before rendering the 3D scene?如何在渲染 3D 场景之前在 3D 场景之上渲染 2D UI?
【发布时间】:2021-01-04 11:18:21
【问题描述】:

我有一个包含 2D 叠加层的 2D 纹理。纹理本身大部分是空白(透明),有一些部分包含一些数据。

我目前所做的是渲染整个 3D 场景,禁用深度缓冲区并在其顶部渲染 2D 四边形:

 // render 3D scene
 context->OMSetDepthStencilState(_noDepthTestState.Get(), 1); // disable depth test
 // render 2D quad on top of the whole viewport
 context->OMSetDepthStencilState(nullptr, 1); // restore default

_noDepthTestState 变量是使用以下描述符创建的 ID3D11DepthStencilState:

   D3D11_DEPTH_STENCIL_DESC desc{};
   desc.DepthEnable = false;
   desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
   desc.DepthFunc = D3D11_COMPARISON_LESS;
   desc.StencilEnable = true;
   desc.StencilReadMask = 0xFF; 
   desc.StencilWriteMask = 0xFF;
   desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
   desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
   desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
   desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
   desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
   desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
   desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
   desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

我想在渲染 3D 场景之前在渲染 2D 叠加四边形,并且 3D 对象只会在 2D 叠加为空白的地方绘制。

有没有一种有效的方法来实现这种行为?深度/模板状态的正确配置是什么?

【问题讨论】:

  • 听起来您可以将叠加层视为 UI 元素。首先渲染 3D 场景,然后将叠加层渲染为精灵。您甚至可以将剪辑空间用于顶点位置,然后您可以将屏幕像素值用于角落。 x=(x/viewport.width)*2-1; 和 y=-((y/viewport.height)*2-1).

标签: directx directx-11 direct3d direct3d11


【解决方案1】:

这取决于渲染主 3D 场景的方式。

假设您不使用模板缓冲区,并且您使用 D3D11_COMPARISON_LESS 深度比较,请按以下方式绘制四边形。

您的顶点着色器应输出四边形顶点 [ ±1, ±1, 0, 1 ]。这使得 GUI 最接近相机,早期 Z 拒绝应该在 PS 阶段之前剪辑 3D 场景中的被遮挡像素,节省一些 GPU 资源(我假设这就是你要先渲染 2D 的原因)。

您的像素着色器应该从您的 GUI 纹理中读取,将 alpha 与某个阈值进行比较,如果它足够小,请调用 discard。丢弃的像素不会改变任何缓冲区,无论是颜色还是深度/模板。

如果您的 GUI 由轴对齐的矩形组成,或者您不使用 MSAA,这将可以正常工作。但是,如果您确实有 GUI 的弯曲/对角边缘,并且使用 MSAA,您将不会对结果感到满意。解决这个问题是可能的,但要复杂得多。在渲染 GUI 纹理时,您需要以某种方式生成每个像素的 SV_Coverage 值。

【讨论】:

    猜你喜欢
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2011-05-30
    • 1970-01-01
    相关资源
    最近更新 更多