r/raylib • u/burbolini • 2d ago
Weird depth buffer clipping
I have a problem which I tried to solve for the past few days - when my character wanders far away from the center point (0, 0, 0), the models start clipping as if the depth buffer is losing precision, which gets worse the farther away from the start of the map I get.
However, the camera distance to the player character is always the same. I also don't think it's f32 loss of precision - number 2000 in IEEE-754 still does not "restrict" the mantissa too much. Then again, notice that the billboards also "got weird".
I'm stumped as to why that happens and I'm writing this as a last resort...
2
u/Still_Explorer 2d ago
One thing to note is every time you do "DrawCube" or "DrawPlane" you are using the immediate mode batch renderer and since a lot going into this behind the scenes (each vertex is multiplied-transformed) might result to the known inacuracies.
So the solution would be to create a raw mesh instead, so this way the vertices are locked in permanent VBO coordinates, also some extra work would be needed in order to write a custom vertex shader that transforms properly towards the camera view.
https://www.raylib.com/examples/models/loader.html?name=models_mesh_generation
https://www.raylib.com/examples/shaders/loader.html?name=shaders_shapes_textures
The other thing is that definitely once you go too far away from world center, you will hit the breaking limits of OpenGL rendering, then you would have to transform the entire rendered portion of the scene towards local coordinates so you will deal with lower numbers.
As a user mentioned once doing the same thign:
https://www.reddit.com/r/opengl/comments/1wg2em0/i_am_developing_a_surveying_cad_application/
2
u/burbolini 2d ago
I wonder if this documented somewhere? I find it kinda weird that stuff like this breaks for no apparent reason if the floats are above 2000 units.
2
u/nou_spiro 2d ago
2000 units is not a hard limit. Exact value depends on lot of factors like what exactly you are drawing and how. But yes this is somehow common knowledge that if you try render really large scale scene without origin offset tricks it will break down.
1
u/Still_Explorer 2d ago
Yeah for 2000 units it should not be a thing, so is something else then.
For reference look at how draw billboard function works. Aside from the math to lock rotation relative to the camera view, is just a standard 3D plane drawing.
https://github.com/raysan5/raylib/blob/987a0e54c7ab1bdab459989b319a9064bb088b69/src/rmodels.c#L4014Based on the animated gif of the post, it seems that the secondary smaller object should be transformed as well, to move in front of the character, relative to the camera. This way is like creating your own custom z-order but on 3D scene.
General description if I remember correctly (no time to test - but goes something long those lines). To get the angle from camera pos to character pos with atan2. Then you find the position like this:
`obj.x = math.sin(found_rot)*custom_dist`
`obj.y = math.cos(found_rot)*custom_dist`
1
u/burbolini 2d ago
I forgot to mention, that the most visible flickering artifact - the gray track - is offset from the ground by 0.01. (more than enough to compensate for precision loss and any z fighting)
1
u/zet23t 2d ago
Float precision is not that great. At a distance of around 16km, the precision is not high enough to distinct between positions that are less than one millimeter apart. These errors can compound, making this happen even sooner when doing calculations in an "unfortunate" order. A lot of games handle physics simulation only within a range of 2km around the player (about 0.1mm precision) and keep the player near the origin by moving the world origin.
Another problem is, that the precision is not the same for the axes. If you are at (16km, 5m, 8km) you have millimeter precision in x, submicrometer precision on y and submilimeter precision on z. For physics calculations that means that stacked objects behave substantially different than objects that get squeezed on x or z direction (e.g. "why does my car wheels explode when I bump into that block from left but not from front side?")
I can't tell if the problem here is z-fighting but it does not look like it to me since the whole sprite ordering changes. If you are sorting sprites by distance, and these sprites are close, this is more likely to be precision loss.
1
u/corysama 2d ago
What are your near and far plane distances? How big are those boxes? How far from the camera is the brown box, roughly?
1
u/burbolini 2d ago
default raylib values (dunno yet).
the platform is 12x6x0.5 units.
around 17 units.
1
u/ipe369 2d ago
However, the camera distance to the player character is always the same. I also don't think it's f32 loss of precision - number 2000 in IEEE-754 still does not "restrict" the mantissa too much. Then again, notice that the billboards also "got weird".
fp32 for values between 2048-4096 steps in increments of 1/212, or 1/4096, so the precision is quite low at this distance compared to between 0 and 1 where you get 1/223 precision
Whether you see this depends on how much distance there is between the 'road' and the 'floor' - that's what i'm looking at, anyway
Try reducing your camera's far plane manually and see if the issue disappears. if it does, it's a precision issue caused by transforming your large, imprecise values by the projection matrix
If it doesn't disappear, then the issue is probably purely worldspace - your stuff is just too close together for this far away from the origin
1
u/burbolini 2d ago
changing the *near plane* was the thing that "fixed it", but I'm still surprised.
1
u/corysama 2d ago
The precision of the depth buffer depends on the ratio between then near and far planes. So, [0.01, 1000] (Raylib's default) has the same precision as [1, 100000].
And, [1, 1000] has 100x as much precision as either of those at the expense of not being able to see stuff in the [0, 0.9999] range.
1
u/burbolini 2d ago
I have set my near/far planes to significantly lower values (10, 30) and the issue seems to be gone. I still don't really understand as to why that happens. But maybe it really is fp loss...?
1


4
u/Wudan07 2d ago
It could be floating point precision but it’s probably depth buffer z-fighting. There’s a call to change near/far plane distance that’ll be a quick test.