Utilizing Directional and Spotlight Lighting with ThreeJS Helper Functions

I am currently utilizing a guide on implementing light in Threejs from Light in Threejs. I have successfully added some light to my scene.

Now, I am attempting to add light to the character in my game but it is still not working. Even though I used the code provided in the guide and only changed the position.set parameter.

 const color = 0xFFFFFF;
 const intensity = 1;

 const light2 = new THREE.SpotLight(color, intensity, 0, Math.PI/3);
 light2.position.set(100, -5000, 1000);

 light2.target = lightTarget;
 light2.castShadow = true;
 const helper2 = new THREE.SpotLightHelper(light2);

After adding the light to my character using the following code:

self.flame.add(helper2);
self.flame.add(lightTarget);
self.flame.add(light2);

I also included a helper, but if I use just the helper in the scene or comment out the line:

 self.flame.add(light2)

I can see the position of the light perfectly. However, when I add the light, the helper disappears (unlike with other lights) and the light behaves unexpectedly.

Can anyone offer assistance?

Answer №1

To ensure proper functionality, the helpers need to be linked to the scene (or at least the SpotLightHelper does). Consider parenting the target to the scene as well.

Remember to execute helper.update for each helper in your code.

'use strict';

/* global THREE, dat */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 45;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 100;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(0, 10, 20);

  const controls = new THREE.OrbitControls(camera, canvas);
  controls.target.set(0, 5, 0);
  controls.update();

  const scene = new THREE.Scene();
  scene.background = new THREE.Color('black');

  {
    const planeSize = 40;

    const loader = new THREE.TextureLoader();
    const texture = loader.load('https://threejsfundamentals.org/threejs/resources/images/checker.png');
    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;
    texture.magFilter = THREE.NearestFilter;
    const repeats = planeSize / 2;
    texture.repeat.set(repeats, repeats);

    const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
    const planeMat = new THREE.MeshPhongMaterial({
      map: texture,
      side: THREE.DoubleSide,
    });
    const mesh = new THREE.Mesh(planeGeo, planeMat);
    mesh.rotation.x = Math.PI * -.5;
    scene.add(mesh);
  }
  const cubes = [];
  let parent = scene;
  {
    const cubeSize = 1;
    const cubeGeo = new THREE.BoxBufferGeometry(cubeSize, cubeSize, cubeSize);
    const cubeMat = new THREE.MeshPhongMaterial({
     color: '#8AC',
     emissive: '#333',
    });
    for (let i = 0; i < 6; ++i) {
      const mesh = new THREE.Mesh(cubeGeo, cubeMat);
      mesh.position.set(1, 0, 0);
      parent.add(mesh);
      cubes.push(mesh);
      parent = mesh;
    }
  }
  cubes[0].position.set(-3, 7, 0);
  
  const color = 0xFFFFFF;
  const intensity = 1;
  const light = new THREE.SpotLight(color, intensity);
  light.position.set(0, 0, 0);
  light.target.position.set(0, -1, 0);
  parent.add(light);
  parent.add(light.target);
  //scene.add(light.target);

  const helper = new THREE.SpotLightHelper(light);
  scene.add(helper);

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {
    time *= 0.001;

    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
      camera.updateProjectionMatrix();
    }
    
    for (const cube of cubes) {
      cube.rotation.z = Math.sin(time) * .4;
    }
    light.angle = THREE.Math.lerp(
       THREE.Math.degToRad(20), 
       THREE.Math.degToRad(80),
       Math.sin(time * 0.77) * 0.5 + 0.5);
    
    helper.update();
    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
html, body {
  margin: 0;
  height: 100%;
}
#c {
  width: 100%;
  height: 100%;
  display: block;
}
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

There is a possibility of encountering an endless update loop in the watcher when utilizing the expression "tabs" error in vue

My code includes a watcher on tabs to prevent them from changing based on the values of the edit. If edit is false, then go to the next tab; otherwise, prevent the change. However, when I try to click on the tab heading to change the tab, I encounter an er ...

Server-side rendering with the Node.js mustache template engine

I am in the process of developing a basic application for compiling mustache templates into static pages on the server side. This is what I have accomplished so far: var view = { title: "Joe", calc: function () { return 2+4; } }; v ...

What steps can be taken to modify this jQuery code so that any changes made are also saved to localStorage

I have successfully used jQuery to change the background color of all my divs with the same class (userNumber1) when I check its checkbox. However, I am now looking for a way to save these changes to localStorage, so that they persist each time the page is ...

Why is my Laravel Vue CRUD not automatically updating the posts section with new data?

Hey there, I've been working on a project using Laravel 5.6 with Vue.js for CRUD functionality. I'm trying to display the posts I've just added in the posts section without having to reload the entire page. However, my current code is only s ...

Setting maximum and minimum zoom limits for an element ID using JavaScript or jQuery

My application features a DIV element with the unique identifier of mainDiv. The issue I am facing is related to zooming functionality, as it currently lacks any set limits - both for scaling up and scaling down. I have been searching on Google for a sol ...

Refreshing user session with the help of selenium's webdriver functionality

Our application requires some external inputs for testing purposes, but this data is only accessible when a user is logged in. To streamline the process and avoid requiring the user to log in multiple times, we store their credentials in a session upon ini ...

Clicking on multiple instances of the same Vue.js component (popover) results in displaying identical data

Attempting to display an AJAX response in a popover shown by clicking an icon (a custom Vue component) brings about a challenge. The issue arises when there are multiple instances of this component, dynamically rendered through the v-for directive within a ...

a function that is not returning a boolean value, but rather returning

There seems to be a simple thing I'm missing here, but for the life of me, I can't figure out why the function below is returning undefined. var isOrphanEan = function isOrphanEan (ean) { Products.findOne({ 'ean': ean }, func ...

Having trouble populating and submitting a selected option from a dropdown menu in Angular?

Upon loading the page, the Category dropdown automatically populates with data from the database. However, when I attempt to select a value from the dropdown and click a button to post the data to a specified URL, an error occurs: ERROR Error: Error tryin ...

Learn how to utilize the Page props in the getServerSideProps method with Next.js

I have passed some properties to the _app page. <PageWrapper> <Component someProps={someProps} /> <GlobalCSS /> </PageWrapper> Can these props be accessed in the getServerSideProps method on each individual Page? export const g ...

Issue with PLUploader in ASP.Net/JQuery: "Add Files" button not functioning post image upload操作

Hello, I've been utilizing the PLUploader controller for ASP.NET in C#. Initially, it works as intended, but after uploading files, the "add files" button becomes disabled or stops working, preventing me from adding more images. Can anyone offer assi ...

What is the best approach for developing an npm package containing multiple Vue directives? Should each directive have its own separate package, or should they

While I have successfully created an npm package by exporting a single vue directive in the src/index.js file, I am now faced with the challenge of creating a package that allows for the use of multiple vue directives. Unfortunately, I have been unable t ...

Unable to retrieve the correct `this` value within an axios callback

Feeling a bit fuzzy-brained at the moment. I've put together this code that downloads a JSON from a URL and displays it on the screen: export default class App extends React.Component { constructor(props) { super(props); this.state = { data: [], } } ...

Passing JSON Data Between Functions within an Angular Controller

In my current setup using Node.js, Angular, Express, and HTML, I have a text area that gets filled with formatted text data for letters when certain buttons are clicked. <div class="form-group"> <label class="control-label" for="flyer descriptio ...

Inadvertent scroll actions causing unexpected value changes in Material UI sliders

I am currently working on a React application that utilizes Material UI, with slider components integrated throughout the interface. However, I have encountered an issue when using a touch screen device - unintentional changes to the slider values occur wh ...

Guide on inserting the elements <label>, <input>, and <span> into a <li> in a particular sequence

var btn = document.querySelector('.add'); var remove = document.querySelector('.draggable'); function dragStart(e) { this.style.opacity = '0.4'; dragSrcEl = this; ...

Why is a wrapper essential in jQuery?

Similar Question: What is the significance of (function($) {})(jQuery); in jQuery? Why does the function (function($){})() sometimes include the word jQuery? Seen this code snippet used in various places, and while I know it's essential for s ...

Implementing delayed loading of Angular modules without relying on the route prefix

In my application, I am using lazy loading to load a module called lazy. The module is lazily loaded like this: { path:'lazy', loadChildren: './lazy/lazy.module#LazyModule' } Within the lazy module, there are several routes def ...

Modify the color of the field that is currently chosen

Is there a way to modify the highlight color of the active record in an extjs combobox? In the image provided below, the record Petty Cash Fund is currently selected in my dropdown, but the highlighting is not very visible. How can I adjust this for all co ...

Is it considered fashionable to utilize HTML5 data attributes in conjunction with JavaScript?

Currently, I am utilizing HTML5 data attributes to save information such as the targeted DOM element and to initialize events using jQuery's delegation method. An example of this would be: <a href="#" data-target="#target" data-action="/update"> ...