opengl - 非单调深度缓冲区; OpenGL 中的循环重叠

标签 opengl glsl shader depth-buffer

是否可以实现自定义深度缓冲区值,以便我可以实现非传递排序?例如

Red > Green
Green > Blue
Blue > Red

我想这将在片段着色器或其他东西中实现,只有当像素位于现有像素之上时,才根据上面的架构写入像素。请注意,由于它是非传递性的,因此不可能为每种颜色分配单个数值并保留顺序。

换句话说,我想要一个自定义 z 缓冲区,其中每个元素都是非传递类型。因此,z 缓冲区将是一个充满 RedGreenBlue 值的大片。为每个数字分配一个数字,然后根据上面的模式进行比较,以确定哪一个位于顶部。如果所有三种颜色都在同一个片段上,那么我不在乎哪一种颜色在上面。

下图说明了我的意思(这就是我希望它能够做到的):

enter image description here

(图片来自维基百科)

我想要的东西在 OpenGL 中是否可行,或者我是否太过违背原则?如果可能的话,性能下降会有多严重?

最佳答案

您想要做的事情不仅是可能的,而且相对快速且简单。我在我的游戏中实现了类似的东西,以便 render the penrose triangle .

诀窍是使用 stencil buffer而不是深度缓冲区。实际上,您可以通过多种不同的方式使用模板缓冲区来实现循环排序效果,具体取决于您的具体需求。我将在这里描述一种可能的算法:

  1. 在不进行模板测试的情况下绘制红色层,同时将 1 写入模板缓冲区。
  2. 使用模板测试不等于1绘制绿色层,同时将2写入模板缓冲区。这将阻止它在已经绘制了红色的地方绘制,有效地将绿色置于红色“后面”。
  3. 使用模板测试绘制蓝色层不等于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/

相关文章:

类似于 MeshLab 的可视化工具的 OpenGL 着色器为每张脸着色

OpenGL 调色板交换着色器?

c++ - GLSL 类型不一致

opengl - 如何处理 OpenGL 索引缓冲区数组中的多个纹理以与数据着色器一起使用?

opengl - 来自高度图的法线图

c++ - 基于uniform int在GLSL中声明数组

opengl - 使用几何着色器进行实例化

android - 使用 glMultMatrixf 进行翻译,以及何时规范化

c++ - OpenGL 纹理未按定义出现

OpenGL顶点着色器转换和输出