C ++,OpenGL Z-buffer prepass

时间:2010-12-25 20:06:23

标签: c++ opengl occlusion-culling

我正在制作一个简单的体素引擎(想想Minecraft),目前我正在摆脱被遮挡的面孔以获得一些宝贵的fps。我没有在OpenGL中进行过很多实验,也不太了解glColorMask魔法是如何工作的。

这就是我所拥有的:

// new and shiny
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// this one goes without saying
glEnable(GL_DEPTH_TEST);

// I want to see my code working, so fill the mask
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

// fill the z-buffer, or whatever
glDepthFunc(GL_LESS);
glColorMask(0,0,0,0);
glDepthMask(GL_TRUE);

// do a first draw pass
world_display();

// now only show lines, so I can see the occluded lines do not display
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

// I guess the error is somewhere here
glDepthFunc(GL_LEQUAL);
glColorMask(1,1,1,1);
glDepthMask(GL_FALSE);

// do a second draw pass for the real rendering
world_display();

这有点奏效,但是一旦我改变相机位置,世界开始消失,我看到越来越少的线条,直到什么都没有。

3 个答案:

答案 0 :(得分:9)

听起来你没有清除深度缓冲区。

当您尝试使用glDepthMask(GL_TRUE);清除深度缓冲区时,需要启用深度书写(通过glClear)。您可能仍然从前一帧禁用它,导致所有清除在子序列帧中为无操作。只需在glDepthMask之前移动glClear来电。

答案 1 :(得分:8)

glColorMask和glDepthMask确定帧缓冲区的哪些部分实际写入。

早期Z剔除的想法是,首先仅首先渲染深度缓冲部分 - 实际节省来自将几何体分类到远处,以便GPU可以快速丢弃被遮挡的碎片。然而,在绘制Z缓冲区时,您不想绘制颜色分量:这允许您切换着色器,纹理,即简言之,计算量很大。

警告语:早期Z仅适用于不透明几何体。实际上,整个深度缓冲算法仅适用于不透明的东西。一旦你进行混合,你就必须远近排序,不要使用深度缓冲(为算法搜索“顺序无关透明度”以克服相关问题)。

如果您有任何混合的东西,请将其从“早期Z”阶段移除。

在第一遍中你设置了

glDepthMask(1); // enable depth buffer writes
glColorMask(0,0,0); // disable color buffer writes
glDepthFunc(GL_LESS); // use normal depth oder testing
glEnable(GL_DEPTH_TEST); // and we want to perform depth tests

完成Z传递后,您可以稍微更改设置

glDepthMask(0); // don't write to the depth buffer
glColorMask(1,1,1); // now set the color component

glDepthFunc(GL_EQUAL); // only draw if the depth of the incoming fragment
                       // matches the depth already in the depth buffer

GL_LEQUAL也完成了这项工作,但也让片段比深度缓冲区中的片段更接近。但是由于没有更新深度缓冲区,因此每次在那里绘制某些东西时,原点和存储深度之间的任何内容都会覆盖它。

主题略有改变是在之后的多个延迟着色过程中使用'早期Z'填充的深度缓冲区作为几何缓冲区。

要保存更多几何图形,请查看遮挡查询。使用遮挡查询,您可以向GPU询问有多少(如果有任何碎片)通过所有测试。这是一个体素引擎,你可能正在使用八叉树或Kd树。在遍历分支之前绘制树枝的空间分割面(使用glDepthMask(0),glColorMask(0,0,0))会告诉您,该分支中的任何几何体是否完全可见。结合近乎远程排序的遍历和树上的(粗略)平截头体裁剪将为您带来巨大的性能优势。

答案 2 :(得分:5)

z-pre pass可以与半透明物体一起使用。如果它们是半透明的,请不要在预处理中渲染它们,然后进行zsort和渲染。