Summary
When a Mesh with MeshStyle::transparencyBin = true is present in the scene and there is also a visible Line entity, the apparent opacity of the mesh is inconsistent across its faces so that the appearance of the mesh differs depending on the viewing angle, even when the line does not intersect the mesh. If the Line entity is marked invisible via a Visibility component, the same mesh is rendered with uniform transparency across its faces and a consistent appearance from all viewing angles.
Minimal Reproduction (rocky_demo_qt)
The reproduction is implemented in src/apps/rocky_demo_qt/rocky_demo_qt.cpp as follows:
- The demo creates a pair of overlapping square-based pyramids using
MeshGeometry and Mesh. The pyramids are partially transparent (alpha = 0.4) and use a MeshStyle with transparencyBin = true.
- Both pyramids share the same latitude/longitude. One is placed at an altitude of 500 km, and the second is placed at a slightly higher altitude so that the two volumes overlap.
- The demo also creates a single horizontal
Line (via LineGeometry, LineStyle, and Line) positioned north of the pyramids at latitude 15° so that it does not intersect or overlap the pyramids.
- A
Visibility component is attached to the line entity, and its visible flags are set based on the ROCKY_DEMO_LINE_VISIBLE environment variable. When ROCKY_DEMO_LINE_VISIBLE is unset, the line is present in the ECS but not rendered (invisible). When the variable is set, the same line is rendered.
Here is what the mesh looks like when the line is invisible (this is the expected rendered result):
Here is what the mesh looks like when the line is visible. Notice that the left half of the pyramid from this viewing angle appears more opaque than the right half.
How to Reproduce
-
Replace rocky_demo_qt.cpp with the modified version
here and build the demo application.
-
Run without the environment variable:
ROCKY_DEMO_LINE_VISIBLE is unset, so:
- The line’s
Visibility.visible[] flags are all false (line is invisible).
- The line still exists in the ECS, but it does not render.
- Observed behavior:
- The overlapping pyramids appear with uniform transparency.
- The apparent opacity does not change when orbiting the camera around them.
-
Run with the environment variable set:
ROCKY_DEMO_LINE_VISIBLE=1 ./rocky_demo_qt
ROCKY_DEMO_LINE_VISIBLE is set, so:
- The line’s
Visibility.visible[] flags are all true (line is rendered).
- Observed behavior:
- The same pyramids, with the same
MeshStyle and geometry, now show inconsistent transparency:
- One side can appear more opaque than the other.
- The perceived opacity of the overlapping region changes as you orbit the camera.
- This occurs even though the line is spatially separate and does not intersect the pyramids.
Additional Experiments
To rule out geometry or style quirks, I tried variations on how the mesh is constructed and styled, including:
- Toggling
MeshStyle::writeDepth on/off.
- Toggling
MeshStyle::twoPassAlpha on/off.
- Toggling
MeshStyle::drawBackfaces on/off.
- Changing winding order of the faces.
- Dual-winding faces (adding triangles in both directions).
- Duplicating vs. not duplicating vertices on the faces.
In all of these cases:
- With a visible line, the view-dependent transparency behavior described above persists.
- With the line present but invisible (via
Visibility), the mesh transparency is stable and appears uniform across the mesh.
Summary
When a
MeshwithMeshStyle::transparencyBin = trueis present in the scene and there is also a visibleLineentity, the apparent opacity of the mesh is inconsistent across its faces so that the appearance of the mesh differs depending on the viewing angle, even when the line does not intersect the mesh. If theLineentity is marked invisible via aVisibilitycomponent, the same mesh is rendered with uniform transparency across its faces and a consistent appearance from all viewing angles.Minimal Reproduction (
rocky_demo_qt)The reproduction is implemented in
src/apps/rocky_demo_qt/rocky_demo_qt.cppas follows:MeshGeometryandMesh. The pyramids are partially transparent (alpha = 0.4) and use aMeshStylewithtransparencyBin = true.Line(viaLineGeometry,LineStyle, andLine) positioned north of the pyramids at latitude 15° so that it does not intersect or overlap the pyramids.Visibilitycomponent is attached to the line entity, and itsvisibleflags are set based on theROCKY_DEMO_LINE_VISIBLEenvironment variable. WhenROCKY_DEMO_LINE_VISIBLEis unset, the line is present in the ECS but not rendered (invisible). When the variable is set, the same line is rendered.Here is what the mesh looks like when the line is invisible (this is the expected rendered result):
Here is what the mesh looks like when the line is visible. Notice that the left half of the pyramid from this viewing angle appears more opaque than the right half.
How to Reproduce
Replace
rocky_demo_qt.cppwith the modified versionhere and build the demo application.
Run without the environment variable:
ROCKY_DEMO_LINE_VISIBLEis unset, so:Visibility.visible[]flags are allfalse(line is invisible).Run with the environment variable set:
ROCKY_DEMO_LINE_VISIBLEis set, so:Visibility.visible[]flags are alltrue(line is rendered).MeshStyleand geometry, now show inconsistent transparency:Additional Experiments
To rule out geometry or style quirks, I tried variations on how the mesh is constructed and styled, including:
MeshStyle::writeDepthon/off.MeshStyle::twoPassAlphaon/off.MeshStyle::drawBackfaceson/off.In all of these cases:
Visibility), the mesh transparency is stable and appears uniform across the mesh.