2

how to hide/disvisible intersection of two object3D by three.js? for example:

there are two spheres are 'S-Red' and 'S-Blue'

because S-Red is transparent so looks like:

enter image description here

but I hope can display like this

enter image description here

Nazim Kerimbekov
  • 4,712
  • 8
  • 34
  • 58
jason
  • 21
  • 1
  • I haven't done this before but you can try this http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/ – Xedret Jun 30 '19 at 09:09
  • hello Xedret , i tried CSG and BSP but both of then are slowly(need more then 30s to show the result) i hope can show the result in 5~10s via Material – jason Jun 30 '19 at 23:52
  • I have been using WebGL for a while now and as far as I have seen, THREE.Geometry has no boolean operations other than merge, subtraction is not an option... Last time I checked the docs it was revision r103. – Xedret Jul 01 '19 at 03:15

1 Answers1

1

You can set opacity of sphere pixels in fragment shader:

enter image description here

body, canvas { 
  margin: 0;  
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/controls/TransformControls.js"></script>
<script>
  var scene = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera(75, innerWidth/innerHeight, 0.01, 1000);
  camera.position.set(5,5,0);
  var renderer = new THREE.WebGLRenderer();
  renderer.setSize(innerWidth,innerHeight);
  document.body.appendChild(renderer.domElement);
  let orbit = new THREE.OrbitControls(camera, renderer.domElement);
  scene.add(new THREE.GridHelper(500, 100, 0x666666, 0x444444));
  let s1 = sphere(3,  2, 0)
  let s2 = sphere(3, -2, 1)
  let u1 = s1.material.uniforms, u2 = s2.material.uniforms;
  requestAnimationFrame( render );
  
  function sphere(radius, position, color){
      color = color.toFixed(1)
      var geometry = new THREE.SphereGeometry(radius, 50, 50);
      var material = new THREE.ShaderMaterial({
          transparent: true,
          depthWrite: false,
          side: THREE.DoubleSide,
          uniforms: {c: {type: "3f"}, o: {type: "3f"}},
          vertexShader:   `
            varying vec3 p;
            void main() {
              // transfer vertex position to fragment shader, 
              // this value is interpolated by gpu hardware between pixels of triangle, 
              // containing this vertex
              p = position; 
              gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }`,
          fragmentShader: `
            varying vec3 p;  // position of current pixel relative to sphere center
            uniform vec3 c;  // center of current sphere
            uniform vec3 o;  // center of opposite sphere
            void main() {
               vec3 a = abs(p)*50.0;  
               float opacity = a.x<1. || a.y<1. || a.z<1. ? 0.8 : 0.3;               
               // here is test of shpere overlapping   
               opacity = distance(o, p + c) < 3.0 ? 0.0 : opacity; 
               gl_FragColor = vec4(vec3(${color}, 0.0, 1.0 - ${color}), opacity);
            }`
      });
      let mesh = new THREE.Mesh(geometry, material);
      mesh.translateX(position)
      scene.add(mesh);
      let control = new THREE.TransformControls(camera, renderer.domElement);
      control.addEventListener('dragging-changed', e => orbit.enabled = !e.value);
      scene.add(control);
      control.attach(mesh)
      return mesh;
  }

  function render() {
      requestAnimationFrame( render );
      let p1 = s1.position, p2 = s2.position;
      u2.o.value = u1.c.value = [p1.x, p1.y, p1.z];
      u1.o.value = u2.c.value = [p2.x, p2.y, p2.z];
      u1.c.needUpdate = u1.o.needUpdate = 
      u2.c.needUpdate = u2.o.needUpdate = true;   
      renderer.render( scene, camera );
  }
</script>
Stranger in the Q
  • 3,668
  • 2
  • 21
  • 26