在 OpenGL ES 2.0 或 3.0 中为 Z 测试设置深度纹理

Set depth texture for Z-testing in OpenGL ES 2.0 or 3.0

我的 C++ 代码中有一个 16 位 uint 纹理,我想用它在 OpenGL ES 3.0 应用程序中进行 z 测试。我怎样才能做到这一点?

为了提供一些背景信息,我正在制作一个 AR 应用程序,其中虚拟对象可以被真实对象遮挡。生成了真实环境的深度贴图,但是不知道怎么应用。

在我的应用程序中,我首先使用 glTexImage2D 从相机源渲染背景图像,然后绘制一些虚拟对象。我希望对象基于深度纹理是透明的。理想情况下,遮挡测试需要不是二进制的,而是渐进的,这样我就可以在遮挡边缘附近将对象与背景进行 alpha 混合。

我可以在片段着色器中传递和读取深度纹理,但不确定如何将它用于 z 测试而不是渲染。

假设您有一个深度纹理 uniform sampler2D u_depthmap 并且深度纹理的内部格式是浮点格式。

要从当前片段所在的纹理中读取纹素,您必须知道视口的大小 (uniform vec2 u_vieport_size)。 gl_FragCoord 包含片段的 window 相对坐标 (x, y, z, 1/w) 值。所以深度图的纹理坐标计算如下:

vec2 map_uv = gl_FragCoord.xy / u_vieport_size; 

由于内部浮点格式,深度纹理 u_depthmap 的深度在 [0.0, 1.0] 范围内给出。片段的深度也包含在 gl_FragCoord.z 范围内 [0.0, 1.0]。

也就是说map的深度和fragment的深度可以这样计算:

uniform sampler2D u_depthmap;
uniform vec2 u_vieport_size;

void mian()
{
    vec2  map_uv      = gl_FragCoord.xy / u_vieport_size; 
    float map_depth   = texture(u_depthmap, map_uv).x;

    float frag_depth  = gl_FragCoord.z;        

    .....
}

注意,map_depthfrag_depth 都在 [0.0, 1.0] 范围内。如果两者都是用相同的投影(特别是相同的近平面和远平面)生成的,那么它们是可比较的。这意味着您必须确保着色器为世界中的同一点生成与深度图中的深度值相同的深度值。如果不是这种情况,则必须将深度值线性化,并且必须计算视图 space Z 坐标。