Why does OpenGL select my polygons when the camera is far from the object?

I use a fragment shader to shade Lambert and Fog on objects loaded from an OBJ file, but I have a little problem with polygons. Some polygons in my grid are “rejected” when I move the position of the camera away from the object.

Example:

I honestly don’t know why this happens, and why it only happens when I move away from the object. Here are my shaders:

Vertex Shader

# version 400 out struct vData { vec4 pos; vec4 texcoord; vec3 normal; } fdata; void main() { fdata.texcoord = gl_MultiTexCoord0; fdata.normal = normalize(gl_NormalMatrix * gl_Normal); fdata.pos = gl_Vertex; gl_Position = gl_ModelViewProjectionMatrix * fdata.pos; } 

Fragment shader

 # version 400 layout(binding=0) uniform sampler2D mainTexture; uniform vec4 lightColor; uniform vec4 lightPos; in struct vData { vec4 pos; vec4 texcoord; vec3 normal; } fdata; vec4 ComputeLambert(const in vec3 lightdir, const in vec4 lightColor, const in vec3 normal, const in vec4 diffuse) { float nDotL = dot(normal, lightdir); return diffuse * lightColor * max(nDotL, 0.0); } float ComputeFogFactor(const in vec4 coord, const in float density) { const float LOG2 = 1.442695; float z = coord.z / coord.w; float fogFactor = exp2( -density * density * z * z * LOG2 ); return clamp(fogFactor, 0.0, 1.0); } void main() { vec3 mypos = fdata.pos.xyz / fdata.pos.w; vec3 lightdir = lightPos.xyz / lightPos.w; vec3 direction = normalize(lightdir - mypos); vec4 diffuse = texture2D(mainTexture, fdata.texcoord.st); diffuse = ComputeLambert(direction,lightColor, fdata.normal, diffuse); float fogFactor = ComputeFogFactor(gl_FragCoord,gl_Fog.density); vec4 finalcolor = mix(gl_Fog.color, diffuse, fogFactor); //vec4 finalcolor = vec4(1.0,1.0,1.0,1.0); finalcolor.a = 1.0; gl_FragColor = finalcolor; } 

I made sure I turned off Face Culling before my call for drawing, so I’m pretty sure that this is not a problem. Does anyone know if there is anything I can do about this?

+6
source share
2 answers

It looks like a problem with the Z-buffer ... I know that you look at it with comments, but:

  • How is your frust tuned?

    znear,zfar ?

  • What bit depth do you use for your Z buffer?

    When you combine these two things together, you can appreciate the accuracy of the depth.

    for example z = <0.1m - 10000.1m> and 16 bit takes 10000.0/65536=0.15 [m/step] , of course, normal gl frustrum has non-linear values ​​of Z, so greater accuracy is close and much less

    When you compare your steps and the minimum details of your model, and they are not much different from your problem.

To restore this, you can do this:

  • change frustrum

    increase close value or lower value

  • use more depth bits in z-buffer (does not work on all cards)

  • use more frustrums

    for a very large range of rendering I use more frustrums with the same look, but

     view1 z = < 0.1, 10.0 > view2 z = < 10.0, 100.0 > view3 z = <100.0,10000.0 > 

    Of course, you need to clear the z-buffer before using another frustrum. Views can overlap by the maximum size of the drawn model (then you do not need all the models in all views, just visualizing the object by the range view).

    It is slower due to several rendering passes, but in the overlapping case, the deceleration occurs only at the choice of the if range, which is not a big deal.

  • use linear values ​​of Z-buffer ...

    do not use the converted Z value inside GLSL ; instead, convert it yourself so that the accuracy is the same in all ranges. Instead exponentially lower in more distant positions

  • use LOD for model

    this is the minimum minimum accuracy over long distances, but if your model does not have LOD ranges, then it is very difficult to calculate it correctly.

PS. it is not rejected, but the front and back surfaces have low z-value accuracy, which can lead to their malfunction (even change front-back and back)

+1
source

as far as I know, the depth buffer values ​​are not linear, so the farther the polygons are away from the camera, the less bits are set for a certain depth range, which leads to a z-battle. This problem gets even worse when you select your far viewing-truncation plane very far (as you said: twice the size of the terrain).

So, try to reduce the truncation size (length) and / or increase the depth of the z-buffer

0
source

Source: https://habr.com/ru/post/957812/


All Articles