three.js

three.js - Overlapping layers flickering


When several objects overlap on the same plane, they start to flicker. How do I tell the renderer to put one of the objects in front?

I tried to use .renderDepth, but it only works partly - see example here:

http://liveweave.com/ahTdFQ

var camera, controls, renderer, scene;

init = function() {
  var mesh;
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 100, 1000);
  camera.position.set(50, 50, 150);
  controls = new THREE.TrackballControls(camera, renderer.domElement);
  mesh = new THREE.Mesh(new THREE.BoxGeometry(40, 50, 50), new THREE.MeshBasicMaterial({
    color: 0xff0000
  }));
  mesh.renderDepth = 1;
  scene.add(mesh);
  mesh = new THREE.Mesh(new THREE.BoxGeometry(50, 50, 50), new THREE.MeshBasicMaterial({
    color: 0x0000ff
  }));
  mesh.renderDepth = 2;
  scene.add(mesh);
};

animate = function() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
};

init();

animate();
body {
  margin: 0;
  overflow: hidden;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.122.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.122.0/examples/js/controls/TrackballControls.min.js"></script>

Both boxes have the same size and it works as intended. I can change which of the boxes is visible by setting .renderDepth. But if one of the boxes is a bit smaller (say 40,50,50) the contacting layers are flickering and the render depth doesn't work anymore.

How to fix that issue?


Solution

  • When .renderDepth() doesn't work, you have to set the depths yourself.

    Moving whole meshes around is indeed not really efficient.
    What you are looking for are offsets bound to materials:

    material.polygonOffset = true;
    material.polygonOffsetFactor = -0.1;
    

    should solve your issue. See update here: http://liveweave.com/syC0L4

    var camera, controls, renderer, scene;
    
    init = function() {
      var mesh;
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 100, 1000);
      camera.position.set(50, 50, 150);
      controls = new THREE.TrackballControls(camera, renderer.domElement);
      mesh = new THREE.Mesh(new THREE.BoxGeometry(40, 50, 50), new THREE.MeshBasicMaterial({
        color: 0xff0000
      }));
      mesh.renderDepth = 1;
      scene.add(mesh);
      mesh = new THREE.Mesh(new THREE.BoxGeometry(50, 50, 50), new THREE.MeshBasicMaterial({
        color: 0x0000ff,
        polygonOffset: true,
        polygonOffsetFactor: -0.1,
    
      }));
      mesh.renderDepth = 2;
      scene.add(mesh);
    };
    
    animate = function() {
      requestAnimationFrame(animate);
      controls.update();
      renderer.render(scene, camera);
    };
    
    init();
    
    animate();
    body {
      margin: 0;
      overflow: hidden;
    }
    <script src="https://cdn.jsdelivr.net/npm/three@0.122.0/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.122.0/examples/js/controls/TrackballControls.min.js"></script>

    Use negative factors to display and positive factors to hide.