mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
100.32k stars 35.2k forks source link

Issue with Achieving Occlusion While Maintaining Transparency of a 3D GLTF Model #27138

Closed danieleCTM closed 7 months ago

danieleCTM commented 7 months ago

Description

I am encountering an issue with a 3D model of an arm that I want to be transparent yet still occlude a watch model behind it. While I have successfully managed to render the arm with transparency, it fails to occlude the watch as intended.

Reproduction steps

The arm model should be transparent to the viewer and, at the same time, should prevent the watch model from being visible where it is positioned behind the arm.

While the arm model is transparent, it does not occlude the watch model behind it. The watch is fully visible as if there's no arm model occluding it.

Code

async function initializeThreeJS() {
  return new Promise<void>((resolve, reject) => {
    // Initialize Three.js
    scene = new THREE.Scene();
    const aspect = video.videoWidth / video.videoHeight;
    const frustumSize = 10; // You can adjust this value to zoom in or out
    const width = frustumSize * aspect;
    const height = frustumSize;

    // Add the lights
    //const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    //scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(1, 1, 1);
    scene.add(directionalLight);

    camera = new THREE.OrthographicCamera(
      width / -2, width / 2,
      height / 2, height / -2,
      1, 1000
    );

    renderer = new THREE.WebGLRenderer({ canvas: canvasElement3D, antialias: true, alpha: true });

    // Add HDR
    const pmremGenerator = new THREE.PMREMGenerator(renderer);
    pmremGenerator.compileEquirectangularShader();

    new RGBELoader()
      .load('assets/hdr/environment.hdr', (texture) => {
        const envMap = pmremGenerator.fromEquirectangular(texture).texture;
        scene.environment = envMap;
        texture.dispose();
        pmremGenerator.dispose();
      });

    // Position the camera
    camera.position.z = 5;
    camera.updateProjectionMatrix();

    const loader = new GLTFLoader();

    let modelsLoaded = 0; // Counter for loaded models

    // Function to check if all models are loaded
    const checkAllModelsLoaded = () => {
      modelsLoaded++;
      if (modelsLoaded === 2) { // Check if both models are loaded
        resolve(); // Resolve the Promise if both models are loaded
      }
    };

    loader.load('assets/left_arm.glb', (gltf) => {
      gltf.scene.traverse((child) => {
        if (child instanceof THREE.Mesh) {
          // Set a new MeshBasicMaterial
          const newMaterial = new THREE.MeshBasicMaterial({
            color: 0x00ff00,
            transparent: true,
            opacity: 0.0,
            depthWrite: true,
            colorWrite: false,
          });
          child.material = newMaterial;
          child.renderOrder = 1; // Render first, occludes the watch
        }
      });

      meshLeftArm = gltf.scene;
      scene.add(meshLeftArm);
      checkAllModelsLoaded(); // Increment and check if all models are loaded
    }, undefined, (error) => {
      console.error('Error loading left_arm model:', error);
      reject(error); // Reject the Promise in case of an error
    });

    loader.load('assets/gold_casio_watch.glb', (gltf) => {
      gltf.scene.traverse((child) => {
        if (child instanceof THREE.Mesh) {
          child.renderOrder = 2; // Render after the arm
        }
      });

      meshGoldWatch = gltf.scene;
      scene.add(meshGoldWatch);
      checkAllModelsLoaded(); // Increment and check if all models are loaded
    }, undefined, (error) => {
      console.error('Error loading gold_casio_watch model:', error);
      reject(error); // Reject the Promise in case of an error
    });
  });
}

Live example

I can't show you a live example sadly

Screenshots

No response

Version

r157

Device

Desktop

Browser

Chrome

OS

Windows

gkjohnson commented 7 months ago

Please use the forum to ask the community questions on using three.js.