GLSL着色器:遮挡顺序和剔除

时间:2016-09-10 00:52:45

标签: opengl glsl depth-buffer culling occlusion-culling

我有一个GLSL着色器,在给定一组贝塞尔曲线(点的三维坐标)的情况下绘制三维曲线。绘图本身是按照我想要的方式完成的,除了遮挡不能正常工作,即在某些视点下,应该在最前面的曲线看起来仍然是遮挡的,反向的:曲线的一部分是假设的被遮挡的情况仍然可见。

为了说明,这里有一些屏幕截图的例子:

1 - 彩色曲线更接近相机,因此在此处正确渲染。 correct render

2 - 彩色曲线应该位于灰色曲线的后面,但它会呈现在顶部。 wrong render

我是GLSL的新手,可能不知道这种效果的合适术语,但我认为它是遮挡剔除(更新:它实际上表明了深度缓冲区的问题,术语混乱!)。我的问题是:在使用GLSL着色器时如何处理遮挡?我是否必须在着色器程序或其他地方处理它们?

关于我的代码,它有点长(加上我使用OpenGL包装器库),但主要步骤是:

  1. 在顶点着色器中,我计算gl_Position = ModelViewProjectionMatrix * Vertex;并将颜色信息进一步传递给几何着色器。
  2. 在几何着色器中,我获取4个控制点(lines_adjacency)及其相应的颜色,并生成一个遵循贝塞尔曲线的三角形条(我在贝塞尔曲线段之间使用了一些基本颜色插值)。
  3. 片段着色器也很简单:gl_FragColor = VertexIn.mColor;
  4. 关于OpenGL设置,我启用了GL_DEPTH_TEST,但它似乎没有我需要的东西。此外,如果我在场景上放置任何其他非着色器几何体(例如四边形),无论视点如何,曲线总是呈现在它的顶部。

    有关如何解决问题及其原因的任何见解和提示均值得赞赏。

    更新解决方案

    因此,正如我所知,最初的问题不是找到剔除算法,而是我没有正确处理z值的计算(参见接受的答案)。我还了解到,给定正确的深度缓冲设置,OpenGL可以正确处理遮挡,因此我不需要重新发明轮子。

    我搜索了我的GLSL程序,发现在将顶点坐标转换为屏幕坐标(vec2( vertex.xy / vertex.w ) * Viewport;)时,我基本上将z值设置为几何着色器中的零。我通过分别计算z值(vertex.z/vertex.w)并将它们分配给发射点(gl_Position = vec4( screenCoords[i], zValues[i], 1.0 );)来修复它。这解决了我的问题。

    关于深度缓冲设置,我没有必要明确指定它们,因为我使用的库默认正确设置它们。

1 个答案:

答案 0 :(得分:1)

如果您不使用深度缓冲区,则最近渲染的对象将始终位于顶部。

您应该使用glEnable(GL_DEPTH_TEST)启用它,将功能设置为您喜欢的(glDepthFunc(GL_LEQUAL)),并确保每一帧都清除它(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))。

然后确保您的顶点着色器正确设置最终顶点的Z值。看起来最简单的方法是在CPU端设置ModelViewProjectionMatrix的“模型”部分,以便在传递到着色器之前获得深度值。

只要您使用正交投影矩阵,渲染就不会受到影响(除了使绘制顺序正确)。