仅使用模板测试进行遮挡查询

时间:2014-10-16 17:40:22

标签: opengl sdl stencil-buffer occlusion-culling

如果我首先在相机和待测对象之间严格控制障碍物集时完全禁用深度测试,那么遮挡查询是否仍然有效? 这是一种提高性能的尝试,因为从逻辑上讲,如果封堵器后面没有遮挡物,我就不需要进行复杂的z测试。

我使用以下命令初始化颜色/深度/模板缓冲区:

SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
...
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

glDisable(GL_CULL_FACE);

glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);

glEnable(GL_STENCIL_TEST);
glStencilMask(0x00000001);
...
glClear(GL_STENCIL_BUFFER_BIT);

2 个答案:

答案 0 :(得分:2)

最具决定性的文件是最新的OpenGL规范。从OpenGL 4.5规范,第476页上的“#34; 17.3.7遮挡查询"”(我强调添加):

  

遮挡查询使用查询对象来跟踪通过深度测试的碎片或样本数量。

     

当遮挡查询处于活动状态时,对于通过深度测试的每个片段,样本传递计数会递增。

因此,真正的问题是:"通过深度测试"意思?如果没有深度测试,像素是否通过深度测试?模板测试如何发挥作用?

关键是模板测试在深度测试之前应用,这是规范中定义的行为。因此,只有通过模板测试的片段才会经过深度测试,因此将在遮挡查询中计算。换句话说,只计算通过两者模板和深度测试的片段。

一种绝对有效的方法是启用深度测试,让所有碎片通过深度测试。然后,这将计算通过模板测试的所有片段。用于此的设置是:

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);

glEnable(GL_STENCIL_TEST);
...

现在,它是否也可以在没有深度缓冲区或禁用深度缓冲区的情况下按预期工作?第一部分" 17.3.6深度缓冲测试":

  

如果没有深度缓冲区,就好像深度缓冲区测试总是通过

在这种情况下,答案是肯定的,您可以使用没有深度缓冲区的遮挡查询,它将计算通过模板测试的片段。

第二种情况在前面的#34; 17.3.6深度缓冲测试"

部分中有所介绍。
  

禁用时,深度比较和后续可能更新的深度缓冲区值被绕过,片段将传递给下一个操作

图17.1在规格显示"遮挡查询"作为"深度缓冲测试"之后的下一个操作。因此,如果禁用深度测试,则所有通过早期测试(包括模板)的片段都将被遮挡查询计算。

最后的答案是:,您只需使用模板测试即可使用遮挡查询。

致谢:根据@jozxyqk和@ user2464424

的反馈修订最新版本

答案 1 :(得分:1)

来自www.opengl.org/registry/specs/ARB/occlusion_query.txt

  

此扩展程序解决了这两个[HP_occlusion_test]问题。它返回为它   结果通过深度和模板测试的样本数量

     

...

     

我们在哪个阶段计算样品?

     

已解决:我们在两者深度和之后立即计算      模板测试,即通过两者的样品。注意深度      在模板测试之后进行测试,所以说它是      通过深度测试的数量就足够了;虽然经常这样      在概念上有助于将深度和模板测试视为      因为深度测试的结果影响了      使用模板操作。

来自www.opengl.org/registry/specs/ARB/occlusion_query2.txt

  

此扩展通常会向ARB_occlusion_query

添加一个布尔遮挡查询

关闭深度测试后,我假设所有碎片都通过了。 从上面可以看出,可以单独依靠模板测试来影响遮挡查询结果,这与opengl.org/wiki中的以下内容不一致。

  

模板测试,alpha测试或片段着色器丢弃与查询无关

扩展程序未提及discard。 GL 4.5 core / compat规范中的遮挡查询部分仅提及通过深度测试的计数片段。 如果片段没有进行深度测试,那么我想它不会被认为是通过

一点注意事项,但我认为它也值得一提early fragment test