1
\$\begingroup\$

I have a project where I have a sphere with a png texture that represents a planet (or a moon in the videos I'm attaching).

Wrapped around that sphere I have a hexasphere (implemented using the results of my question from last year: How to orient a hexagonal tile on a geodesic sphere (Goldberg polyhedron)?).

Almost everything works just fine however I've noticed that in some situations, the hexasphere flickers at some points.

From my experiments, it seems that the problem is the lighting I am using.

The hierarchy of nodes I have is as follows:

bodyContainer    OMNI
    planet         OMNI (sphere, radius:0.987 with image texture as it's only (diffuse) material)
    hexasphere   AMBIENT (hexasphere, radius: 1.0 as described in the linked question)

enter image description here

There are two light sources, both placed at the centre of the "sun" in my larger model. OMNI is an Omnidirectional light source with default settings. AMBIENT is an Ambient light source.

The reason that "body" uses OMNI is that I want the planet or moon to have a light and dark side which changes as the body orbits the sun.

The hexasphere that is co-located with the body by being a sibling of the body in the same container. It needs to use the AMBIENT light source so that it is equally visible on the dark side of the planet or moon.

What I'm noticing, it that when I move the camera further away from the planet, the parts of the hexasphere closest to the camera seem to flicker, and I seem to be able to see through to some of the hexasphere's cells on the opposite of the sphere.

Here are some videos to show what I'm seeing.

This first shows the scene in it's full 'glory' with all nodes in play as described above:

https://youtu.be/o3hdpuLoSbQ

This next one shows the same hierarchy, however I've changed the planet body to use the AMBIENT light instead. Note that there is no flicker, but also, I've lost the dark/light side of the planet.

https://youtu.be/O0Ca-MrYgJc

In this 3rd video, I've replaced the body texture with a simple translucent blue color, and reverted to using the OMNI light. It looks great, but the flickering is back.

https://youtu.be/ftGWnaqoN5I

Finally, I've changed back to the AMBIENT light again, but kept the blue body texture. Note that the flickering is gone again.

https://youtu.be/c6i5vjOEauw

I'm quite positive that this is something I can fix, but I don't understand yet how. Is this simply a weakness in the lighting mechanisms in SceneKit?

Is there something special I should be doing to allow the outer hexasphere to render cleanly (i.e. without the flickering), with the ambient light, whilst having the inner sphere that is using an omni light?

UPDATE

I've found one solution that appears to work, however I'm not sure if this will result in a lower quality visual overall. If I set the material property litPerPixel to NO, then the problem I've outlined goes away. I'm just not sure that the presumed "lower quality" rendering might cause other problems elsewhere.

\$\endgroup\$
2
  • \$\begingroup\$ Do you know what your near and far clipping planes are set to on the camera? It looks like it could possibly be related to loss of precision in the depth buffer, although it doesn’t present itself in quite the way I would expect. \$\endgroup\$
    – Ed Marty
    Sep 29, 2018 at 14:15
  • \$\begingroup\$ For zNear, I use the default of 1.0. zFar by necessity (owing to this being a solar system I'm trying to represent) is quite large: 649,701.38992. I'm basically trying to ensure that no matter where in the solar system I place the camera, I can see Pluto, and the skybox beyond it. \$\endgroup\$
    – PKCLsoft
    Sep 29, 2018 at 22:39

1 Answer 1

1
\$\begingroup\$

I would recommend either rescaling the scene so that things don’t get 600,000 units away, or adjust zNear in proportion to zFar. As the ratio of zFar:zNear gets greater, the depth buffer precision decreases, appearing as z-fighting in surfaces near each other. As the default ratio in SceneKit is 100:1, adjusting zNear to be on the order of 1000 would keep the same ratio, although that does seem quite large. You could try something closer to 10 or 100, and see how that affects the scene.

See here for some details about the ratio problem: https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml

\$\endgroup\$
3
  • \$\begingroup\$ I've tried a couple of things with that, but what I see is that the view becomes quite severely clipped. Planets that are far away disappear, as does the skybox (which I've implemented as double-sided sphere enclosing the solar system). I think trying to dynamically play with zNear and zFar are going to introduce problems where some parts of the model will be constantly being clipped/culled, which will be worse than the flickering. Thus far the litPerPixel setting has not introduced any other side effects. \$\endgroup\$
    – PKCLsoft
    Sep 30, 2018 at 4:11
  • \$\begingroup\$ In that case I would recommend rescaling the scene to be within a more normal range. 600,000 is just really, really big. For example, try scaling everything down so that it fits in the original 1:100, just to see if it helps \$\endgroup\$
    – Ed Marty
    Sep 30, 2018 at 11:59
  • \$\begingroup\$ Thanks. That is something I'll look at, but I really don't know if I can do that without running into floating point issues. It would mean (I think) that, in order to keep everything in place, I'd be relying on the ability to represent positions with very small numbers. I'll look into it this week. It would be nice to fix this without turning off SceneKit features that have been added to improve render quality. \$\endgroup\$
    – PKCLsoft
    Oct 1, 2018 at 7:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .