当点具有相同深度时,OpenGL 深度缓冲变慢

3
我正在开发一个涉及绘制大量重叠四边形到屏幕的2D游戏。前后顺序并不重要。
如果我为每个四边形设置从0开始递增的z值,并设置glDepthFunc(GL_LESS),就可以获得相当不错的速度提升,这是可以预期的。 这样做是为了避免绘制那些完全或部分被其他四边形遮挡住的四边形。 因此,我使用类似以下方式绘制四边形:
float small = (float(1)/1000000);
for (int iii = 0; iii < 100000; iii++) {
    freeSpace = bullets[iii]->draw(opengl, freeSpace, iii*small);
}

然而,由于我不使用z值来表示实际深度,因此我应该能够执行以下操作:

for (int iii = 0; iii < 100000; iii++) {
    freeSpace = bullets[iii]->draw(opengl, freeSpace, 0.0f);
}

或者在着色器中将z值设置为0.0f。(第三个参数是z值,并最终被不变地设置为gl_position。)

奇怪的是,第二种方法(每次将z值设置为0.0f)的帧率几乎不到前一种方法的一半。

为什么会这样?它们都使用glDepthFunc(GL_LESS)和

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 100000*(2*3));

同样的道理,我认为每次将z设置为0.0f会更快。为什么不这样做呢?


你清除深度缓冲区的值是多少? - Roger Allen
不是,但它小于1(这是深度缓冲区被清除的值)。因此,每个像素只被写入一次的想法就产生了。我可以使用GL_LEQUAL,但它的性能非常糟糕(与GL_LESS相同)。我的目标是尝试让深度缓冲区只允许每个像素只被绘制一次,以减少填充率要求。 - Ellipsis
深度缓冲区清除为默认值(我从未更改它)。因此,我相信它会清除为1.0f。 - Ellipsis
1个回答

3

我不确定,但我的猜测是原始体之间z值的微小差异使得zcull硬件起作用。这将在片段着色器处理之前剔除片段。除了避免片段着色器工作外,当片段到达深度缓冲区测试时,这种剔除可以以比正常z测试更快的速度发生。


啊,谢谢。听起来很有可能。我在片段着色器中进行了丢弃,所以我认为早期的z cull不可能发生。然而,正常的culling可能确实会发生。奇怪的是,当点具有and z值时它不会发生?我该如何解决这个问题?我的当前方法似乎很复杂。我应该使用模板缓冲区,还是让顶点着色器生成z值?无论如何,感谢您的回复。 - Ellipsis
如果您在片段着色器中杀死了片段,那么 zcull 硬件将无法使用,这也会影响其他 z 测试性能的提升。如果您可以避免进行片段着色器的杀死操作,您可能会发现显著的性能提升。 - Roger Allen
我必须将圆形绘制到屏幕上,因此似乎是不可避免的。我正在绘制纹理化的四边形圆形,无论如何,我都必须打开混合,这会导致减速,或者在片段着色器中丢弃所有 alpha 值为 0 的像素。还有其他(更好)的方法吗?我是否正确地认为,即使我在片段着色器中丢弃了像素,某种 zculling 仍在进行? - Ellipsis
我认为基本答案是——很复杂,所以没有简单的答案。您正在探索不同芯片将加速和优化不同部分的管道的部分。听起来您通常对图形管道中应该发生的事情有一个很好的想法。我建议只需尝试您的想法并探索设计空间以查看在您的卡上哪种方式最有效。 - Roger Allen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接