Is your materials not getting updated when adding light at runtime?

Whenever I dynamically add a new spot at runtime, it seems like nothing is happening. The light only becomes visible on the objects when I change their material.

Even after adding MyMaterial.needsUpdate = true;, which is supposed to be the default setting, there is still no noticeable change.

To test this issue, I created a simple plane object using PlaneGeometry and MeshPhongMaterial. Upon pressing the "L" key, I add a SpotLight but still see no effect. However, by then pressing the "M" key to assign a new material to the plane, the spot light finally becomes visible.

Clearly, there is something missing from my implementation, but I can't seem to figure out what it is...

I am working with three.js r69.

WebGLRenderer Setup:

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 Object:

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;
    }
}

Answer №1

Take a look at this snippet of code from the three.js editor, which is part of the library package. This function is called when a new light is added during runtime:

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;

                }

            }

        }

    } );

}

This function essentially updates the needsUpdate flag for all materials present in the scene. By making this call, the respective materials should be ready for rendering in the next cycle. Give it a shot to witness the results.

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

What is the best way to immediately update the state in a React functional component?

Having recently started learning React, I find myself struggling to understand the lifecycle of a functional component. Let's consider a scenario where I have multiple checkboxes labeled as: checkbox, a, b, c, and d, each corresponding to values a, b, ...

Issues with jQuery Progress Bar Functionality

As a beginner in jQuery, I am currently working on creating an interactive progress bar using jQuery. My goal is to provide a set of checkboxes on a webpage so that when a visitor checks or unchecks a checkbox, the value displayed on the progress bar will ...

What is the best way to use AngularJS filters to arrange time?

Currently, I have a timer that is counting down from a user-set value. Users input a number representing minutes, which is then converted to milliseconds by multiplying it by 1000 * 60. The timer then decrements this number as it counts down. My goal is t ...

Is there a way to modify node attributes in the tick function of a d3 force-directed graph?

When working with a force directed graph, I am tasked with creating either circle or square nodes based on the group they belong to. The node creation process involves: const node = svg .append('g') .attr('stroke', &apo ...

Changing scope is ineffective unless $scope.$apply is used

When a button is clicked, I have a directive that displays a loading screen. angular.module('randomButton', ['Data']) .directive('randomButton', function(Data) { return { scope: '=', restrict: ...

Displaying only the Firebase entries that were created by the currently logged-in user in Angular JS

Currently, I have a table displaying all entries from an "events" node in firebase. However, I only want to display events created by the logged-in user. At the moment, it's showing events created by all users. I'm thinking of using an ng-if di ...

Await the sorting of intervals

Looking for a solution to re-execute a hand-made for loop with a delay of 10 seconds after it finishes indefinitely. I've attempted some code, but it keeps re-executing every 10 seconds rather than waiting for the loop to finish before starting again. ...

Tips for ensuring the Google Maps API script has loaded before executing a custom directive on the homepage of an Angular website

Issue - I am facing issues with Google Maps autocomplete drop-down not working on my website's main page even after parsing and loading the Google Maps API script. The problem seems to be a race condition on the main page of my website, specifically i ...

Exception thrown by ASP.Net Javascript code persists despite being commented out!

In my ASP website, I have incorporated Javascript code in the HEAD section to create a custom context menu. Here is the logic that I initially used: function fileGridGrouping_ContextMenu(s, e) { if(e.objectType != "row") return; fileGridGrou ...

Encountered a setback while trying to add information to a MySql database through Express

When I try to execute an insert query on a database, it throws the following error: code: 'ER_PARSE_ERROR', errno: 1064, sqlMessage: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versio ...

The JavaScript loop does not update the value of a number input field

In an effort to save and retrieve data from local storage, I have implemented a loop that iterates through various fields in a dynamic table row. The process involves saving the data to local storage, clearing the table rows, recreating them for data retr ...

Buffering ceases on the video

I am experiencing an issue with 4 videos and a preloader, which should hide once all the videos are fully buffered. <div id="preload"> <h1> Download... </h1> </div> <video preload="auto" class= ...

Error in defining class variable within the constructor not found

Just started delving into CoffeeScript and facing a challenge. In my code snippet below, I initialize WebSocketServer with a number as the first argument and a function as the second argument. However, when the websocket receives a message, @msgHandler sud ...

Error: When attempting to access the 'name' property of an undefined object, a TypeError is thrown. However, accessing another property on the same object does

Retrieving information from API. The fetched data looks like [{"_id":"someId","data":{"name":"someName", ...}}, ...] My state and fetching process are as follows: class Table extends React.Component { constructor() { super(); this.state = { ...

unable to bypass mongoose nested documents

I'm currently working with mongoose and node in an effort to paginate data from sub-documents. I've managed to limit the subdocuments, but skipping them seems to be a challenge. The specific versions I'm using are: Mongo 3.0.0 Node 0.10.3 ...

Implementing AngularJS to Display Images (IMG, PNG, or SVG) Within Dropdown Options

Looking to include an image in an Angular select option list. I've seen examples using data-image within the options, but can't seem to get it working. Any help would be appreciated. Check out the jsfiddle here: http://jsfiddle.net/drt6y0wf/ Is ...

Navigate a camera within a glTF model exported from Blender using Three.js

In my current project, I am collaborating with a game developer who has utilized Blender to implement all aspects of the boardgame. He has successfully integrated sprites within Blender and connected them to the camera in such a way that they always face t ...

JavaScript function innerHTML without any styling properties

I'm working with this initial code: <div class="form-row"> <div id="ingredientadd" class="col"gt; <label for="ingredient">Ingredient</label> <input type="text" class=&q ...

Issue with invoking Bracket-Shell bespoke Native (C++) Method

I'm currently working on developing a unique C++ function that can be invoked from JavaScript to resize the window. The necessary components are located in various files: Within appshell_extensions_platform.h: #if defined(OS_WIN) void ResizeWindow( ...

Scroll through Two DIVs, where one is displayed and the other is concealed

Check out my JSFiddle here: https://jsfiddle.net/rq2tvccg/14/ I'm working on a project with 2 DIVs that each contain elements. Only one of the DIVs is displayed at a time, toggled by a button. I need to add an element that appears in both lists simul ...