Overlapping, off-centred translucent objects?

I’m using THREE.js for a plotting/visualizing tool. I was wondering, is there a way to ensure that two transparent surfaces will render properly from all angles, even when they are overlapping? Right now I’m trying this with two spheres, with MeshPhongMaterial, depthWrite off, and opacity set to less than 1, and what I see is that it looks like the engine decides which one is in front and which one is behind by comparing their centres - save then painting all of the object that’s classified as “behind” as if they were covered by the other, even if some specific parts of it are, in fact, in front. I understand this is cheaper than going vertex by vertex to determine the blending (which would probably require multiple passes), but is it possible to have it handled any better, even at the cost of increasing the rendering load? Is there a plugin for this? Or should I write my own shaders? Thanks!

Related: https://github.com/mrdoob/three.js/issues/9977

You can turn off threejs sorting and sort objects yourself, if you want. That will let you optimize for a particular viewpoint. But the general case is difficult.

This isn’t just about sorting though; in general, I’ll probably still unhappy with the result if the sorting affects the whole object rather than parts of it. What I’d need is for each vertex/face to be considered independently, and blended accordingly, depending on whether it is behind another semi-transparent face or not.

That is the difficult case. :wink:

One approach to this is called “depth peeling”. You render an image, Then you “peel” the first layer and render the depths underneath. After only a couple of passes you can get pretty good results.

1 Like

How is that done in THREE.js? Do I need to decompose the geometry in individual triangles/faces? Also, does that result in big performance losses?

No and yes. It’s not at all trivial, but it is possible, depending on your needs it may be possible to quickly prototype, but it may also be quite hard if you want to just have transparent = true work “properly”. It is also very expensive, since you need to render the same objects multiple times and do a lot of pixel reading and writing. Looks correct though :slight_smile:

I’ve been meaning to make an example for this for a while, i’ll try to muster something up over this holiday weekend, there seems to be a demand for this.

2 Likes

I’ve just found that Bablylon.js apparently offers something like this. There’s good results seen with what they call a ‘depth pre-pass’ or faced depth sort:

https://doc.babylonjs.com/resources/transparency_and_how_meshes_are_rendered#things-to-do-and-not-to-do

Is any of these techniques available in THREE.js? Even as a plugin?

Inspired by your post and many others I made this relatively naive implementation of depth peeling (order independent transparency).

https://raw.githack.com/pailhead/three.js/depth-peel-example/examples/webgl_materials_depthpeel.html

(enabled is actually disabled, need to update).

I was really excited and wanted to share this, but i was banned for the last two weeks on account of my religious beliefs, i’m sorry for the late response.

2 Likes

Oh, that’s great, thanks! Do you have any idea what’s the performance hit for large numbers of solids? There seems to be a slight loss of speed when it’s enabled.

P.S. I’ll be away for Christmas holidays but I should get back on the project for which I’d need this in January, do you think then we could discuss e.g. turning it into a proper plugin? If I got a better idea of how the example works I could maybe adapt it to my needs.