我想实现一个OpenGL场景(OpenGL ES 2.0),其中深度测试仅在选定的三角形之间启用。
更具体地说:假设我们有四个三角形要渲染。应该在三角形1和2之间以及三角形3和4之间启用深度测试,但是在三角形1和3和三角形2和4之间都不启用。换句话说:是否有可能在两对三角形内进行深度测试,而不是在它们之间进行深度测试(以提高性能,当两对三角形的渲染序列可以更容易地在软件层面上计算时)?
根据opengl.org的常见问题解答(见页面底部- 12.080),一个场景可以被划分为区域,但描述没有足够的细节让我理解这是如何实现的。
我想到了几个可能性。
每帧多次清除深度缓冲
最简单的方法可能是在渲染一组对象后清除深度缓冲区。对于问题中的情况:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw triangle 1.
// Draw triangle 2.
glClear(GL_DEPTH_BUFFER_BIT);
// Draw triangle 3.
// Draw triangle 4.
因为你不会在1/2和3/4之间进行深度测试,三角形3和4将被绘制在三角形1和2的顶部,如果它们重叠,与它们的相对深度无关。
该解决方案的一个限制是您必须将每个组的几何图形画在一起。例如,如果出于某种原因,您不能使用这个,如果您以1,3,2,4的顺序呈现三角形。
具有多个深度缓冲区的FBO渲染
另一个选择是使用多个深度缓冲区。做到这一点的唯一方法是使用fbo的屏幕外渲染。在这种情况下,你可以创建多个深度渲染缓冲区。在每次绘制调用之前,你可以将你可以使用的深度缓冲区附加到FBO上。
在你完成将帧呈现给FBO之后,你将不得不将内容复制到默认的framebuffer。
这样做的好处是,只要每次切换深度缓冲区,就可以按任何顺序绘制三角形:
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuf1);
// draw triangle 1
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuf2);
// draw triangle 3
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuf1);
// draw triangle 2
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuf2);
// draw triangle 4
然而,切换渲染缓冲区可能是一个相当昂贵的操作,所以你仍然希望最小化你切换深度缓冲区的次数。
所以这种方法给了你更多的灵活性,但我通常认为它效率较低。你仍然需要清除所有深度缓冲区,所以你有多个深度清除操作,就像在第一种方法。此外,切换深度缓冲区和将颜色缓冲区复制到帧末尾的默认framebuffer也需要开销。
深度测试配置适用于每个绘制调用中的每个三角形;如果你想要不同的设置,你需要进行多个draw调用。