THREE.JS: Render large, distant objects at correct z-indicies and still zoom into small objects


I've got a scene where I'm drawing(to scale) the earth, moon, and some spacecraft. When the moon is occluded by the earth, instead of disappearing, it is still visible (through the earth).

From my research I found that part of the problem is that the near settings for my camera were much too small, as detailed in the article linked, small values of near cause rounding in z-sorting to get fuddled for very distant objects.

The complexity here is that I need to have fine grain z-indexes for when the camera is zoomed in, to look at a spacecraft (an object with a radius of 61 meters at most, in comparison to the earth, weighing in at r =~ 6.5e+06 meters). In order to make objects on the scale of the moon and earth to render in the correct order, the near has to be at least 100,000 m at which point I cannot look at close objects.

One solution would be to reduce the scale to use kilometers, but I cannot afford to lose that precision, and prefer to use meters.

Any ideas as to how to make very large, distant objects render at the correct z Indices, while retaining scale and ability to zoom into small objects?

My Ideas (which I don't know how to implement):

  • Change z-buffer to include more values, and higher resolution?
  • Add distant objects to a "farScene" which is rendered using a "farCamera" which is controlled by the same controls used on a close-up camera?


Probably that the problem is z-test and not z-precision. this mean: z-test not apply (perhaps because that you render transparent object with alpha blending) or z-test apply with non default testing (e.g. override far instead near).

Try to render the whole scene with simple shader with no transparency in-order to make sure that transparency is not the source of the bug. to solve the z-order without z-test you should sort the object yourself each frame to determine the order of rendering (from far to close).

By : meirm

As per @WestLangley 's answer, the solution is simply to add the optionlogarithmicDepthBuffer: true to the renderer:

this.renderer = new THREE.WebGLRenderer({antialias: true, logarithmicDepthBuffer: true});

This video can help you solving your question :)
By: admin