我对 DirectX 和图形编码很陌生。我正在使用 SlimDX 进行实施。我正在绘制一张地图,显示特定区域的数据的可视化表示。我要做的就是采用状态形状,如果像素在该区域内,则绘制它,否则不绘制。这基本上就是模板,对吧?但我无法弄清楚我应该如何为模板缓冲区设置该多边形。或者这不是模板缓冲区的用途?
1 回答
你很接近......这是创建模板缓冲区的情况之一。唯一的问题是,如果您想在此处进行真正的模板缓冲,您需要将深度模板缓冲区设置为可读纹理(对 GPU),因为您需要读取模板缓冲区才能弄清楚需要丢弃哪些像素。有一种“更简单”的方法可以做到这一点,这涉及欺骗深度缓冲区为我们执行读取/比较/丢弃步骤。
在正常的 3D 渲染中,我们将所有对象绘制到后台缓冲区。当我们这样做时,GPU 使用深度模板缓冲区来确定哪些像素“落后于”其他先前绘制的像素。一个像素的最远距离是 Z 值 1.0f,而最接近的像素是 Z 值 0.0f。我们能做的就是将深度模板缓冲区清零,将深度比较设置为始终通过,当我们绘制形状时,我们的顶点着色器将要绘制的顶点的 Z 值设置为 W。当我们最终进行透视时除(光栅化的一部分),我们得到一个 1.0f 的 Z 坐标,它可能是最远的。在我们的第二个渲染过程中,渲染可以正常进行,GPU 将切除不在形状区域内的绘制数据的像素。
换一种更简单的方法:在这种方法中,我们有效地将一张纸放在场景前面,上面有一个孔,与我们的模板形状完全相同。当实际场景被绘制时,它会在除我们的形状所在的位置(“孔”)之外的所有位置绘制在模板“后面”,从而形成精确的切口。在正常的 3D 渲染中,事物通常介于 0 和 1 之间。所有这些对象都将正常绘制,但模板区域之外的任何内容都将无法通过深度测试(因为我们将所有内容设置为零,除了形状所在的位置)并且剪辑。
此方法需要两次渲染,一次将模板形状渲染到深度缓冲区,第二次将数据颜色渲染到后台缓冲区。
请注意,如果您计划做的比问题描述中的更多,则此方法可能需要调整。它适用于简单的场景,但对于更复杂的场景,您需要阅读模板缓冲区。这在 C/C++ 中是一个很好的概述,并且直接适用于 SlimDX,因为 SlimDX 只是对原生 C/C++ API 的一个薄包装。您可以使用它来交叉引用 C/C++ 对象和结构与 SlimDX 中的 C# 对象和结构(查看类/结构文档页面中的非托管对应字段)。
此外,如果场景都以相同的深度级别渲染,此方法将失败(尽管无论如何都不应该这样做,因为 Z-fighting 会一直踢你的椅子)。在 3D 中制作 2D 图形的更好方法是将组件放置在不同的 Z 轴“层”上,并使用正交投影在 3D 中绘制它们(这可以防止由于透视而缩小更远的图像)。
最后,由于我有一段时间没有编写像素着色器代码,我不太记得在像素着色器中向 Z 写入 1 是否会导致将 1 写入深度缓冲区。我很确定确实如此,但在我给出可靠的建议之前,我需要确认这一点。如果是这样,那么在像素着色器中设置该点的 Z 值可以代替在顶点着色器中将 W 分配给 Z。