1
votes

When I add a spot at runtime nothing happens. I have to change the material of the objects to see the light on the modified objects.

I added MyMaterial.needsUpdate = true; : it is the default and it changes nothing.

I did a simple test with a plane object (PlaneGeometry + MeshPhongMaterial).
When I press the "L" key I add a SpotLight ==> nothing happens.
Then when I press the "M" key I assign a new material to the plane ==> I see the spot light.

I'm missing something but I don't know what...

I use three.js r69

WebGLRenderer

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(0xffffff, 1);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.shadowMapWidth = 1024;
renderer.shadowMapHeight = 1024;

The plane :

var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshPhongMaterial({ color: 0xffffff });
planeMaterial.side = THREE.DoubleSide;
planeMaterial.needsUpdate = true;
plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.set(Math.PI / 2.0, 0, 0);
plane.receiveShadow = true;
plane.castShadow = true;
scene.add(plane);

Key actions (with THREEx.KeyboardState.js) :

function updateKey() {
    // Add light
    if (keyboard.pressed("L")) {

        var spotLight = new THREE.SpotLight(0xffffff, 1.0, 0.0);
        spotLight.position.set(0, 15, 0);
        spotLight.angle = 1.39;
        spotLight.intensity = 0.5;

        var lightTarget = new THREE.Object3D();
        lightTarget.position.set(10,0,0);
        scene.add(lightTarget);

        spotLight.target = lightTarget;
        spotLight.castShadow = true;
        spotLight.shadowMapWidth = 1024;
        spotLight.shadowMapHeight = 1024;
        spotLight.shadowCameraNear = 0.1;
        spotLight.shadowCameraFar = 50;
        spotLight.shadowCameraFov = 160;
        spotLight.shadowCameraVisible = true;

        scene.add(spotLight);
    }

    // change material
    if (keyboard.pressed("M")) {
        var mat = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
        mat.side = THREE.DoubleSide;
        plane.material = mat;
        }
}
1
I saw your answer before I posted but I thought (or I did not understand...) that "needsUpdate" was a state variable. That's why I set it to true only once. And thanks for all your answers here !AllForum

1 Answers

0
votes

Here is an example from the three.js editor, that is included in the library. When a light is added at runtime, this function is invoked:

function updateMaterials() {

    editor.scene.traverse( function ( node ) {

        if ( node.material ) {

            node.material.needsUpdate = true;

            if ( node.material instanceof THREE.MeshFaceMaterial ) {

                for ( var i = 0; i < node.material.materials.length; i ++ ) {

                    node.material.materials[ i ].needsUpdate = true;

                }

            }

        }

    } );

}

As you can see, it sets the needsUpdate flag for all other materials that are in the scene. When doing this, it should be updated with the next render. You should give it a try.