【问题标题】:GLSL shader: occlusion order and cullingGLSL 着色器:遮挡顺序和剔除
【发布时间】:2016-09-10 00:52:44
【问题描述】:

我有一个 GLSL 着色器,它可以在给定一组贝塞尔曲线(点的 3d 坐标)的情况下绘制 3D 曲线。绘图本身是按照我的意愿完成的,除了遮挡不能正常工作,即在某些视点下,应该在最前面的曲线似乎仍然被遮挡,并且相反:曲线的一部分应该是被遮挡的还是可见的。

为了说明,这里有几个截图示例:

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

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

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

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

  1. 在顶点着色器中,我计算 gl_Position = ModelViewProjectionMatrix * Vertex; 并将颜色信息进一步传递给几何着色器。
  2. 在几何着色器中,我采用 4 个控制点 (lines_adjacency) 和它们对应的颜色并生成一个遵循贝塞尔曲线的三角形条带(我在贝塞尔曲线段之间使用了一些基本的颜色插值)。
  3. 片段着色器也很简单:gl_FragColor = VertexIn.mColor;

关于 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 );) 来修复它。这解决了我的问题。

关于深度缓冲区设置,我不必明确指定它们,因为我使用的库默认情况下会根据需要正确设置它们。

【问题讨论】:

  • 使用 apitrace 或 renderdoc 之类的调试器查看正在写入深度缓冲区的深度值。
  • 如果我无法在理论层面上弄清楚,我会尝试一下。
  • 你有深度缓冲区吗?根据您用于设置上下文和渲染表面的窗口系统工具包/框架,这可能是默认设置,或者您可能必须特别请求它。
  • 我没有明确设置深度缓冲区,也没有使用它。我需要在深度缓冲区设置中进行哪些更改,或者如何使用它来解决问题?

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


【解决方案1】:

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

您应该使用 glEnable(GL_DEPTH_TEST) 启用它,根据自己的喜好设置功能 (glDepthFunc(GL_LEQUAL)),并确保在每一帧都将其清除为其他所有内容 (glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))。

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

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

【讨论】:

  • 能否请您澄清一下,“顶点着色器正确设置最终顶点的 Z 值”是什么意思? Z值是什么,是gl_Position.z吗?什么是正确 z 值?
  • vec4 的 Z 值(如 gl_Position)与 X 和 Y 一样,但用于深度。一个合适的 Z 值是介于 0 和 1 之间的任何值,或者是您在制作投影矩阵时设置的 zNear 和 zFar 的任何值。 0 是屏幕,1 是从显示器的背面推出,所以当您将深度函数设置为 GL_LEQUAL 时,您的意思是只渲染离显示器最近的东西。
  • 一个更具体的例子是,如果将彩虹深度设置为0.8,灰度设置为0.2,并且先渲染灰度,彩虹上的重叠像素将无法通过深度测试而无法绘制,因为0.8不小于或等于0.2。如果您翻转绘制顺序并先绘制彩虹,则灰度重叠像素会改为通过深度测试。 0.2小于等于0.8,所以彩虹像素和灰度像素重叠
  • 感谢您的帮助,答案/建议帮助我理解了问题(看起来我没有正确设置 Z 值,因此将尝试解决该问题)。
  • 我再问一件事,当你提到如何获得Z值时,你推荐使用Model矩阵。那么公式会是这样的:V' = Model * VertexzValue = normalize (V'.z in Far and Near),对吗?
猜你喜欢
  • 1970-01-01
  • 2011-06-27
  • 2014-09-22
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多