I checked some of its source code, and I only know that it renders the mesh twice when “depth pre-pass” enabled, and only the depth is rendered the first time. Here is the relevant part of the source code I found:
for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
subMesh = sortedArray[subIndex];
if (transparent) {
let material = subMesh.getMaterial();
if (material && material.needDepthPrePass) {
let engine = material.getScene().getEngine();
// Turn off color writing
engine.setColorWrite(false);
// Turn off Blend
engine.setAlphaMode(Constants.ALPHA_DISABLE);
// Render the mesh with Blend off
subMesh.render(false);
// Turn on color writing
engine.setColorWrite(true);
}
}
// Turn on the Blend rendering mesh again
subMesh.render(transparent);
}
I noticed that there are discussions about oit in the community, some have implemented depth peel, and some have implemented weighted average. But both of these have certain problems. The former consumes a lot of performance, while the latter is incorrectly mixed when the depth changes,such as I move the camera.
The closest thing to babylonjs’ material.needDepthPrePass, in three.js, would be material.depthWrite. If you haven’t yet, I would try disabling that on transparent materials, before getting into anything more difficult like OIT.
You may also want to look into alpha hash/dither as an option.
For transparent objects you can add two versions of the transparent object to the scene with the same transform (or make a multi material mesh) with one material that writes only to depth first and one that draws the blended transparent object. Here’s a js fiddle showing how:
With multiple overlapping transparent objects there are couple ways to do it. You could draw all transparent depth prepass objects first and then draw the blended materials afterward which will result in no transparent overlap effects but therefore also no “pop” effect as the transparent objects reorder when you move the camera. Here’s how the render order is set for that:
Or you could draw the depth prepass material just before drawing the blended material for a single object which would result in removing transparent rendering artifacts within a single mesh and retain transparent object overlap but you’ll still have the transparent resort popping:
And for reference here’s what it looks like with no depth prepass:
@donmccurdy this might be a pretty easy feature to add into three.js with an option per transparent material. Do prefer either of the approaches I listed above if I were to look into adding it?
First of all, I want to thank you@gkjohnson(Sorry I don’t know how to use @…)! Really interesting method, is this the depth pre-pass of babylonjs? Let me try to see if I can eliminate the wrong translucent rendering.
I don’t know the details of how Babylonjs is achieving this but this is generally how a depth prepass works (though if three.js had it built in you wouldn’t have to add a duplicate mesh). A depth prepass can also be done on the whole scene by drawing only the opaque objects to depth to help prevent overdraw and improve performance for intensive fragment shaders.
Judging by the screenshot you posted that does have some transparent object overlap it looks like Babylon is using something more similar to the second approach I posted.
Maybe three.js can also consider adding depth pre-pass?
From the effect point of view, the depth pre-pass of babylonjs does use this method. I now also figure out why his option is only found in the source code. I thought there were some algorithms used elsewhere, like the two OIT algorithms I mentioned above. babylonjs makes a judgment on the fragment shader if it is turned on, it returns (0., 0., 0., 1.) in advance.
babylonjs makes a judgment on the fragment shader if it is turned on, it returns (0., 0., 0., 1.) in advance.
Yes effectively the object is rendered with color writing disabled so only depth is written to.
Maybe three.js can also consider adding depth pre-pass ?
I think it would be useful – I assume you are using the second option I listed above to achieve the affect you want that includes transparent object overlap?