Search code examples
javascriptthree.js3dlight

Light mesh with specific light three js


I have a scene with a couple of objects and some objects in these case the spheres i want to be affected by the lights with the colors pink and blue. But i also have a tube geometry that should only be affected by a white light, without being affected by the pink and blue lights.

See image below for demonstration of the problem: What happens now: enter image description here But i want the tube not to be pink and blue but gray: enter image description here

Currently i do this with a meshBasicMaterial but that prevents the the tube from looking 3D.

So how do i create this gray tube with a MeshLambertMaterial that is not affected by the pink and blue lights?

See code below for how i generate my scene now:

# Generating of spheres:
for (var i = 0; i < 5; i++) {
        var SphereGeometry = new THREE.SphereGeometry(2, 20, 20);
        var SphereMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
        var Sphere = new THREE.Mesh(SphereGeometry, SphereMaterial);
        Sphere.position.set(i * 7 -14, 0 + Math.random() * 5 - 2.5, 2);
        spheresArray.push(Sphere);
        scene.add(Sphere);
    }

#Generation of tubes:
for (var i = 0; i < CurvesArray.length; i++) {
        var geometry = new THREE.TubeGeometry( CurvesArray[i], 20, 0.5, 8, false );
        var material = new THREE.MeshBasicMaterial( { color: 0xe3e3e3 } );
        var mesh = new THREE.Mesh( geometry, material );
        scene.add( mesh );
    }

#and these are my lights:
var spotLight = new THREE.SpotLight( 0xff00cc );
    spotLight.position.set( -10, 3, 30, 100 );
    lightsArray.push(spotLight);
    scene.add(spotLight);

    var spotLight2 = new THREE.SpotLight( 0xaa99cc );
    spotLight2.position.set( 5, 15, 10, 100 );
    lightsArray.push(spotLight2);
    scene.add(spotLight2);

    var spotLight3 = new THREE.SpotLight( 0x0022bb );
    spotLight3.position.set( 2, -15, 10, 100 );
    lightsArray.push(spotLight3);
    scene.add(spotLight3);

    var light = new THREE.AmbientLight( 0x5f5f5f );
    scene.add( light );

If any additional information is required or something is not clear let me know so i can clarify!


Solution

  • Use layers: https://threejs.org/docs/#api/en/core/Object3D.layers

    Example: https://jsfiddle.net/mmalex/1xr356zf/

    1. Lights will affect only objects that share same layer.
    2. Camera will see objects that belong to the layer, where camera belongs to.

    Assign your objects and lights layers:

    for (var i = 0; i < 5; i++) {
        var SphereGeometry = new THREE.SphereGeometry(2, 20, 20);
        var SphereMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
        var Sphere = new THREE.Mesh(SphereGeometry, SphereMaterial);
        Sphere.position.set(i * 7 -14, 0 + Math.random() * 5 - 2.5, 2);
    
        // set layers to Spheres
        Sphere.layers.set(i%3); // <<=== check here!
        spheresArray.push(Sphere);
        scene.add(Sphere);
    }
    

    Assign layers to lights:

    var spotLight = new THREE.SpotLight( 0xff00cc );
    spotLight.position.set( -10, 3, 30, 100 );
    spotLight.layers.set(0); // << === layer 0 is by default
    lightsArray.push(spotLight);
    scene.add(spotLight);
    
    var spotLight2 = new THREE.SpotLight( 0xaa99cc );
    spotLight2.position.set( 5, 15, 10, 100 );
    spotLight2.layers.set(1);  // << === layer 1 set to spotLight2
    lightsArray.push(spotLight2);
    scene.add(spotLight2);
    
    var spotLight3 = new THREE.SpotLight( 0x0022bb );
    spotLight3.position.set( 2, -15, 10, 100 );
    spotLight3.layers.set(2);  // << === layer 2 set to spotLight3
    lightsArray.push(spotLight3);
    scene.add(spotLight3);
    

    And render layers one by one:

    let animate = function() {
      requestAnimationFrame(animate);
    
      controls.update();
    
      renderer.autoClear = true;
      camera.layers.set(0); // << == switch camera between layers
      renderer.render(scene, camera);
    
      renderer.autoClear = false; // don't remove previous layer results
    
      camera.layers.set(1); // << == switch camera between layers
      renderer.render(scene, camera);
    
      camera.layers.set(2); // << == switch camera between layers
      renderer.render(scene, camera);
    };