Open Qgel opened 2 years ago
I've looking into this in a bit more detail, and it seems the culprit is the depth sorting function in renderer.py:710.
After some more research, I think I understand that there is no general 'always works' sorting function (especially for whole meshes, but also for individual triangles). However, the current function only considers the distance of the meshes centroid from the camera.
The following distance function would also consider the meshes extents. This fixes the problem in the above case, and also in the scene I'm actually trying to render:
def dist(node):
d_centroid = node.mesh.centroid - cam_loc
d_centroid_norm = np.linalg.norm(d_centroid)
d_extents = node.mesh.extents * (d_centroid / d_centroid_norm)
return -(d_centroid_norm - np.linalg.norm(d_extents))
What would be your thoughts on this? If this is not something that could be used in general, maybe it could be made possible to provide a custom sort function to the renderer or add ordering data to a mesh?
Another thought: Why can't we just set glDepthMask(GL_FALSE)
, i.e. disable depthbuffer writing, after we have drawn all solid objects in renderer._forward_pass()
? This would get rid of the problem, and in my opinion also renders more correctly in general:
We can see that now the inner cube also has transparency to the back wall of the outer cube, wheres before with any ordering one of them would always appear solid.
Qgel's suggestion is good. It should be made available as default or perhaps as a renderer option or material property?
I am trying to render two transparent objects which are 'behind' each other, such as a transparent cube withing another transparent cube with the top cut off, see example below.
However, depending on the order I add the meshes to the scene, and also somehow on the lights, the back object (from camera perspective) sometimes incorrectly does not render through the transparent front object.
The following code can be used to re-produce the issue:
For illustraction, this is the scene rendered in wireframe mode:
However, in solid mode with the code as written above, I get the following result:
Reordering how the meshes are added to the scene fixes the problem and I get the expected result. However, this is not a general solution for more complex scenes. The following is a gif with the above code, but the lines
scene.add(p_cube_hollow)
andscene.add(p_cube_inner_transparent)
are swapped.Increasing the light intensity also fixes the problem, but only with large intensity (and it does not work for my actual scene, but does in this testcase):
Moving the meshes from their initial (0,0,0) position (even by as little as 0.0001) sometimes also seems to fix the problem.