【问题标题】:Writing texture data onto depth buffer将纹理数据写入深度缓冲区
【发布时间】:2011-05-30 21:16:30
【问题描述】:

我正在尝试实现Compositing Images with Depth 中描述的技术。

这个想法是使用现有纹理(从图像加载)作为深度蒙版,基本上是伪造 3D。

我面临的问题是 glDrawPixels 在 OpenglES 中不可用。有没有办法在 iPhone 上完成同样的事情?

【问题讨论】:

    标签: ios opengl-es depth-buffer gldrawpixels


    【解决方案1】:

    深度缓冲区比您在 OpenGL ES 中想象的要模糊;不仅 glDrawPixels 不存在,而且 gl_FragDepth 已从 GLSL 中删除。因此,您不能编写自定义片段着色器来将值假脱机到深度缓冲区,因为您可能会推送颜色。

    最明显的解决方案是将深度信息打包到纹理中,并使用自定义片段着色器在它生成的片段与从您提供的纹理中查找的片段之间进行深度比较。只有当生成的片段更接近时,它才允许继续。正常深度缓冲区将捕获其他遮挡情况,原则上,您可以使用帧缓冲区对象首先创建深度纹理,为您提供完整的 GPU 往返,尽管它与您的问题。

    缺点是绘图会花费您额外的纹理单元,并且纹理使用整数组件。

    编辑:为了使示例简单,假设您将所有深度信息打包到纹理的红色通道中。这会给你一个非常低精度的深度缓冲区,但为了清楚起见,你可以编写一个快速的片段着色器,如:

    void main()
    {
        // write a value to the depth map
        gl_FragColor = vec4(gl_FragCoord.w, 0.0, 0.0, 1.0);
    }
    

    在红色通道中存储深度。因此,您已经部分地重新创建了旧的深度纹理扩展——您将拥有一个图像,在较近的像素中具有较亮的红色,在较远的像素中具有较暗的红色。我认为在您的问题中,您实际上是从磁盘加载此图像。

    若要在未来的片段着色器中使用纹理,您需要执行以下操作:

    uniform sampler2D depthMap;
    
    void main()
    {
        // read a value from the depth map
        lowp vec3 colourFromDepthMap = texture2D(depthMap, gl_FragCoord.xy);
    
        // discard the current fragment if it is less close than the stored value
        if(colourFromDepthMap.r > gl_FragCoord.w) discard;
    
        ... set gl_FragColor appropriately otherwise ...
    }
    

    EDIT2:您可以看到从深度到 RGBA 值here 的更智能的映射。为了直接与该文档相关联,OES_depth_texture 绝对不支持 iPad 或第三代 iPhone。我没有在其他地方进行过完整的测试。

    【讨论】:

    • 感谢您的回答。您能否详细说明一下您正在谈论的 GPU 上的往返行程?我不太确定我是否理解那部分。
    • 这与您提出的问题并不完全相关 - 它与“我如何使用深度图进行阴影”类型的问题更相关,您确实在其中绘制了一些东西来创建深度图在 GPU 上并保留地图以供以后使用,而不是从磁盘加载它。但是我已经快速添加了一些示例代码,可能还是有点模糊?
    • 说了这么多,GL_OES_depth_texture 似乎确实存在于我现在拥有的 iPhone 4 上。我不确定这是否是操作系统版本的东西,但我的理解是硬件实际上与 iPad 相同,所以我无法解释它。可能值得检查您想要支持的特定 iOS 设备和操作系统版本。
    • 我可能会将此作为一个单独的问题提出,但是当使用片段着色器写入纹理以模拟 gl_FragDepth 时,如何防止用可能更接近查看器的片段覆盖更远?我们似乎没有能力查询正在写入的纹理以查看该位置是否已写入内容。
    • @cheeesus - 是的,我做到了。 iOS 6.0 引入了 GL_EXT_shader_framebuffer_fetch 扩展,它允许你读取片段的当前颜色。使用它,您可以读取之前编码深度的片段颜色,将其与当前片段深度进行比较,然后只写出更接近查看者的深度。在 iOS 6 之前,我对颜色分量使用最大混合模式和桶填充方法,仅将深度的动态范围从 256 扩展到 1024。现在我名义上可以获得 32 位动态范围,尽管高精度限制了你在实践中到 16 位。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多