2

In our current project we have probability of having some lines drawing on exact same place. Than we are having a flickering effect like this.

I am trying to manipulate gl_FragDepth values depending on the geometry types to over come this problem. In my fragment shader I have something like:

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

Some lines have priorities over other objects and I am manipulating the uniform variable "offset" to achieve that.

The result is a bit better at first glance :

enter image description here

Even the object which have exact some position looks better I have problems in normal case objects are jumping on top of each other.

My questions are :

1 - Is manipulating gl_FragDepth with smallest possible z-depth for specific prioritized objects a good strategy?

2 - If so instead of assigning gl_FragCoord.z should I use something like described here. ?

Which I tried by calling this function :

 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;
        };
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Kadir Erdem Demir
  • 3,531
  • 3
  • 28
  • 39
  • 1
    I think the second approach is better . Because how depth values are finally stores is completely implementation dependent and hardware specific so the implementation dependent conversions will happen on your modified values of z. So better take real depth value and use it in your manipulation, – Paritosh Kulkarni Sep 17 '18 at 14:31
  • Change the depth test function to [`GL_LEQUAL`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthFunc.xhtml) and/or use a [`polygon offset`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml) – Rabbid76 Sep 17 '18 at 15:40
  • @Rabbid76 polygon offset is just for surfaces as I stated in question I have problems with lines – Kadir Erdem Demir Sep 17 '18 at 15:42
  • Yes!! Read this please https://stackoverflow.com/questions/2020451/glpolygonoffset-bugs-with-lines – Kadir Erdem Demir Sep 17 '18 at 15:57
  • @KadirErdemDemir You can push the polygons to depth by an polygon offset and draw the lines on top. Apply the polygon offset to the polygons and draw the lines without an polygon offset. – Rabbid76 Sep 17 '18 at 16:37
  • @Rabbid76 actually this is what we are doing for surface vs lines already but problem is two geometries which are drawn by gl_lines is z fighting. – Kadir Erdem Demir Sep 17 '18 at 16:40
  • @KadirErdemDemir Then you have to add/subtract a minimum amount to`gl_FragCoord.z`. The amount depends on the format of the depth buffer (16bit, 32bit etc.), actually that is what the polygons offset would do. And don't forget to change the depth test function to less or equal (`GL_LEQUAL`). – Rabbid76 Sep 17 '18 at 16:42
  • @Rabbid76 Thanks, so you agree adding an offset is a good strategy for my case like I ask in my first question. For my second question do you think ı should manipulate fragcoord.z or I should find the real z and work on it? Do you have any comments on this? – Kadir Erdem Demir Sep 17 '18 at 16:46
  • 1
    `gl_FragDepth.z` is the value which is stored to the depth buffer. You have to change this value by a depth unit, if you want to ensure that each fragment is shifted in depth independent on its view space z coordinate. The depth unit is constant and depends on the format of the depth buffer which depends on the hardware, but it can be determined once after the (default) framebuffer was set up and won't change. – Rabbid76 Sep 17 '18 at 16:51
  • @Rabbid76 Can you please be a bit more spesific about finding the depth unit. I am using 0.0001 * offset now because 0.0001 is somewhat close to smallest change with 16 bit float. I also couldn't understand if you suggest using gl_FragDepth.z or view space z. Can you also explain this a bit more. If you have time it is possible if you wrote an answer instead comments. – Kadir Erdem Demir Sep 18 '18 at 07:26

1 Answers1

1

The value which is written to gl_FragDepth in the fragment shader specifies the depth value for the fragment being processed. This value is written to the depth buffer.
In general the depth value has to be in the range [0, 1] (except a different mapping is specified by glDepthRange).

If gl_FragDepth is not set in the fragment shader, then the value which is written to the depth buffer is the normalized device space z coordinate mapped from the range [-1, 1] to the range [0, 1].

This means the depth value can be expressed as follows:

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

In the fragment shader this value can be read from the z component of the Fragment built-in input variable gl_FragCoord.

This means, that the expression

gl_FragDepth = gl_FragCoord.z;

would store the same value to the depth buffer, as would be automatically stored to it, without any writing to gl_FragDepth.

If a depth offset has to be applied, which pulls the line geometry to front, then the depth value has to be decreased by subtracting an offset:

gl_FragDepth =  gl_FragCoord.z - offset;  

The offset has to be greater or equal than the minimum value which can be stored in the depth buffer.

If a fixed-point depth buffer format is used (e.g. GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24) then the depth 0.0 is represented by all bits 0 and the depth 1.0 is represented by all bits 1.
The minimum value is the value where the least significant bit is set and all other bits are zero.

This means for a fixed-point depth buffer with 24 bits (GL_DEPTH_COMPONENT24) the minimum value, which can be represented is:

1 / (2^24 - 1)

in GLSL:

1.0 / (exp2(24.0) - 1.0) 

Because of the relation between gl_Position, gl_FragCoord and gl_FragDepth, as described above, the depth offset can also be applied to gl_Position in the vertex shader, after gl_Position was set:

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

Note, manipulating the view space z coordinate by a constant value can't achieve the same effect (in perspective projection). The view space z coordinate is not linear transformed to the normalized device z coordinate (because of the perspective divide).
See How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174