【问题标题】:Using stencil buffer in Direct3D在 Direct3D 中使用模板缓冲区
【发布时间】:2011-09-05 05:49:02
【问题描述】:

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

【问题讨论】:

  • 请有人给我一个链接,指向在Direct3D 中使用Stencil Buffer 的好教程,其中包含一些基本示例,例如屏蔽像素。

标签: textures direct3d stencil-buffer


【解决方案1】:

模板蒙版 101:

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

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

模板掩码实际上很容易生成:

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

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

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

【讨论】:

  • 谢谢,如果您能给我一些代码示例,说明我们如何在 D3D11 中使用模板缓冲区来实现一些基本效果,将会很有用。
猜你喜欢
  • 2012-07-08
  • 1970-01-01
  • 2018-11-17
  • 2012-03-13
  • 2016-05-03
  • 2020-11-27
  • 2020-04-19
  • 2012-07-11
  • 2016-01-31
相关资源
最近更新 更多