Float precision for Shaders

Hello. I am working on an infinite world using a RayMarching system including collision detection for a 6Fov ship. The main code works fine as expected, but I have a big problem with float precision. My distance function for basic primitives returns a Float value. As you know, under Unity we can use Fixed, Half and Float for shaders. However I notice that when my ship goes further in the infinite world according to its start position (0,0,0) there is a visual deformation. I guess that I need to increase the precision trying to implement something similar to a Double float. I tried to find a way to do that, but (even if the problem is well known) there is no clear explanation. Do you have an idea? Any help will be appreciated. Thank you ++

I dont think that implementing doubles in shader is good idea (if even possible). You should make your world player-centristic coordinate system based. In other words player ship should always be in (0, 0, 0) position, but whole world is moving relative this ship-origin. Using this approach all important things (those near player) will always have highest precision math.

4 Likes

On computers you can make shaders with double precision math but the performance is heavily nerfed by the card manufacturers to discourage buying consumer cards over workstation cards. NVIDIA GPUs for example run doubles 32 times slower than singles.

On just about every other platform it’s not available in most devices if it’s available at all.

3 Likes

Thank you for your comments @Ryiah and @Rukhanka . I forget the Double precision. I will try to do my infinite world with a player-centristic coordinate system. It’s a good idea. I wish you the best ++

Where did you get that from?

I’m was running some fluid sims at double precision on my 2070M (consumer card), and it’s only slightly over 2x slower with double than with float (which is exactly what you would expect, since it’s twice as much memory bandwidth and twice the register pressure).

Multiple sources over the years. One that immediately comes to mind is Wikipedia’s statistics. GFLOPS ratings for singles are 32 times larger than the ratings for doubles. Granted statistics like these are just raw estimates of the performance of the device and other factors will bring them closer to each other.

https://en.wikipedia.org/wiki/List_of_Nvidia_graphics_processing_units

1 Like

Hi @Geckoo , as @Rukhanka said, keep the ship at the origin, because the floats have the highest precision there, in general, though it does vary a little depending on the z-buffer implementation.

I called this Continuous Floating Origin (it does not use threshold-based shifting/rebasing).

You will still come into some bad jitter and other strange effects (e.g. wandering objects) and inaccurate motion with spaceships if they travel millions of meters, or even travel over approximately 70km and want to land and go inside a building. The reason is you can get Distant Relative Jitter. So you need a solution for that as well.

With a solution to both, you can travel the whole Solar System continuously, without portal jumps, in single precision alone.

3 Likes

@cosmochristo thank you for your clean explanation. I understand the main principle of the Continuous Floating Origin, but all my controller is based on a traditionnal movement in space. I am struggling hard in order to convert it, and it is in progress. I wish you the best. Thank you ++

1 Like

If you have some specific issues, just ask. Although a basic implementation can be hacked out fairly quick, it is a much bigger job to make a good design that will scale. It took me years to get a good prototype, then more to re-write the main components, add multiuser networking and some integrations, and I am only part-way through rebuilding the framework!

Would continously (per frame) moving the world instead of the player not result in a lot of otherwise unnecessary transformation calculations?

Do this once per some distance traveled from previous world origin.

3 Likes

Not measurably, as @Rukhanka says, it is just one parent node translation. It is also per move, i.e. not necessarily per frame.
For very large scenes, greater than, say, 70km, you need to do a little more if you have to prevent distant relative jitter and related interaction issues, like in:
https://www.youtube.com/watch?v=BSQW0j8a_Ds
.

For one, the original suggestion mentioned keeping the player at 0,0,0 all the time:

Also, I think repositioning one big “World” object that includes, say, 10000 children, results in the world position of all the children to be recalculated as well.* So you’re still getting needless calculations.
*“If something moves every frame, make sure all its children care about position.” (This doesnt really state the issue directly, but I couldn’t find a better source right now)
https://blog.unity.com/engine-platform/best-practices-from-the-spotlight-team-optimizing-the-hierarchy
Sure, for large worlds you need to reposition at some point, but I guess it could still cause hiccups. Especially since large worlds tend to include large amounts of data.