OpenGL es 2.0读取深度缓冲区

时间:2010-04-07 23:54:03

标签: opengl-es depth-buffer

据我所知,我们无法读取OpenGL ES 2.0中的Z(深度)值。 所以我想知道如何从2D屏幕上的某个点获取3D世界坐标?

其实我有一些随机的想法可能会奏效。由于我们可以使用glReadPixels读取RGBA值,我们如何复制深度缓冲区并将其存储在颜色缓冲区(比如ColorforDepth)中。当然需要有一些很好的约定,这样我们就不会丢失深度缓冲区的任何信息。然后当我们需要一个点的世界坐标时,我们将这个ColorforDepth颜色缓冲区附加到帧缓冲区然后渲染它。所以当我们使用glReadPixels读取此帧的深度信息时。

然而,这将导致1帧闪存,因为颜色缓冲是从深度缓冲区转换的奇怪缓冲区。我仍然想知道是否有一些标准的方法来获得OpenGL es 2.0的深度?

提前!:)

3 个答案:

答案 0 :(得分:7)

使用FBO,您可以在不显示结果的情况下进行渲染。如果您使用的是ES 2.0,则片段着色器可以作为gl_FragCoord的一部分访问当前片段的深度(在窗口坐标中),因此您可以将其写入颜色缓冲区,使用glReadPixels获取结果并继续。或者,您可以将世界空间z作为变量加载并从片段着色器中写入,以防这种情况更容易。

为了说服自己,尝试编写一个快速着色器,将gl_FragCoord.z放在低精度的匆忙中,例如:刚

gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0);

你应该得到一个灰度,颜色的强度代表深度。因为您处于窗口坐标中,所以强度范围从0.0(最接近的可能未剪切片段)到1.0(尽可能最远的未剪切片段)。为了不失去相当多的精度,在组件之间拆分值可能更有帮助,因为您的供应商几乎肯定不支持浮点目标缓冲区。

答案 1 :(得分:0)

我使用基本光线投射从屏幕触摸中拾取3D对象。实际上,我计算了触摸点处的屏幕法线与包含我的物体的球体之间的交点。对于非常精确的拾取或复杂的形状,您必须使用多个球体。

您还可以在屏幕的2D空间中投影对象的某些关键点(我的3D点乘以变换矩阵),然后与触点进行2D比较(距离)。

答案 2 :(得分:0)

我还希望能够读取深度缓冲区中的值, 但是研究表明它无法完成。

如vincent所暗示的那样,如果你有像球体这样简单的形状,光线投射可能会更好。

对于更复杂的形状, 我正在考虑将对象渲染到(可能更小的)屏幕外缓冲区, 手动将每个顶点的一个颜色分量指定为该顶点的深度, 然后读取颜色值。这有点不优雅和讨厌,并要求你能够将对象空间转换为屏幕空间(我使用自己的四元数来驱动矩阵,以便处理它)。着色器可能有一种方法可以将深度信息写入颜色或模板缓冲区(GL ES是否还有模板缓冲区?)

如果有人采用更清洁的方式,我很乐意听到它。