Material that draws nothing?

Is there a concise way to make a material that draws nothing (nodraw/skip/invisible material)?

I want to use the multi-material feature with BoxGeometry to hide the top and bottom of the box, like something from the examples below.

Things I’ve tried

Passing undefined somehow works, even though a quick glance through WebGLRenderer seems like it shouldn’t. Typescript also doesn’t like it and this isn’t documented anywhere so I’m hesitant on using it

  const duct = new THREE.Mesh(ductGeometry, [
    baseMaterial,
    baseMaterial,
    undefined as any, // no material for these faces (+Y/-Y)
    undefined as any,
    baseMaterial,
    baseMaterial,
  ]);

I could also set colorWrite, depthWrite, and stencilWrite to false, but not sure if this is better/worse

Did you try:

new THREE.MeshBasicMaterial( {transparent: true, opacity: 0} );

or

new THREE.MeshBasicMaterial( {
			blending: THREE.CustomBlending,
			blendEquation: THREE.AddEquation,
			blendSrc: THREE.ZeroFactor,
			blendDst: THREE.OneFactor
} )
1 Like

this is how drei library does it

3 Likes

.visible = false would skip the draw call entirely, and will be cheaper than alpha blending, discard, colorWrite=false, etc… Alternatively you could use the geometry.groups API to remove those groups from the geometry entirely. But if it’s just the one cube, not a big difference performance-wise anyway.

7 Likes

Didn’t realize there was a geometry groups API, thanks!

I might end up with .visible later, just haven’t gotten to the point where we want that much control across all of this type of object yet.

If you need just a box without bottom and top, you could use:

new THREE.CylinderGeometry( 1, 1, 1, 4, 1, true )
3 Likes

That box has a radius :joy::thinking::flushed:

2 Likes

Why not :slight_smile:

class LidlessBox extends THREE.Mesh{
  constructor(w, h, d, color){
    let r = Math.cos(Math.PI * 0.25);
    let g = new THREE.CylinderGeometry(r, r, 1, 4, 1, true)
      .rotateY(Math.PI * 0.25)
      .scale(w, h, d)
      .toNonIndexed();
    g.computeVertexNormals();
    let m = new THREE.MeshLambertMaterial({color: color, side: THREE.DoubleSide});
    super(g, m);
  }
}
...
let lidlessBox = new LidlessBox(2, 2, 2, "#fff");
scene.add(lidlessBox);

I would use four merget planes though, to have control for segmentation :slight_smile:

4 Likes

really cool! that’s amazing!

class DominatedGeometry extends THREE.CylinderGeometry{...
2 Likes