Depth peel and transparency

Nice, the peel is definitely more plausible/realistic than the default transparency.

There’s still a case where the color turns solid instead of showing multiple colors from multiple objects that are behind.

F.e. in the following video, I’m looking from below, and moving the mouse to show the area where we see two colors when peel is disabled, then with peel enabled the color becomes implausibly solid instead of showing at least two colors from behind:

1 Like

Can you do a screen shot? Define what makes it inplausible I’m really curious

1 Like

A common transparency problem is liquid inside glass like in this model. Does depth peeling help with this case?

Great work on this so far btw👏

I’m not entirely sure about that one. I don’t see any flickering from sorting, which is what i sort of expected given the shape of the glass and the liquid. It’s pretty opaque though so hard to see. What is the problem with this model?

There’s more details in this thread:

In the video, when peel is enabled, the blue where my cursor is (and the green in the object above it too) becomes solid and brighter. It seems that the other colors should continue to bleed through there, instead of there being only solid blue (and green). Just keep replaying at 4 seconds to see where I enable it at 5 seconds, and it seems some objects are visibly lost from the background.

Regardless it’s really awesome!

Ahh I didn’t realize that was a different video. Have you tried increasing the layers from 1? 1 doesn’t really work, 2 should be ok-ish. Ie. you didn’t actually enable the effect :slight_smile:

1 Like


Here’s that gltf, im not sure if i hooked everything up right but it doesn’t actually look that much different until you put something else in.

I added the “most complicated transparency example” from mrdoob too, one inside the bottle one outside:


Seems like its working ok.



Meh there’s some weirdness when double and single sided are mixed.

Aaaah, that was it. Works great with more layers!

This seems fantastic. Do we know if this is going to be part of core threejs as it seems to cure quite a common and anoying problem?

Cannot be done as long as threejs locks some specific internals. In this case the target renderbuffers. Editing one line in the core would allow for this to be an example or a plugin.

1 Like

Is there a reason why they wouldnt want this as an example / plugin? Is there any downside(performance etc.) to your approach?

1 Like

Well, the algorithm and the approach are a tradeoff. It has upsides and downsides compared to other transparency rendering approaches.

But, allowing users access to the targets render buffer is a different thing. Three.js has many places where this pattern happens:

function private_function(){ 
   _private_object = || 

Which is awesome! For example customDepthMaterial works like this. It’s not really documented, it’s not really explained how it works, but it works. Somewhere deep inside WebGLRenderer you have:


result = customMaterial || materialVariants[ variantIndex ];

So, if you don’t provide customMaterial yourself by slapping it onto a mesh:

mesh.customDepthMaterial //undefined
mesh.customDepthMaterial = myDepthMaterial

It will just use something internal.

When we work with THREE.WebGLRenderTarget three.js creates a render buffer for each target and does not give you any access to it.

My approach requires two different targets to use the same render buffer. Following the pattern present in so many places in three.js you could do.

myRenderTarget = new THREE.WebGLRenderTarget() // render buffer created and you cant access it


myRenderTarget.renderBuffer = myRenderBuffer
myOtherTarget.renderBuffer = myRenderBuffer

As a result, my example could work, but so could many others that we don’t know or that are yet to be written.

I have no idea why this is pattern is selectively applied in some areas but then not in others.

Perhaps you could add a comment here and we could both figure it out :slight_smile:


The color jumps abruptly when crossing the critical angle where the blue and the red are equally close to the camera. That does not look natural.

What’s the critical angle?

Hm, I kind of assumed it was when the spheres are equally close, but I am not sure. Try
camera.position.set(-18.0, -2.5, 26.8)-ish for the pair in the bottle, and camera.position.set(-0.35, -5.40, 31.96) for the pair outside (both with lookAt before enabling the controls). Update: It looks like disabling and enabling again after increasing the peel iteration thing solves the problem. I thought it would respond dynamically to changes on that slider.

Additionally, there is a problem with click handling, which makes using the GUI difficult. I guess it may be another instance of forgetting to supply a domElement to the OrbitControls.

Ah yes the ui is broken beyond belief. It’s not on by default in that scene, i think double sided is messing things up etc. Not being able to share render buffers turned me off from this whole project.


May be this links can help you:
WebGL 2 Order-independent Transparency