ThreeJS and the transparent problem

Can anyone tell me if this well known transparency stacking issue is solved when using the web GPU renderer?

I hate to generalize from a single example, but maybe so.

I have upgraded to WebGPU version r167 and am trying to add the excellent WebGPU smoke generator (from the three.js examples) and am having a serious case of deja vu. Sometimes the island is in front of the smoke and other times the smoke is (properly) emitting from the island. I re-ordered the smoke generator to the front of the object list and it helped a bit. Otherwise, it seems that this problem probably still exists in WebGPU.

I will see if I can create a small demo to illustrate.

There aren’t really any silver bullets for transparency afaik.

Alpha hash is great on higher res displays where the pixels are small enough that the hashing falls below a visual threshhold, and its great at reducing overdraw on High DPI, low power GPUs. (retina)

It’s also really great mixed with TAA where the TAA makes it work better at a lower cost than forward blending.

But the vast majority of threejs apps don’t use taa, and have to run on all devices… including chonky pixel devices.

The ā€œidealā€ transparency depends on too many factors to declare one The Best.

  • forward transparency (aka the default): reasonably fast, suffers from overdraw/blending, basically requires sorting hacks to get ordering that looks good or disabling depthwrite and pretending transparent things don’t intersect each other. but fast and well understood. used everywhere.

  • hash - Fast… looks good on high dpi… on regular dpi displays, can look hashed.

  • hash+taa - fast transparency + overhead of TAA + taa artifacts/control
    can look fantastic with the right setup

  • depth peeling — higher complexity… designed for accuracy… higher overdraw+blending … only one full implementation for threejs that I am aware of @dubois

none of the above support ior/transmission except for:

  • MeshPhysicalMaterial+transmission… similar caveats to forward But additional overhead since it does multiple rendering passes, but can look amazing.

  • path tracing – accurate but slow, super complex… a complete rendering pipeline probably mostly useful for high quality offline rendering imo

3 Likes

Damn, I was hoping that with webGPU, those issues would belong to the past.
I’ve never experienced the transparency bug in Sketchfab, do they have their own 3d engine, not based on webGL ?

Ima leave this implementation (live demo) and this discussion here.

3 Likes

If it wasn’t based on webGL I doubt it would run in a browser, at least without plugins of some sort, like flash used to be. Is the product you are referring to online? Like, on a webpage?

Let me leave a few links too,
Thread with demos:

Discussion for sharing stencil buffers, this is from 2018 (wow still open!!) not sure if things changed but there’s mention of depth textures. @gkjohnson is a collaborator I believe, maybe he can push it.

This was also proposed as an example, was stuck for a few years so I closed it:

I think that my demo is still the oldest, if any credit can be thrown my way it would be very much appreciated. I am having a really hard time proving that I know anything about threejs, and it’s hard to put food on the table.

1 Like

I was reffering to https://sketchfab.com , a popular 3D model viewer

Yeah, since no unity player, flash and such is needed to run sketchfab we can assume that they run on webGL, there simply isn’t another way to do this in the browser.

I’m facing issues with transparency and overlapping meshes similar to what’s being discussed here. But I didn’t find any solution which suits my case.

I’m gathering all the resources I found here for future reference and also for other users:


6 Likes

after going through a lot of references and scratching my head for weeks, I was able to fix my issue with the method suggested here with a small change.

First of all, this solution is specific to my case where I have 3d grid of adjacent boxes.
Note that the faces exactly adjacent, the boxes don’t intersect/overlap with each other.

In my case with the default settings, the following screenshot is how it looks like without default souble-sided material & transparency.

And with below change this screenshot is how it looks like


Scale the mesh ever-so slightly to solve the z-fighting issue so that the faces don’t exactly overlap

const scale = boxDimensionVec.clone().multiplyScalar(0.99);
mesh.scale(scale)

use shader definitions to conditionally apply colors to only front-side of the mesh (as mentioned in the following github discussion)

void main() {
    #ifdef FLIP_SIDED
        gl_FragColor = vec4( 0, 0, 0, 0.0 );
    #elif defined( DOUBLE_SIDED )
        gl_FragColor = ( gl_FrontFacing ) ? vec4( 1, 0, 0, 0.5 ) : vec4( 0, 0, 0, 0.0 );
    #else
        gl_FragColor = vec4( 1, 0, 0, 0.5 );
    #endif
}