通过操纵 gl_FragDepth 将选定的线对象优先于其他对象

Prioritizing selected line objects over others by manipulating gl_FragDepth

在我们当前的项目中,我们有可能在完全相同的地方绘制一些线条。比我们有这样的闪烁效果。

我正在尝试根据几何类型操纵 gl_FragDepth 值来解决这个问题。在我的片段着色器中,我有类似的东西:

if ( offset > 0.0 )
   gl_FragDepth =  gl_FragCoord.z - offset*0.001;

有些行比其他对象具有优先级,我正在操纵统一变量 "offset" 来实现这一点。

结果乍一看好一点:

即使对象具有精确的某个位置看起来也更好我在正常情况下会遇到问题对象会相互跳跃。

我的问题是:

1 - 为特定的优先对象以尽可能小的 z 深度操纵 gl_FragDepth 是一个好的策略吗?

2 - 如果是这样而不是分配 gl_FragCoord.z 我应该使用类似的东西 described here。 ?

我尝试调用这个函数:

 float findRealDepth(in highp mat4 modelViewProjectinMatrix,
                     in highp vec4 objectPosition)
        {
            float far=gl_DepthRange.far; float near=gl_DepthRange.near;
            vec4 clip_space_pos = modelViewProjectinMatrix * vec4(objectPosition.xyz, 1.0);
            float ndc_depth = clip_space_pos.z / clip_space_pos.w;
            return (((far-near) * ndc_depth) + near + far) / 2.0;
        };

写入gl_FragDepth in the fragment shader的值指定正在处理的片段的深度值。该值被写入深度缓冲区。
一般来说,深度值必须在 [0, 1] 范围内(除了由 glDepthRange 指定的不同映射)。

如果在片段着色器中没有设置gl_FragDepth,那么写入深度缓冲区的值是标准化设备space z坐标从[-1, 1] 到范围 [0, 1].

这意味着深度值可以表示如下:

depth = 0.5 + 0.5 * gl_Position.z / gl_Position.w;

在片段着色器中,可以从片段内置输入变量的 z 分量中读取该值 gl_FragCoord

这意味着表达式

gl_FragDepth = gl_FragCoord.z;

会将相同的值存储到深度缓冲区,就像自动存储到深度缓冲区一样,而无需写入 gl_FragDepth.

如果必须应用深度偏移,将线几何图形拉到前面,则必须通过减去偏移来减小深度值:

gl_FragDepth =  gl_FragCoord.z - offset;  

offset 必须大于或等于可以存储在深度缓冲区中的最小值。

如果使用定点深度缓冲区格式(例如 GL_DEPTH_COMPONENT16GL_DEPTH_COMPONENT24),则深度 0.0 由所有位 0 表示,深度 1.0 由所有位 1 表示。
最小值是设置最低有效位且所有其他位为零的值。

这意味着对于具有 24 位 (GL_DEPTH_COMPONENT24) 的定点深度缓冲区,可以表示的最小值是:

1 / (2^24 - 1)

在 GLSL 中:

1.0 / (exp2(24.0) - 1.0) 

由于gl_Positiongl_FragCoordgl_FragDepth之间的关系,如上所述,深度偏移也可以应用于顶点着色器中的gl_Position,设置 gl_Position 后:

gl_Position.z = gl_Position.z - offset * 2.0 * gl_Position.w;

注意,用常量值操纵视图space z 坐标不能达到同样的效果(在透视投影中)。视图 space z 坐标不是线性转换为规范化设备 z 坐标(因为透视划分)。
参见 How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?