1

我正在尝试使用模板缓冲区ID3D11Texture2D将一个纹理的一部分覆盖在另一个纹理上。我计划通过在模板缓冲区上绘制所需的形状然后复制纹理来做到这一点。请推荐一些很好的教程,其中包含 2D 纹理的示例代码,用于学习模板缓冲区的使用。(或这样做的一些替代方式)

4

1 回答 1

15

模板掩模 101:

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

*不遵守这些规则中的大多数通常会导致最差的模板性能:您的像素着色器为每个像素执行,而不是对模板遮罩的像素执行早期拒绝。此外,在较旧的 Geforce 卡上,这也可能导致所有后续绘图调用的早期深度拒绝中断,直到下一帧或深度缓冲区和模板被清除后才会修复。

模板遮罩实际上很容易生成:

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

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

  • (理想情况下)还禁用深度写入
  • 绘制需要模板遮罩的效果
于 2011-06-20T23:44:59.947 回答