Ios 将纹理数据写入深度缓冲区

Ios 将纹理数据写入深度缓冲区,ios,opengl-es,depth-buffer,gldrawpixels,Ios,Opengl Es,Depth Buffer,Gldrawpixels,我正在尝试实现以下位置描述的技术: 其想法是使用现有纹理(从图像加载)作为深度遮罩,基本上伪造3D 我面临的问题是glDrawPixels在OpenglES中不可用。有没有办法在iPhone上完成同样的事情?深度缓冲区比您在OpenGL ES中想象的更模糊;不仅缺少glDrawPixels,而且GLU FragDepth已从GLSL中删除。因此,您不能将自定义片段着色器写入到深度缓冲区的假脱机值,因为您可能会推送颜色 最明显的解决方案是将深度信息打包到纹理中,并使用自定义片段着色器在生成的片段和

我正在尝试实现以下位置描述的技术:

其想法是使用现有纹理(从图像加载)作为深度遮罩,基本上伪造3D


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

深度缓冲区比您在OpenGL ES中想象的更模糊;不仅缺少glDrawPixels,而且GLU 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_纹理在iPad或第三代iPhone上肯定不受支持。我还没有在其他地方进行完整的测试。

谢谢你的回答。你能详细介绍一下你所说的GPU上的往返行程吗?我不太确定我是否理解这一部分。这与你所问的问题并不完全相关——它与“我如何使用深度贴图进行阴影”类型的问题更相关,在这类问题中,你确实绘制了一些东西,以便在GPU上创建深度贴图,并保留该贴图以备将来使用,而不是从磁盘加载。但我已经添加了一些示例代码,可能仍然有点含糊不清?话虽如此,我现在看到的iPhone4上确实存在GL_OES_depth_纹理。我不确定这是否是操作系统版本的东西,但我的理解是,硬件实际上与iPad完全相同,因此我无法解释它。可能值得检查您想要支持的特定iOS设备和操作系统版本。我可能会单独问这个问题,但当使用片段着色器来模拟
gl_FragDepth
写入纹理时,如何防止用可能较远的片段覆盖可能较近的片段?我们似乎无法查询正在写入的纹理,以查看该位置是否已写入内容。@cheeseus-是的,我有。iOS 6.0引入了GL_EXT_shader_framebuffer_fetch扩展,允许您在片段处读取当前颜色。使用此选项,您可以读取前面编码深度的片段颜色,将其与当前片段深度进行比较,并仅写出更接近查看器的深度。在iOS 6之前,我对颜色组件使用了最大混合模式和桶填充方法,仅将深度的动态范围从256扩展到1024。现在我名义上可以得到一个32位的动态范围,尽管在实践中,高精度限制为16位。