Why does light position not update?

I'm using three.js to render a moving cylinder:

let renderer, camera, scene, light, cylinder;

initialize();
animate();

function initialize() {
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight);

  scene = new THREE.Scene();

  light = new THREE.SpotLight();
  scene.add(light);

  cylinder = new THREE.Mesh();
  cylinder.material = new THREE.MeshToonMaterial({ color: "#007700" });
  cylinder.geometry = new THREE.CylinderGeometry(3, 3, 12, 25)
  scene.add(cylinder);
}

function animate() {
  cylinder.position.z -= 1;
  cylinder.rotation.x -= THREE.Math.degToRad(2);
  
  light.position.x = cylinder.position.x;
  light.position.y = cylinder.position.y + 100;
  light.position.z = cylinder.position.z;

  camera.position.x = cylinder.position.x;
  camera.position.y = cylinder.position.y + 10;
  camera.position.z = cylinder.position.z + 30;
  camera.lookAt(cylinder.position);

  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: #aaccaa;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.js">
</script>

I want the light to be positioned above the cylinder every frame, but as you can see the cylinder quickly moves into darkness. How come?

Upvotes: 0

Views: 74

Answers (1)

prisoner849
prisoner849

Reputation: 17596

Such thing happens when you don't set the spotlight's target.

The documentation says:

.target

The Spotlight points from its position to target.position. The default position of the target is (0, 0, 0).

Note: For the target's position to be changed to anything other than the default, it must be added to the scene using

Thus, it means that when you move your light with the cylinder, it (the light) points to the center of the scene, as it's a default.

Assign your cylinder as the light's target and you'll get the desired result.

let renderer, camera, scene, light, lightPosition, cylinder;

initialize();
animate();

function initialize() {
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight);

  scene = new THREE.Scene();

  cylinder = new THREE.Mesh();
  cylinder.material = new THREE.MeshToonMaterial({ color: "#007700" });
  cylinder.geometry = new THREE.CylinderGeometry(3, 3, 12, 25)
  scene.add(cylinder);
  
  light = new THREE.SpotLight();
  lightPosition = new THREE.Vector3(0, 100, 0);
  light.target = cylinder;
  scene.add(light);
}

function animate() {
  cylinder.position.z -= 1;
  cylinder.rotation.x -= THREE.Math.degToRad(2);
  
  light.position.copy(cylinder.position).add(lightPosition);

  camera.position.x = cylinder.position.x;
  camera.position.y = cylinder.position.y + 10;
  camera.position.z = cylinder.position.z + 30;
  camera.lookAt(cylinder.position);

  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: #aaccaa;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.js">
</script>

Upvotes: 2

Related Questions