4

我有一些用 OpenGL 编写的渲染代码。我使用模板缓冲区来实现剪辑:


    //Let's assume this is done in render loop.

    if(!already_created())
    {
      create_stencil_attachment_and_bind_to_FB_as_depth_stencil_attachment();
    }

    glEnable(GL_STENCIL_TEST);
    glColorMask(0,0,0,0);
    glDepthMask(0);
    glClearStencil(0);
    glClear(GL_STENCIL_BUFFER_BIT);
    glStencilFunc(GL_ALWAYS,1,1);
    glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);

    render_to_stencil();

    glColorMask(1,1,1,1);
    glDepthMask(1);
    glStencilFunc(GL_EQUAL,1,1);
    glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);

    render_with_clipping();

    glDisable(GL_STENCIL_TEST);

现在,问题是,我需要将此代码移植到 DX11。我在 MSDN 上看到了示例和一些不错的教程。我最终得到了这个逻辑:

1. 创建 ID3D11Texture2D,格式 = DXGI_FORMAT_D32_FLOAT_S8X24_UINT。
2. 创建 ID3D11DepthStencilState 用于渲染到 stencil: //我们称之为 DS_RENDER
   - 对于正面和背面:
     - op = D3D11_STENCIL_OP_REPLACE 适用于所有 3 种情况
     - 函数 = D3D11_COMPARISON_ALWAYS
   - 深度启用 = FALSE
   - StencilEnable = TRUE
   - StencilReadMask = 0xFF
   - StencilWriteMask = 0xFF
3.为之前创建的状态和纹理创建ID3D11DepthStencilView。//我们称之为DSV
4. 创建 ID3D11DepthStencilState 用于使用模板作为“输入”: //我们称之为 DS_CLIP
   - 对于正面和背面:
     - op = D3D11_STENCIL_OP_KEEP 适用于所有 3 种情况
     - 功能 = D3D11_COMPARISON_EQUAL
   - 深度启用 = FALSE
   - StencilEnable = TRUE
   - StencilReadMask = 0xFF
   - StencilWriteMask = 0xFF

现在,我不确定如何将模板设置为目标或输入。

MSDN 说:

`pDevice->OMSetDepthStencilState(pDSState, 1);`

`pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, pDSV);`

如果我正确理解这些调用,第一个设置模板状态,而第二个将 pDSV 作为附加“附件”绑定到渲染目标。那是对的吗?

如果是这样,这会按我的预期工作吗?



    pDevice->OMSetDepthStencilState(DS_RENDER, 1);
    pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, DSV);

    render_geometry_to_stencil_buffer();

    pDevice->OMSetDepthStencilState(DS_CLIP, 1);

    render_geometry_with_clipping();

    pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, NULL); //Does this disable stencil testing?

提前感谢您的每一个帮助或有用的提示。

4

1 回答 1

1

如果您只想渲染到模板,请使用(设置您的写入状态):

pd3dDeviceContext->OMSetRenderTargets(0, NULL, DSV);

您不需要渲染到颜色缓冲区,因此无需绑定它。

然后渲染到您的目标并启用模板测试,请使用:

pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, DSV);

当你使用 stencil 作为输入时,一个很简单的事情也是设置 StencilWriteMask = 0; 所以它永远不会写入它(这是你想要渲染剪裁几何的东西)。

如果您使用:

pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, NULL); 

您确实会禁用任何形式的深度/模板测试(不再有深度限制,因此 DepthStencilState 将完全没有效果)。

此外,我会使用 DXGI_FORMAT_D24_UNORM_S8_UINT 作为深度格式(个人偏好),它将完全适合您的用例并消耗更少的内存。

希望有帮助。

于 2013-10-11T16:08:57.520 回答