在Direct3D中使用模板缓冲区

时间:2011-05-31 06:30:26

标签: textures direct3d stencil-buffer

我正在尝试在ID3D11Texture2D上使用模板缓冲区来覆盖另一个纹理上的一个纹理的一部分。我计划通过在模板缓冲区上绘制所需的形状然后复制纹理来完成此操作。请提供一些有关2D纹理示例代码的优秀教程,以学习模板缓冲区的使用。 (或者另外一种方式)

1 个答案:

答案 0 :(得分:14)

模板掩模101:

  • 所有主流GPU都使用8位模板缓冲区,并且它们与深度缓冲区绑定,因此您必须选择包含模板的缓冲区格式(主要是D24S8)
  • 在每帧开始时清除深度和模板,以避免帧间性能问题*(请参阅下面的注释)
  • 除非您知道自己在做什么,否则请始终使用0xFF作为读写掩码。
  • 出于性能原因,在进行模板读取测试时没有启用深度写入
  • 出于性能原因,如果可能,请将模板读取测试限制为== 0和!= 0,并清零(
  • 如果您正在使用D3D9,您可以使用剪刀和清除模板缓冲区,这比手动渲染四元组以将缓冲区设置回零要快得多。
  • 无法在着色器中访问模板信息,因此后处理效果无法确定相邻像素的模板状态,而掩模也不在正常的渲染目标中并作为纹理采样。
  • 可以从以下条件修改模板缓冲区值:
    1. 模板测试失败
    2. 深度测试失败
    3. 模板和深度测试均已通过
  • 无论哪个条件首先决定动作,都可以
    1. 保持(仅保留模板值)
    2. 替换(用'stencilref'值替换模板值)
    3. 递增(向当前缓冲区添加1)
    4. 减量(模板缓冲区中的子1)
    5. 零(将值设置为直接为零,当其他条件之一需要使用当前的stencilref值时非常有用)

*如果不遵循大多数这些规则,通常会导致模板性能最差:您的像素着色器针对每个像素执行,而不会对模板蒙板像素执行早期拒绝。此外,对于较旧的Geforce卡,这也会导致所有后续绘制调用的早期深度拒绝的中断,直到下一帧或深度缓冲器&模板被清除。

模板蒙版实际上很容易生成:

  • 清除模板缓冲区
  • 启用模板写入的模板状态(使用stencilref 1或'increment'代替'keep''替换')
  • 绘制多边形。请注意,在着色器中使用“discard”将阻止模板更新,这是将纹理加载到模板缓冲区中的方式(但仅作为二进制掩码)

  • 禁用模板写入,启用模板测试

  • (理想情况下)也禁用深度写入
  • 绘制需要模板遮罩的效果