3D Graphics Quality and Floating Point Accuracy on Android

I am working on a 3D RPG game for the Android called Heroes Of Honesty http://www.PompiPompi.net.

My Galaxy Note Android phone got less than 16M concurrent colors. I am not sure how many, maybe 64K colors, maybe a bit more. The point is that on 3D graphics, gradients look a bit coarse color wise.
There is nothing much you can do about it, this is a hardware limitation although you might be able to choose a different color palette.

However, there is another issue. Floating point accuracy.

There is a limitation to floating point accuracy on the programmable shaders of GLES2.0, and you can even reduce the accuracy on compile time.
This might cause artifacts, and it might be worse than you realize.

The following images were taking from my Galaxy Note phone. You will notice that the top image’s gradients are more coarse. This is exactly the same scene.

Bad Float Accuracy

Good Float Accuracy

You can see the gradients on the fog at the back, and also if you look carefully at the ground you will see at the top picture that it’s more jagged.

So why does this happen? This is the exact same scene.

When drawing a 3D scene you need to set the position of the objects to draw and the position of the camera and light sources.

At this scene the characters are somewhere on the world map away from its center. This mean I am setting the camera look at 3D coordinate to something such as (-1000, 0, 1000).
The character on the center is at the same position of the camera look at coordinate, so it’s position is also set to (1000, 0, -1000).

What if we would draw the same scene, but now we move all the objects, camera and light source so the main player will be at position (0, 0, 0). It doesn’t matter for the scene since we always look from the viewpoint of the camera.

It turns out that doing this improve the floating point accuracy.

Since positioning the camera and characters at (1000, 0, -1000) makes the floating point contain a large number(1000), all the calculations relative to it are done relative to a big number. Therefore there are fewer bits in the floating point assigned to the smaller values.

Such smaller values might be the vertex coordinates of the character’s mesh, but now instead of being 1000.01 they are 0.01 which leaves more room for accuracy.

The top image is rendered when everything is placed relative to the map’s center, and the bottom image is rendered when everything is placed relative to the character’s center.