6

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

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

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

4

1 回答 1

7

深度缓冲区比你在 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 值的更智能的映射。为了直接与该文档相关联,OES_depth_texture 绝对不支持 iPad 或第三代 iPhone。我还没有在其他地方进行过完整的测试。

于 2011-01-04T17:06:04.880 回答