spotLight not attached to camera properly

Viewed 44

I'm still struggling with getting spotLight to stick to the camera. I can see the light but looks like it stays at one place (?). See the video for reference

//Camera
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 1, 0 );
//spotLight attached to camera
spotlight = new THREE.SpotLight( 0xffffff, 55 );
spotlight.angle = 0.20*(Math.PI / 3);
spotlight.penumbra = 0.1;
spotlight.decay = 2;
spotlight.distance = 200;
camera.add( spotlight);
camera.add( spotlight.target );
                
spotlight.target.position.set( 0, 0, 1 );
spotlight.target=camera;
spotlight.position.copy( camera.position );

controls = new PointerLockControls( camera, document.body );
//adding first person camera from PointerLockControls
scene.add( controls.getObject() );

I also tried grouping camera and spotlight:

const group = new THREE.Group();
group.add(camera);
group.add(spotlight);
spotlight.target=camera;
spotlight.position.copy( camera.position );
controls = new PointerLockControls( group, document.body );

but that did not work either. What should I change? What's missing here?

//edit this is what my current code looks like

import * as THREE from "../node_modules/three/build/three.module.js";
            import { GUI } from './jsm/libs/dat.gui.module.js';
            
            let renderer, scene, camera, gui;
            let spotlight, lightHelper;

            function init() {
                renderer = new THREE.WebGLRenderer();
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                document.body.appendChild( renderer.domElement );
                scene = new THREE.Scene();

                camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 1000 );
                camera.position.set(0,0,1);
                const boxgeometry = new THREE.BoxGeometry( 25, 25, 25 );
                const boxmaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
                const cube = new THREE.Mesh( boxgeometry, boxmaterial );
                scene.add( cube );
                cube.position.set(-20,0,1);

                const ambient = new THREE.AmbientLight( 0xffffff, 0.2 );
                scene.add(ambient);

                **scene.add(camera);
                spotlight = new THREE.SpotLight(0xffffff, 55, 80, 0.8*Math.PI);
                camera.add(spotlight);
                camera.add(spotlight.target);**

                let material = new THREE.MeshPhongMaterial( { color: 0x808080, dithering: true } );
                let geometry = new THREE.PlaneGeometry( 2000, 2000 );
                let floor= new THREE.Mesh( geometry, material );
                floor.position.set( 0, - 1, 0 );
                floor.rotation.x = - Math.PI * 0.5;
                floor.receiveShadow = true;
                scene.add(floor);
                render();

                window.addEventListener( 'resize', onWindowResize );

            }
        function animate() 
            {
                requestAnimationFrame( animate );
                camera.rotation.y+=0.01;
                renderer.render( scene, camera );
            }
            animate();
1 Answers

The setup should look like so:

let camera, scene, renderer;

init();

function init() {

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
  camera.position.z = 1;

  scene = new THREE.Scene();
  scene.add(camera);

  const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
  scene.add(ambientLight);

  const spotLight = new THREE.SpotLight(0xffffff, 0.6, 0, Math.PI * 0.05);
  camera.add(spotLight);

  const geometry = new THREE.PlaneGeometry();
  const material = new THREE.MeshPhongMaterial();

  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setAnimationLoop(animation);
  document.body.appendChild(renderer.domElement);

}

function animation(time) {

  const t = time * 0.001;

  camera.position.x = Math.sin(t) * 0.25;
  camera.position.y = Math.cos(t) * 0.25;

  renderer.render(scene, camera);

}
body {
  margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.134.0/build/three.min.js"></script>

It's important to add the spot light as a child to the camera and the camera itself to the scene.

Related