Search code examples
graphicsthree.jsrenderingtransparencycolor-blending

Disable color blending between specific objects in Three.js


I'm developing a visualization tool for 2D objects in Three.js.

Like the example shown, I want to take a set of 2D shapes rendered with an orthographic camera and, because each bigger shape "contains" the smaller ones, I've been using the z coordinate to render them in such a way that the bigger objects are rendered behind smaller ones.

That works. However, I want to disable the color blending as if I wasn't drawing full objects everytime but instead drawing its increments/decrements like the example above. Additionally, I want each to blend with the existing contents, like the background or the map shown in the example bellow.

The question is essencially: Is it possible to disable color blending between a set of objects, while allowing color blending between those objects and others (like the background, for example)?

Example


Solution

  • Render them front to back by setting their renderOrder. The depth buffer will then prevent the ones behind drawing where the ones in front have already drawn

    #c {
      background-image: url(https://i.imgur.com/zYyAndd.jpg);
      background-size: cover;
    }
    <canvas id="c"></canvas>
    <script type="module">
    import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r113/build/three.module.js';
    
    function main() {
      const canvas = document.querySelector('#c');
      const renderer = new THREE.WebGLRenderer({canvas, alpha:true});
    
      const fov = 75;
      const aspect = 2;  // the canvas default
      const near = 0.1;
      const far = 5;
      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
      camera.position.z = 2;
    
      const scene = new THREE.Scene();
    
      const geometry = new THREE.CircleBufferGeometry( .5, 32 );
    
      for (let i = 0; i < 5; ++i) {
        const material = new THREE.MeshBasicMaterial({
          transparent: true,
          opacity: 0.5,
        });
        material.color.setHSL(i / 5, 1, 0.5);
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);
        mesh.position.z = i * -0.1;
        const s = 1 + i * 0.5;
        mesh.renderOrder = i;
        mesh.scale.set(s, s, s);
      }
    
      renderer.render(scene, camera);
    }
    
    main();
    </script>