模板缓冲区

模板缓冲区 用于屏蔽图像中的像素,以产生特殊效果。 掩码决定是否绘制像素。 这些特殊效果包括合成、贴花、溶解、渐变和滑动、轮廓和剪影、以及双面模板。 下面显示了一些更常见的效果。

模板缓冲区在像素级别启用或禁用对渲染目标表面的绘制。 在最基本的级别,它使应用程序能够屏蔽呈现的图像部分,以便不显示它们。 应用程序通常使用模板缓冲区来实现特殊效果,例如溶解、贴图和描边。

模板缓冲区信息嵌入 z 缓冲区数据中。

模板缓冲区的工作原理

Direct3D 在像素级别对模板缓冲区的内容执行测试。 对于目标图面中的每个像素,执行测试时,它使用模板缓冲区中的相应值、模板参考值和模板掩码值。 如果测试通过,Direct3D 将执行作。 使用以下步骤执行测试。

  1. 使用模具掩码对模具引用值执行按位 AND 运算。
  2. 对具有模具掩码的当前像素执行模具缓冲区值的按位 AND 运算。
  3. 使用比较函数将步骤 1 的结果与步骤 2 的结果进行比较。

上述步骤显示在以下代码行中:

(StencilRef & StencilMask) CompFunc (StencilBufferValue & StencilMask)
  • StencilRef 表示模板参考值。
  • 模板掩码表示模板掩码的值。
  • CompFunc 是比较函数。
  • 模板缓冲区值是当前像素的模板缓冲区的内容。
  • 符号&表示按位与运算。

如果模板测试通过,则当前像素将写入目标表面,否则将被忽视。 默认比较行为是更新像素,无论每个按位操作的结果如何。可以通过更改枚举类型的值来选择所需的比较函数,从而改变此行为。

应用程序可以自定义模板缓冲区的操作。 它可以设置比较函数、模板掩码和模板参考值。 它还可以控制 Direct3D 在模板测试通过或失败时所采取的动作。

合成

您的应用程序可以使用模板缓冲区将 2D 或 3D 图像合成到 3D 场景中。 模板缓冲区中的掩码用于遮蔽渲染目标表面的区域。 然后,可以将存储的 2D 信息(如文本或位图)写入遮挡区域。 或者,应用程序可以将其他 3D 基元渲染到渲染目标图面的模板掩码区域。 它甚至可以呈现整个场景。

游戏通常将多个 3D 场景组合在一起。 例如,驾驶游戏通常显示后视镜。 后视镜展示了驾驶员后方的3D场景视图。 它实质上是一个与司机的前视景相叠加的第二个3D场景。

印贴

Direct3D 应用程序使用贴图来控制从特定基元图像绘制到渲染目标表面的像素。 应用程序将贴花应用于基元的图像,使共面多边形能够正确呈现。

例如,将轮胎标记和黄色线条应用于道路时,标记应直接显示在道路顶部。 但是,标记和道路的 z 值是相同的。 因此,深度缓冲区可能不会在两者之间产生干净分隔。 后基元中的某些像素可能呈现在前基元的顶部,反之亦然。 生成的图像显示为从帧到帧闪闪发光。 这种效果被称为 z轴争斗闪烁

若要解决此问题,请使用模板来屏蔽后图元部分,其中会出现贴花。 关闭z缓冲,并将前图元的图像渲染到呈现目标表面的已掩蔽区域。

尽管可以使用多个纹理混合来解决此问题,但这样做会限制应用程序可以产生的其他特殊效果的数量。 使用模板缓冲区应用贴花,可以释放纹理混合阶段用于其他效果。

溶解、淡化和滑动

越来越多的应用程序采用电影和视频中常用的特殊效果,例如解散、轻扫和淡化。

在溶解中,一个图像逐渐被另一个图像在顺畅的帧序列中替换。 尽管 Direct3D 提供了使用多个纹理混合来实现相同效果的方法,但使用模板缓冲区进行溶解的应用程序可以利用纹理混合功能来实现其他效果,同时进行溶解。

当应用程序执行解体时,它必须呈现两个不同的图像。 它使用模板缓冲区来控制将每个图像中的像素绘制到渲染目标表面。 可以定义一系列模板掩码,并在连续帧中将其复制到模板缓冲区。 或者,您可以定义第一帧的基础模板掩码,然后逐步更改它。

在溶解开始时,应用程序设置模板函数和模板掩码,以便起始图像中的大多数像素通过模板测试。 结束图像中的大多数像素无法通过模板测试。 在连续的帧中,模板掩码会更新,从而使起始图像中通过测试的像素越来越少。 随着帧的进展,结束图像中未通过测试的像素越来越少。 通过这种方式,应用程序可以使用任意解散模式执行解体。

淡入或淡出是一种特殊情况下的解散。 淡入时,模板缓冲区用于从黑或白图像溶解到 3D 场景的渲染。 淡出正好相反,您的应用程序从渲染 3D 场景开始,逐渐过渡为黑色或白色。 可以使用你想要的任意模式来实现淡化。

Direct3D 应用程序使用类似的轻扫技术。 例如,当应用程序执行从左向右轻扫时,结束图像将逐渐从左向右在起始图像上滑动。 与解体一样,必须定义一系列模具掩码,这些掩码加载到连续帧上的模具缓冲区中,或连续修改起始模具掩码。 模板掩码用于禁止写入起始图像中的像素,并允许写入结束图像中的像素。

轻扫比消散更复杂,因为应用程序必须按照轻扫的相反顺序从结束图像中读取像素。 也就是说,如果轻扫从左向右移动,应用程序必须从右到左读取结束图像中的像素。

轮廓和剪影

您可以使用模板缓冲区来实现更抽象的效果,例如描边和剪影效果。

如果应用程序将模板掩码应用于一个与原形状相同但略小的基元图像,生成的图像将仅包含这个基元的轮廓。 然后,应用程序可以使用纯色填充图像的模板遮罩区域,使基元具有浮雕效果。

如果模板掩码的大小和形状与您正在渲染的基元相同,则生成的图像会在基元应所在的位置出现一个孔。 然后,应用程序可以使用黑色填充空白处,以生成原始图形的剪影。

双面模板

阴影体积用于通过模板缓冲区绘制阴影。 应用程序通过计算遮挡几何体的轮廓边缘,并将其从光源挤出形成一组3D体积,从而计算阴影体积。 然后将这些卷两次渲染到模板缓冲区中。

第一个渲染绘制正向多边形,并递增模板缓冲区值。 第二次渲染绘制阴影体积的背面多边形,并递减模板缓冲区的值。 通常,所有递增和递减的值都会相互抵消。然而,场景已经使用常规几何图形进行渲染,导致在渲染阴影体积时,某些像素未通过 z 缓冲区测试。 模板缓冲区中剩余的值对应于阴影中的像素。 这些剩余的模板缓冲区内容用作掩码,将一个大型的全黑矩形通过 alpha 混合到场景中。 当模板缓冲区充当掩码时,结果是使阴影中的像素变暗。

这意味着每个光源绘制两次阴影几何图形,从而给 GPU 的顶点吞吐量施加压力。 双面模板功能旨在缓解这种情况。 在此方法中,有两组模板状态(如下所示),一组用于正面三角形,另一组用于背面三角形。 这样,每个阴影体积(每个光源)只绘制一个通道。

深度和模板缓冲区