是否可以实现自定义深度缓冲区值,以便我可以实现非传递排序?例如
Red > Green
Green > Blue
Blue > Red
我想这将在片段着色器或其他东西中实现,只有当像素位于现有像素之上时,才根据上面的架构写入像素。请注意,由于它是非传递性的,因此不可能为每种颜色分配单个数值并保留顺序。
换句话说,我想要一个自定义 z 缓冲区,其中每个元素都是非传递类型。因此,z 缓冲区将是一个充满 Red
、Green
或 Blue
值的大片。为每个数字分配一个数字,然后根据上面的模式进行比较,以确定哪一个位于顶部。如果所有三种颜色都在同一个片段上,那么我不在乎哪一种颜色在上面。
下图说明了我的意思(这就是我希望它能够做到的):
(图片来自维基百科)
我想要的东西在 OpenGL 中是否可行,或者我是否太过违背原则?如果可能的话,性能下降会有多严重?
最佳答案
您想要做的事情不仅是可能的,而且相对快速且简单。我在我的游戏中实现了类似的东西,以便 render the penrose triangle .
诀窍是使用 stencil buffer而不是深度缓冲区。实际上,您可以通过多种不同的方式使用模板缓冲区来实现循环排序效果,具体取决于您的具体需求。我将在这里描述一种可能的算法:
- 在不进行模板测试的情况下绘制红色层,同时将
1
写入模板缓冲区。 - 使用模板测试
不等于1
绘制绿色层,同时将2
写入模板缓冲区。这将阻止它在已经绘制了红色的地方绘制,有效地将绿色置于红色“后面”。 - 使用模板测试绘制蓝色层
不等于2
。这将允许它绘制在红色之上,但不能绘制在绿色之上,从而有效地将其放置在它们之间.
相同的技术可以推广到 N 层,如下所示:
- for each layer X going front-to-back, from `N - 1` down to `0`
- draw layer X with stencil test `not equal to X + 1`, while writing `X` to the stencil buffer
其代码可能类似于:
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
for (int X = N - 1; X >= 0; --X) {
glStencilFunc(GL_NOTEQUAL, X + 1, 0xFF);
// drawLayer(X);
}
此算法仅保证层X
将与层(X - 1) % N
和(X + 1) % N
正确交互>。如果您想要更复杂的规则,则需要更复杂的算法。
请注意,使用 8 位模板缓冲区时,您的层数将被限制为 255 个。
另请注意,由于该算法不使用深度缓冲区,因此它也适用于 3D 场景 - 只需像平常一样启用深度测试,然后您就可以开始比赛了。这就是我能够以 3D 形式渲染彭罗斯三角形示例的方式。
关于opengl - 非单调深度缓冲区; OpenGL 中的循环重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66301659/