While I was testing out performance related methods, I came across this behaviour, that I believe has to do with precision error, but wanted to confirm, and check if there is any source of mitigation and/or any ideas to ease it out.
I have a simple scene with some cubes (36 verts/12 tris), and a plane below (4 verts/2 tris), each one using a unit of 1 for length (cube 1x1x1, plane 1x1).
When I set the scale factor for the plane of 100 times (100x100) everything works fine and as expected in terms of geometry. As shown in the Video1
When I scale the same plane 1.000.000 times, there seems to exist an unstable transformation depending on the view as shown in the Video2
I’m using 16-float matrices (4x4) to perform transformations, and I believe that it has to do with that, I already came across this issue in the past but was with the view matrix itself when too far from the origin, what boggles me is that the scene is origin-centered, the camera and all the elements are near the origin (within the 10’s units) and still the object shakes the same way, and more profusely when the view is looking from the XZ axis towards the origin.
The same happens if the plane is originally 100000x100000 with 1x scaling.
If the whole scene is scaled 0.01x while the plane is scale 1000x then the same happens.
Rather than just splitting the scene into more objects (which is application/CPU dependant) what are some good solutions or workarounds to this issue?
And, if it’s not possible, how can I achieve having an infinite plane (or visually infinite) without having to make suchs transformations?
Regardind the shaking shadow over the plane when the view is near the XZ axis looking towards the origin, is it caused by the lack of float precision? I know it is accentuated by it, but on a small scale that can be noticed as well.
With single-precision float, you’ve only got 23 bits of relative (mantissa) precision. The bigger the magnitude of the numbers you’re dealing with, the less you have down at the other end for numeric accuracy.
For instance, 2^23 = 8,388,608. If you represent 1,000,000, then (to rough approximation, ignoring denorms, etc.), you’ve only got accuracy of ~0.12 units.
Well, I assume this was a contrived example. Because if you scale a plane, you still get a plane, and there’s no reason to carry this scale factor through.
The reason being to create an effect of a never ending plane, it would still be a plane (keeping its geometrycal topography would be the purpose) but with the ending result of seamlessly merging into the view horizon.
The only solution I see to this (besides chaging the data structures) is to cut it down into many pieces in order to keep its localized transformations more precise
If you’re drawing a plane as a large quad, add a centre vertex which is reasonably close to the camera and draw it as 4 triangles rather than 2.
The main issue for floating-point accuracy is cancellation: subtracting two quantities which are almost equal (i.e. their difference is small compared to the individual values), or adding quantities which are almost equal in magnitude but opposite in sign.
1.234567 - 1.234512 = 0.000055
goes from 7 significant figures (relative error of ~4×10-7) to 2 significant figures (relative error of ~9×10-3).
If you have a triangle whose vertices are far from the viewpoint and you clip it against the near plane (or any other plane at a point close to the viewpoint), the clipping calculation will end up with a (relatively) large cancellation error. If one of the vertices is close to the viewpoint, the other vertices will have very little weight so the error in their positions won’t matter.