2

如果事先知道障碍物集严格位于相机和要测试的对象之间,如果我完全禁用深度测试,遮挡查询是否仍然有效?这是一种提高性能的尝试,因为从逻辑上讲,如果没有遮挡物位于被遮挡物后面,我不需要复杂的 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);
4

2 回答 2

2

最具决定性的文档是最新的 OpenGL 规范。来自 OpenGL 4.5 规范,第 476 页的“17.3.7 遮挡查询”部分(重点由我添加):

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

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

因此,真正的问题就变成了:“通过深度测试”是什么意思?如果没有深度测试,像素是否通过深度测试?模板测试是如何发挥作用的?

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

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

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);

glEnable(GL_STENCIL_TEST);
...

现在,它是否也可以在没有深度缓冲区或禁用深度缓冲区的情况下按需要工作?第一部分在“17.3.6 深度缓冲测试”部分的末尾回答:

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

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

第二种情况在前面的“17.3.6 深度缓冲测试”一节中有介绍:

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

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

最后的答案是:的,您可以通过模板测试来使用遮挡查询。

致谢:根据@jozxyqk 和@user2464424 的反馈修改了最新版本

于 2014-10-17T04:47:26.317 回答
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核心/兼容规范中的遮挡查询部分仅提及通过深度测试的计数片段。如果片段没有通过深度测试,那么我猜它不被认为是通过它

有点旁注,但我认为还值得一提的是早期的片段测试

于 2014-10-17T03:19:39.523 回答