5
\$\begingroup\$

Whenever a camera is "far" away (its location is some "large" vector), trouble arises when rendering objects close to it: It is the classic precision loss from subtracting 2 floating point numbers.

I know these ways around it:

  • using doubles for projection/viewing transformations (may not be feasible/possible on mobile devices),
  • doing the subtraction on the CPU (with doubles or integers) and uploading the (relative) position of the object into the shader. This position vector is then added to the vector, that is to be transformed in the vertex shader,
  • tweaking the camera view matrix or model matrix. These matrices are then combined on the CPU and uploaded.

How do these methods compare? Have I missed some other approach?

\$\endgroup\$
6
  • \$\begingroup\$ Questions is, do you really need camera "far"? No in 99% cases! You can scale. \$\endgroup\$
    – wondra
    Aug 5, 2014 at 9:30
  • \$\begingroup\$ That may be true, but 1% > 0%. The issue is really a large world size. If the world is large the camera may stray "far" and one has to take that into account. \$\endgroup\$ Aug 5, 2014 at 9:33
  • \$\begingroup\$ So you may scale it. Why messing with doubles instead of bringing it to range where float is precise enought? \$\endgroup\$
    – wondra
    Aug 5, 2014 at 9:36
  • \$\begingroup\$ Scaling is the wrong idea here. You lose precision, whenever you subtract 2 floats, that are close enough. You could make the world smaller, but that would be a limitation. \$\endgroup\$ Aug 5, 2014 at 9:52
  • \$\begingroup\$ @wondra, because of the way floating point works, you don't actually gain precision by scaling down. You still have the same number of mantissa bits, and the ratio of max-error:desired-length remains the same, so the visible error is the same (even if the numbers are smaller). A better solution is often to move the world so that objects near the camera are also near the origin, where the error is smallest relative to the sizes/separations/velocities of the objects you're rendering. \$\endgroup\$
    – DMGregory
    Aug 5, 2014 at 15:41

1 Answer 1

3
\$\begingroup\$

I think you could look at how the Infinity Engine (now I-Novae Engine) solved this issue. (Unfortunately I can not find the blog post anymore.)

First the engine maintains multiple levels of resolution, depending object importance. For the outermost scale it uses 128 bit floating points, which is enough to model the solar system reliably at meter scale. (I did not do the math...)

The underlying problem is, that anything the scale of planets, even 32 bit floats start to quickly loose resolution. But on the other hand using anything other than 32 bit floats for rendering is unbearably slow. (At least it was at time.) Since they wanted "infinite" view distance, this posed a real problem.

They approached the problem with three solutions:

First the engine create a separate scene for rendering that is centered around the camera. This ensures that the little objects where precision matters are correctly placed. (Little details are procedurally filled in.)

Really large and far away objects, like space stations, planets or an entire nebula are rendered separately. In many cases they are scaled so that they properly fit into the range of the 32 bit floats. This is then put into a the final scene using billboarding.

Finally everything that is farther away than a certain threshold is submitted for rendering using a logarithmic scale. This is primarily done, to preserve z-buffer resolution for near objects while still being able to render the space station in front the gas giant.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .