three.js: Directional light target position cannot be updated

The directional light calculates its direction based on its position and the position of its target, which is an empty Object3D set by default at the origin.

It uses the matrixWorld property of its target for calculation, so if the position of the target is updated the target.matrixWorld needs to be updated too, and this doesn’t happen automatically unless it is added to the scene. See #10218

So if I do this:

var light = new THREE.DirectionalLight( 0xfff000, 2 );
scene.add(light);

light.position.set(0, 1, 0);  // default; light from top shining down

//light.target.position is currently (0,0,0)

Then do this:

light.target.position.set( 0, 2, 0 );

I would expect the light to switch to shining from the bottom up. However nothing happens because the light.target.matrixWorld doesn’t get updated.

One possible fix is to add the target to the scene alongside the light:

scene.add(light, light.target);

Now things work as expected. I can update the docs to reflect this requirement if people think it’s the best approach.

But it would be great if it was automatic. Perhaps the Object3d.add() function could be extended to check if an object has a .target and if so add that too?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 16 (4 by maintainers)

Most upvoted comments

@looeee lookAt() does not work correctly if the object has a rotated/translated parent, so it is restricted. See the inline comment. (The basic problem is getting it to work while still keeping the object “right-side-up” after lookAt() is called. A rotated parent can tilt the object.)

@aardgoose Yes, that seems to be a reasonable approach to consider, but updateMatrixWorld() would need to be fixed.

@mrdoob has been advocating removing target completely for some time. I am keeping an open-mind on that approach. Forcing the renderer to auto-update the target is also reasonable.

Until then, some comments in the docs advising the user to add the target to the scene graph is appropriate.