how could I fix this?
how could I fix this?
Hello!
I have a large map that seems to do this visual wobble when viewing at further distances.
Here’s the scene with a free fly cam, I don’t really know how else to show it: PlayCanvas | HTML5 Game Engine
Alright, thanks! I’m on mobile right now, so I can’t check the project, but maybe you can try to increase the far clip of the camera component.
This can also be due to z fighting. So you can try moving either blue or green a bit up or down to avoid this.
this, and raising the near clip of the camera, worked great. Thanks!
This has to do with floating point errors. Its fairly complicated to explain but basically there are not infinite numbers representable within digital spaces. There is a hard limit on the amount of numbers a 32 or 64 bit number can represent.
The way floating points try to get around this is that the numbers are spaced out extremely lopsided towards zero and slowly space out. How that works is that doubling the range gives the same amount of values. The amount of possible values between 0 and 1 is the same as between 1 and 3 and the same between 3 and 7 and between 7 and 15 and so on. In fact, the amount of values between 0 and 1 is the same as between 8,388,607 and 16,777,215. At that scale the gap size is exactly 1, so the floats can represent 0.0625 no problem, but they cannot represent 9,000,000.5. Anything past 16,777,215 will have a gap size of 2, meaning that not even every integer can be properly represented.
It is flat out impossible on 32 bit floats. Someone some time back told me what float system Playcanvas uses but I forgot. This is also the reason when doing math sometimes the number ends in .00000000000003 or .999999999997 or something like that. Floats cannot utilize every decimal place between 0 and 1, they can only use a certain number of decimal places equally spaced out between each other. Because the divisor is a power of 2 number and therefore not even remotely properly divisible by 10 they use a weird spacing scheme.
In 32 bit floats every decimal place between 0 and 1 must be a multiple of 2^-23, or 0.00000011920928955078125, so any number not exactly a factor of this will have to be represented using the closest number that is. Double the range from 1 to 3 and the gap in decimal is 2^-22, then from 3 to 7 it is 2^-21, and so on. The number of values between range is the same, but the range itself doubles so the numbers are half as precise as they were in the last range.
This allows for extremely precise numbers in the beginning but slowly gives way to much larger numbers later. This allows for the calculation of very fine numbers and very large numbers not just using a very limited 32 bit number, but while using the exact same numbering system. The people who invented must have been were well aware of the decimal errors and gap size limitations, but the floating point was an extremely useful system in calculations.
This is why you saw what you did. The farther away an object is from the camera the less values are available to position objects. When two objects are very far away yet very close to each other they have no choice but to round to and occupy the same distance value, which causes the distance buffer to not have any way of understanding what is on top of what, and you get the result you see.
There really is not much of a “fix” for this other than moving the objects farther apart.
This is to do with the range of values possible in the depth buffer. The buffer is 32 bit IIRC so the range between the near clip and far clip has to be represented in that buffer
If the range is very large, there is only so many decimals a the depth buffer can actually represent Making z fighting more likely when polygons are closer to each other.
Making the range smaller helps increase the possibile decimals represented in 32 bits allowing polygons to be closer together without z fighting
See Z-fighting - Wikipedia for more detail
Thats what I just said
Is it possible to move with integers - Help & Support - PlayCanvas Discussion
I believe a double float is a 64 bit float right?
But that’s on javascript only.
GPU’s are 32bit in majority of cases.
The bit that was missing was narrowing the range can help with these issues as well
So if a camera has a range from 0 to 1 would the entire float be shoved into that 1 unit or would it just use the first segment of the float? Is the rest of the float values wasted or are they all crammed together?
I don’t know exactly how it works under the hood but I do know that the float represents the entirety of the range between the near and far clip
So objects can’t be as close together between 0 and 2 compared to 3 and 4
(Martin, please correct me if I’m wrong here)
So the render distance contains the entire float?
I’m not sure what you mean by render distance here as it’s not a factor. The range between near and far clip of the camera is represented by entire float of the depth buffer in my understanding of how it works.