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

时间:2018-09-17 14:06:19

标签: c++ opengl glsl depth-buffer

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

我试图根据几何类型操纵gl_FragDepth值来解决此问题。在我的片段着色器中,我有类似的内容:

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

某些行的优先级高于其他对象,我正在操纵统一变量“ offset”以实现这一目标。

乍一看,结果会更好:

enter image description here

即使位置精确的对象看起来更好,在正常情况下,对象在彼此之间跳跃也有问题。

我的问题是:

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;
        };

1 个答案:

答案 0 :(得分:1)

gl_FragDepth中写入fragment shader的值指定要处理的片段的深度值。此值将写入深度缓冲区。
通常,深度值必须在 [0,1] 范围内(除非glDepthRange指定了不同的映射)。

如果未在片段着色器中设置gl_FragDepth,则写入深度缓冲区的值是从范围 [-1,1]映射的规范化设备空间z坐标。 ] 到范围 [0,1]

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

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

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

这意味着表达式

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设置了{1}}:

gl_Position

请注意,以恒定值操作视图空间z坐标不能达到相同的效果(在透视投影中)。视图空间的z坐标不会线性转换为归一化的设备z坐标(由于透视图划分)。
参见How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?