Back side of material doesn't cover full view when inside object

Ok, so I have my atmosphere Group of sphere meshes up and running for my globe, consisting of:

  • a BackSide mesh called skies, placed “inside” as the “sky color” (using skies.renderOrder = 1 and having its normals flipped in the shader as described here)
  • a DoubleSide mesh called limit, as an occlusive barrier placed “between” the “inside view” and “outside view” (via the limit.renderOrder = 0 and limitmaterial.colorWrite = false combo)
  • a FrontSide mesh called atmos, placed “ouside” as the atmosphere “seen from space” (using atmos.renderOrder = 2)

all of them having a radius of 1.02 (meaning 1.02 * 6371 = 6498.42 km if we equal 1 from Three.js with the actual Earth radius), but I came across some typical “glitch” encountered in most 3D systems, where although I’m inside the skies mesh as per camera.position.distanceTo(skies.position) (which is multiplied with the real Earth radius to give the distance in km in the tooltip from the screenshot below), the back side of that mesh doesn’t cover the entire view of the camera, as it should have (notice the blue back side not extending up to the top of the view, although the camera is inside the back side mesh as per the displayed distance):

Inside View - Problem

and a zoomed out view, for anyone curious about the principle of showing the “view from space” of the atmoshpere when seen from distance, versus showing the “view from ground” aka the sky when seen from “inside” the atmosphere (as in the first image):

Inside View - Zoomed Out

My questions are:

  • why does this happen and is it the expected behavior?
  • if so, what can be done to correct the situation and show the back side of a mesh as covering the full view of the camera when the latter is inside the said mesh?
  • if nothing can be done, what is the formula or the variables / values on which the amount of back side material that is displayed when in such a situation depends on (so I can compute its visibility in the shader, and hide the skies if it’s not covering the entire view)?

Let me know if I’ve not been clear enough with my question or decription. I believe you can replicate what I encountered by creating a simple sphere mesh having .side = BackSide on its material and try to navigate slightly inside of the boundary of the mesh by placing yourself / the camera on a secant line intersecting the sphere.

I think I am struggling a bit to understand what is happening from the description, I don’t suppose it’s possible to simplify a version of this into a JSFiddle or Codepen?

You may find it helpful to place a second camera at the offending position, and add a CameraHelper to it, so that you can visualize the near/far planes. The near plane intersecting the sky sphere might explain the problem you are seeing.

1 Like

Thanks for answering. I suspected the same in regards to the near plane being the “culprit” for this. Here is a fiddle to illustrate the effect - the clipping will occur there at the bottom of the image instead. For conveniency, I also assigned the M key to instantly get to such a position where things are clipped when they shouldn’t (at least when it comes to replicating real physics and such) - just run the fiddle, click the canvas to focus on it, and press M to jump to that point. You can uncomment updating the controls if you like to better understand the position, but that will also look at the object’s center so will not show the clipping (the angle between the surface normals and the camera direction must be closer to 90 degrees for the clipping to occur).

I discovered that this happens for .FrontSide material as well, so I didn’t bother to use a back side material anymore. Is there a feasible solution for this? I mean, I do use logarithmicDepthBuffer: true in the renderer from my actual code, to avoid Z-fighting, so I can set the near plane to a smaller value (currently it’s at 0.01), but I have a very large far plane distance at 720000 (which I need) and I’m not sure if avoiding the Z-figthing will be effective if I further lower the near plane distance.

EDIT: I appears lowering the near plane distance solves the issue, after all. I set it at 0.00001, the far plane remaining at 720000 and didn’t seem to produce any drawbacks or artefacts, so it’s all good for now - I’ll mark your answer as the solution, thanks. Of course, without the logarithmicDepthBuffer: true workaround, the Z-fighting artefacts are visible, but the setting successfully eliminates them.

That sounds like a good solution – I wonder if camera.zoom would allow you to narrow the field of view and not need to reduce the near plane as much? But there may not be any perfect solution if the camera can get arbitrarily close to this sphere’s surface.

Earlier, I used for a little while camera.zoom and had some plans with it, so normally it would be the preferred choice if what you said would work. Thing is, I have a bunch of things set up based on the “normal” / unaltered field of view (e.g. initial position being precisely the geostationary orbit distance of 42164 km to Earth’s center, field of view set according to that distance aka 17.38 degrees so that Earth is full view, the displayed distance calculation also based on these values, the raycaster as well, etc.), and I’m not sure to what degree changing the camera.zoom will affect these, in order to avoid major changes to the code as a result.

In other words, it’s an excellent alternative if it works as you suspect, however in a practical sense it’s more feasible to lower the camera.near if there are no downsides to that (and so far, it looks there aren’t, thanks to the logarithmic depth buffer switch). I’ll definitely keep the camera.zoom adjustment in mind as a potential alternative, so many thanks for letting me know of it. :ok_hand:

Since you mentioned it, the camera is not supposed to entirely get arbitrarily close to the sphere’s surface, it only has to be able to get close enough to seem like the “viewer” (aka the camera) is “on the ground”. In other words, it doesn’t really matter if it doesn’t precisely “touch” the surface, but it has to look like it. In real terms, if the camera is the equivalent of a spaceship navigating around Earth, it should be able to look like I can “land” with it, that’s all. I’m trying to get as realistic as possible with everything here, I don’t want my project to be like many others where you can tell from the first look that it’s an artistic representation that doesn’t really follow reality.

1 Like