在我们当前的项目中,我们有可能在完全相同的位置绘制一些线。比起像这样的闪烁效果。
我试图根据几何类型操纵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;
};
答案 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_COMPONENT16
,GL_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_Position
,gl_FragCoord
和gl_FragDepth
之间的关系,深度偏移也可以在{之后的顶点着色器中应用于gl_Position
设置了{1}}:
gl_Position
请注意,以恒定值操作视图空间z坐标不能达到相同的效果(在透视投影中)。视图空间的z坐标不会线性转换为归一化的设备z坐标(由于透视图划分)。
参见How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?