【问题标题】:OpenGL es 2.0 Read depth bufferOpenGL es 2.0 读取深度缓冲区
【发布时间】:2011-02-05 12:04:46
【问题描述】:

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

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

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

提前谢谢!:)

【问题讨论】:

    标签: opengl-es depth-buffer


    【解决方案1】:

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

    为了说服自己,请尝试编写一个快速着色器,以低精度快速输出 gl_FragCoord.z,例如只是

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

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

    【讨论】:

    • Tommy,您能否多说一些关于在组件之间拆分 gl_FragCoord.z 的问题。不跟随。干杯。
    • @dugla 如果深度是一个 32 位整数,那么在 R、G、B 和 A 中,你可能只有 8 位。所以在实践中你要做的就是乘法向量(1, 256, 65536, 16777216),然后将该向量 mod 1.0 的每个分量存储到相关通道中。您可以稍后通过除以相关组件并相加来重新组合。
    • @Tommy 很有趣!!您能否详细说明 vec4 到浮点转换的反面? Сould you show an example please?
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我还希望能够读取深度缓冲区中的值, 但研究表明这是不可能的。

      正如 vincent 所建议的,如果你有简单的形状,比如球体,光线投射可能会更好。

      对于更复杂的形状, 我正在考虑将对象渲染到(可能更小的)屏幕外缓冲区, 手动将每个顶点的颜色分量之一指定为该顶点的深度, 然后读取颜色值。这有点不雅和烦人,并且要求您能够将对象空间转换为屏幕空间(我正在使用我自己的四元数来驱动矩阵,因此可以解决这个问题)。可能有一种方法可以使用着色器将深度信息写入颜色或模板缓冲区(GL ES 甚至有模板缓冲区吗?)

      如果有人有更清洁的方法,我很想听听。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多