Depth peel and transparency

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 = public.foo || _private.foo 
}

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:

Or

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

instead:

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:

2 Likes

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.

4 Likes

May be this links can help you:
https://gkjohnson.github.io/threejs-sandbox/fat-line-opacity/webgl_lines_fat.html
https://tsherif.github.io/webgl2examples/oit-dual-depth-peeling.html
https://tsherif.github.io/webgl2examples/oit.html
WebGL 2 Order-independent Transparency