Blending of a semi-transparent line over an opaque object is correct, while blending it over another semi-transparent object is incorrect

Two of us are working on the problem of correctly rendering the lines in the figure above, called tethers.

These lines are transparent and we’re producing them with shaders.

However, when they are blended, we’re observing incorrect blending behavior - but only when the object behind the line is itself a transparent object. It works if the object behind is opaque.

Our understanding is that opaque objects are rendered first from front to back in order to avoid overdraw as much as possible, and then transparent objects are rendered from back to front in order to do the blending right. This sounds like the correct approach, but it looks like the blending of the transparent objects with each other is not handling the destination alpha correctly.

Note that we don’t think this is a rendering order problem and that would generate a different artifact, that is the lines would appear behind the tubes instead of in front of them.

This just looks like the blending function is not correct when doing the back-to-front rendering of transparent objects.

We’re happy to try to get to the bottom of this, but it would help us out if someone could point us to any documentation on the details of how the code is currently implemented, or tips on how to efficiently debug shader code in three.js.

Other things that could help us out:

  • Pointing us to the source file for the specific chunk of shader code that handles the transparent-over-transparent blending operations.
  • Is there a way to view the final shader code that three.js constructs?

The repo is here: https://github.com/philipswan/TetheredRing

Shader is in index.html, line 175, “<script id="tetherFragmentShader" type="x-shader/x-fragment">
Tether material is created in main.js, line 1301, “const tetherMaterial = new THREE.ShaderMaterial( {
Tube material is created in transitsystems.js, line 305 “const transitTubeMaterial = new THREE.MeshPhongMaterial( {transparent: true, opacity: 0.25})”.

We discovered that by setting <meshName>.renderOrder = 1 on the tethers and cables (cables are in the distance on the right side) makes the blending work much better for this camera angle; however, we’re still concerned that manually overriding the blending order will break the scene in some other circumstance. Still, perhaps it’s a clue…

Repo is 404 …
Maybe this is related to: three.js docs ?

You probably copy-and-pasted the period - I’ve made that mistake before too.

1 Like

Cool yeah that was the problem. Can you try setting premultipliedAlpha : false on the renderer and see if that affects things?