4
\$\begingroup\$

I've been working on a planet sized and shaped terrain lib for a while (In webgl and Unity) and have a couple of working implementations [Quadtree cubesphere and circular clipmaps].

But both of them suffer from the same problem. In the GPU vertex shader I move the vertices to their correct location on the planet. But 16 bit floats can't handle values that go into the millions. So when you get close to any vertex in the terrain it jiggles from the GPU rounding errors.

With the quadtree solution this is how I put vertices where they belong in the shader:

vec3 newPosition = vec3(normalize(StartPosition.xyz + (WidthDir * position.x + HeightDir * position.y) * Width) * Radius);

In the circular clipmaps I create a point at 0,0,1 and use two quaternions to rotate it to where it belongs (one for where the point is in the clipamp and one for where the clipmap should appear on the planet), then multiply it by the planet radius.

But both implementations require the multiplication of the planet's radius [the clipmap also has one quaternion with precision far higher than a 16 bit float, at ground level it will be a precision of 1/6000000 of PI].

So does anyone know how to handle this problem on the GPU so that at least the points closest to the camera have position values close to zero and no large number multiplication? Or is the only solution to set the positions on the CPU and just do some math work to make sure the vertices on the side of the planet closet to the camera always have values close to zero?

enter image description here

\$\endgroup\$
4
\$\begingroup\$

You can read a more detailed answer here:Which is the best LOD method for planet rendering?

I'm doing exactly something similar for my computer science degree thesis and attacked the same problem.

The problem you have is jitter, and you will find another one more called z-fighting.

Jitter: Most of today’s GPUs support only 32-bit floating-point values, which does not provide enough precision for manipulating large positions in planetary scale terrains. Jitter occurs when the viewer zooms in and rotates or moves, then the polygons start to bounce back and forth.

The best solution for this is to use "Rendering Relative to Eye Using the GPU" method. This method is described in the book "3D Engine Design for Virtual Globes" (I'm sure you can find it on the internet aswell) in where basically you have to set all your positions with doubles on CPU (patches, clipmaps, objects, frustrum, camera, etc) and then MV is centered around the viewer by setting its translation to (0, 0, 0)T and the doubles are encoded in a fixed-point representation using the fraction (mantissa) bits of two floats, low and high by some method (read about Using Ohlarik’s implementation and The DSFUN90 Fortran library).

Although the vertex shader requires only an additional two subtractions and one addition, GPU RTE doubles the amount of vertex buffer memory required for positions. This doesn’t necessarily double the memory requirements unless only positions are stored.

Depth Buffer Precision: Z-fighting. As we are rendering very large terrains, in this case: planets, the Z-buffer has to be HUGE, but it doesn't matter wich values you set for znear and zfar, there will always be problems.

As the Z-buffer depends on a float point interval, and also it is linear (although perspective projection is non linear) values near the eye suffer from Z-fighting because the lack of precision 32-bit floats have.

The best way to solve this problem is to use a "Logarithmic Depth Buffer" http://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html

A logarithmic depth buffer improves depth buffer precision for distant objects by using a logarithmic distribution for zscreen. It trades precision for close objects for precision for distant objects. Since we are rendering with a LOD method, far objects require less precision because they have less triangles.

I hope I could help, if you need anything more you can email me.

\$\endgroup\$
  • \$\begingroup\$ The jitter solution sounds very computationally expensive. I wonder if the parallelism lost from the 64bit math emulated in 32bit floats will make the GPU solution enough faster than the CPU to warrant all the complexity of its implementation. I've had another thought. In my quadtree example, with an Earth sized planet, I start noticing floating point errors when vertices get to around 300 meter resolution. I'm going to create a test implementation where the terrain switches to a plane at that point. With fog I'm hoping the loss of the curvature of the planet isn't overly noticeable. \$\endgroup\$ – RodgerDodger Jan 20 '14 at 16:12
  • \$\begingroup\$ It's not much expensive (depending on your implementation) you can get the book examples from a git repositories and check the code and precision, it is just a few more substractions and additions in the vertex shader, that is the advantage of GPU RRTE. Email me if you want the book nosmirck@gmail.com \$\endgroup\$ – nosmirck Jan 20 '14 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.