Matrix.frustumM problem setting near draw distance

Hi Folks,

The flowing question relates to opengl on android.
When setting the OpenGLES draw distance using Matrix.frustumM I notice that you can’t set the near draw distance to zero and any value less than 1 gives really weird distortion. Setting the near distance to 1 works fine most of the time but when the camera moves closer to objects than this distance it looks horrible because they are not drawn (or a portion of them is not drawn). Is there anything that can be done about this? Many thanks for your time.

With a perspective projection, the relationship between the eye-space Z coordinate and the value stored in the depth buffer is non-linear. The result is that the depth buffer has finer resolution close to the near plane and coarser resolution further away.

As a general principle, don’t make the near plane any closer than it needs to be, and don’t make the far plane any further away than it needs to be.

Assuming that the far distance is many times the near distance, a reasonably accurate approximation is that half the range of depth values (0.0 to 0.5) will be used for Z values between the near distance and twice the near distance. So if the near distance is 1 and the far distance is 1000, depth values between 0.0 and 0.5 will be mapped to Z values between 1 and 2 while depth values between 0.5 and 1.0 will be mapped to Z values between 2 and 1000.

More generally, Z values beyond N times the near distance will only use 1/N of the range, while the remainder will be used by closer values, e.g. three quarters of the depth range (0.0 to 0.75) will be used for Z values between the near distance and four times the near distance and anything beyond that will get the remaining quarter (0.75 to 1.0).

The awkward case is where you can have objects which are very close to the viewpoint in the same scene as objects which are very far away. This is particularly awkward if you only have a 16-bit depth buffer. If you need to have both very near and very far objects in the same scene, you may need to use multiple rendering passes to avoid depth-sorting artefacts.

E.g. if you’re holding an object in front of your face while standing inside a building, with the surrounding landscape visible through the windows, you might first render the landscape with the near distance set to tens of metres and the far distance set to some kilometres, then render the interior of the building with the near distance set to half a metre (or however close the viewpoint could reasonably be to the walls or furniture) and the far distance to tens of metres, then render your hands and the object being held with the near distance at a centimetre and the far distance at half a metre. The depth buffer would be cleared between each pass, so the landscape will always be behind the building and the building always behind the hands and held object.

Thank you for such a comprehensive reply which has helped me fix my problem.
I am now doing 2 rendering passes as you suggest and everything is working perfectly.