[SOLVED] Rendering problem when two faces are close to each other


I’m trying to render a load of squares on rods (top image):

I’m doing this by with drawInstanced() for two gl::Batchs, one for the rods (a geom::Cube) and one the squares (a manually constructed square gl::VboMesh). The rods is slightly offset from the squares, but there’s a rendering issue, which I don’t understand. I’m calling gl::enableDepth() in draw().

I tried not drawing the rod and calling gl::enableFaceCulling() to hide the squares facing away, which gives much better results in terms of rendering (middle image).

But I don’t want to see through the rods! It looks like the issue is the proximity of the rods to the squares. If I reduce the size of the rods (and draw them in red for visibility) the the squares look better but still some aren’t drawn properly when they’re far away (lower image

Is there anything I can do to improve the quality of the rendering of the squares?


I guess you are using a persp camera.
Have you tried to reduce the view range (far and near)?



What you’re experiencing is called “z-fighting”, and as @dashandslash suggests, this has to do with depth buffer precision. If you specify an unusually large range (e.g. you want to render everything from 1 micrometer to 1 lightyear in the distance), the floating point precision of the buffer will not be able to distinguish between planes that are close to each other.

What makes matters worse is that depth is non-linear: there is much more precision available close to the near plane than there is further away from the near plane. A good article about it can be found here.

The solution is to tweak the depth range, especially the near plane distance. Make it as large as you can. And also reduce the far plane distance.

If that’s not enough, make sure to use the highest depth buffer precision available. The default (I think) currently is 24 bit with 8 bits stencil mask (GL_DEPTH24_STENCIL8). If you don’t need the stencil buffer, try GL_DEPTH_COMPONENT32 or even GL_DEPTH_COMPONENT32F. Note that this may have an effect on performance, so test this.

Finally, if all else fails, try looking into “reverse depth”, as mentioned in this article. This, however, is pretty advanced stuff, so try adjusting the near plane first.



Thanks @paul.houx for the in-depth explanation!
I feel so lazy now for not having invested a bit of more effort on explaining the reason behind my answer (which ended up being a question).

And thanks for the links, great articles!



Thanks @dashandslash and @paul.houx for your detailed answer. I did have some outrageous values for the near and far planes!

Putting something reasonable has done the trick. Thank you.


Just to give an extra solution: while the answer given by @paul.houx is usually the right fix, sometimes you might actually want two geometries on top of each other, with one having priority over the other (for example, when using decals).

In that case you can use glPolygonOffset to achieve that effect. This article is for Three.js but it gives a nice simple explanation.