The MeshBasicMaterial in THREE.js successfully renders, while the MeshLambertMaterial does not produce the desired outcome

In my current project, I've been working on creating a randomized sheet composed of arrays containing x, y, and z coordinates to draw triangles between points. You can see the outcome by clicking on this screenshot.

Initially, I utilized MeshBasicMaterial for this purpose. However, I desired to switch to MeshLambertMaterial to make use of lighting effects. Surprisingly, when implementing this change, the resulting sheet appeared quite different from what I expected as shown in this image.

Here is the functioning Basic Mesh code responsible for the green tiles:

for(j = 0; j < h-1; j++) {      
    for(i = 0; i < w-1; i++) {  
        o = ((j%2==1)?1:0);
        var geom = new THREE.Geometry();
        var a = new THREE.Vector3(x[i][j], y[i][j], z[i][j]);
        var b = new THREE.Vector3(x[i+1][j], y[i+1][j], z[i+1][j]);
        var c = new THREE.Vector3(x[i+o][j+1], y[i+o][j+1] ,z[i+o][j+1]);
        geom.vertices.push(a);
        geom.vertices.push(b);
        geom.vertices.push(c);
        geom.faces.push(new THREE.Face3(0,1,2));
        tile1[i][j] = new THREE.Mesh(
            geom,
            new THREE.MeshBasicMaterial({color: 'green'})
        );
        scene.add(tile1[i][j]);
    }
}

And here is the failing Lambert Mesh code associated with red tiles (simply changing 'Basic' to 'Lambert'):

for(j = 0; j < h-1; j++) { 
    for(i = 0; i < w-1; i++) {
        o = ((j%2==1)?0:1);     
        var geom = new THREE.Geometry();
        var a = new THREE.Vector3(x[i+o][j], y[i+o][j], z[i+o][j]);
        var b = new THREE.Vector3(x[i+1][j+1], y[i+1][j+1], z[i+1][j+1]);
        var c = new THREE.Vector3(x[i][j+1], y[i][j+1], z[i][j+1]);
        geom.vertices.push(a);
        geom.vertices.push(b);
        geom.vertices.push(c);
        geom.faces.push(new THREE.Face3(0,1,2));
        tile2[i][j] = new THREE.Mesh(
            geom,
            new THREE.MeshLambertMaterial({color: 'red'})
        );
        scene.add(tile2[i][j]);
    }
}

A cube created using the above Lambert Mesh settings reacts properly to light sources.

scene.add(new THREE.Mesh(new THREE.BoxGeometry(10,1000,5),new THREE.MeshLambertMaterial({color:'red'})));

The question arises - why does the Lambert Mesh not produce the desired effect on a geometry where the Basic Mesh functioned correctly?

EDIT: Placing a colored box beneath the sheet revealed that the tiles above it were not failing to render but appearing black instead. They seem opaque and do not reflect color or light as intended compared to the box.

Answer №1

Having proper lighting in your scene is crucial for utilizing THREE.LambertMaterial. Have you ensured that your scene lighting is set up correctly?

UPDATE:

I have identified the issue with your code. It is essential to include normals to your faces so that the WebGL renderer can effectively render the light interactions on the surfaces with THREE.LambertMaterial. Adjust your code as follows:

face = new THREE.Face3( 0, 1, 2 );
face.normal = new THREE.Vector3().crossVectors(
    new THREE.Vector3().subVectors( b, a ),
    new THREE.Vector3().subVectors( c, b )
).normalize();
geom.faces.push( face );

With this modification, your faces should now render correctly.

Alternatively, you can utilize geometry methods to automatically calculate normals instead of manually defining them:

geometry.computeFaceNormals();
geometry.computeVertexNormals();

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

Regarding passing input into a JavaScript class method that is exported through the exports keyword

The inquiry at hand relates to ExtendScript code, however, I believe it should be independent of any specific javascript implementation. If we have the following in a JS library file (base64.js) exports.encode64 = encoder('+/'); //... function ...

Executing a function right away when it run is a trait of a React functional component

Having a fully functional React component with useState hooks, and an array containing five text input fields whose values are stored in the state within an array can be quite challenging. The main issue I am facing is that I need to update the inputfields ...

How can I access properties of generic types in TypeScript?

Converting the generic type to any is a valid approach (The type E could be a typescript type, class, or interface) of various entities like Product, Post, Todo, Customer, etc.: function test<E>(o:E):string { return (o as any)['property' ...

Discover the technique for splitting a string using jQuery with multiple strings as separators

I am looking to split a string in jQuery or JavaScript using multiple separators. When we have one string as a separator, our code looks like this: var x = "Name: John Doe\nAge: 30\nBirth Date: 12/12/1981"; var pieces = x.split("\n"), p ...

I'm curious if there is a specific jQuery event that triggers right before an element loses focus or right before the next element gains focus

I am facing a situation where I have two input elements in a form that are closely connected. The first element triggers an ajax call to check for existing data in the database when the user tries to move away from it, while the second element opens a moda ...

The layout option is not specified within the ejs-mate package

error boilerplate I am baffled as to why the layout is not being defined. I have installed ejs-mate and ejs, yet it still gives this error. <% layout('layouts/boilerplate') %> <h1>All campgrounds </h1> <div> <a ...

Having issues with the functionality of the jQuery HTML function

I'm working on this jQuery code snippet: $('#wrapper').html('<img src="/loading.gif">'); var formdata = $("#validateuserform").serialize(); $.post("/userformdata.php",formdata,function(html){ if(html) ...

Discover how to obtain an access token using Yelp API V3 with JavaScript

Currently in the process of learning how to utilize this system, however there appears to be an issue with my code. $.ajax({ dataType: "POST", url: "https://api.yelp.com/oauth2/token", grant_type: "client_credentials", client_i ...

The placement of the FirebaseAuth.onAuthStateChanged call in an Angular application is a common concern for developers

Where is the best place to add a global listener initialization call in an Angular app? Take a look at this code snippet: export class AuthService { constructor( private store: Store<fromAuth.State>, private afAuth: AngularFireAuth ) { ...

Fetching an item from Local Storage in Angular 8

In my local storage, I have some data stored in a unique format. When I try to retrieve the data using localStorage.getItem('id');, it returns undefined. The issue lies in the way the data is stored within localStorage - it's structured as a ...

Create a custom countdown using Jquery and Javascript that integrates with MySQL and PHP to display the datetime in the format Y-m-d

Hey there, I'm looking to create a countdown script using dates in the format (Y-m-d H:m:s). The goal is to retrieve the current_datetime and expire_datetime in this format and incorporate them into some JavaScript or jQuery plugin to display a countd ...

How can I defer Tween.js animation in three.js until a button is specifically clicked?

I am trying to implement a tween animation for my camera in three.js that should only start when a specific object is clicked. This object can be within the scene or it could be a simple HTML button. The code snippet below demonstrates how the camera anima ...

Issue encountered when executing the migration fresh seed: SyntaxError, which indicates the absence of a closing parenthesis after the

Having trouble with a nextJS project that utilizes mikro-orm? Struggling to overcome this persistent error for days: C:\Users\BossTrails\Documents\core.nest-main_2\node_modules\.bin\mikro-orm:2 basedir=$(dirname "$(e ...

AngularJS: accessing remote systems - a guide

I am looking to explain my objective clearly I need guidance on how to establish a remote desktop connection from my Angular.js application to a windows application running system. The server I am using is Google App Engine. My current ideas: The Windo ...

Angular 2 orderByPipe not displaying any results initially

At first, I thought the reason for not displaying anything initially was due to it not being async and returning an empty array. Everything worked fine without the pipe, but the posts weren't shown on startup. After submitting a post, all the posts ap ...

Shift every ng-repeat child element and display the updated outcome

I am looking to create an animation that will shift all items displayed using the ng-repeat directive to the left, hide the first item, and show a new element in place of the last one. The elements are being displayed using the ng-repeat directive from a ...

Exploring the isolated scopes of AngularJS directives

Exploring directives in AngularJS led me to this interesting code snippet: var app = angular.module('app', []); //custom directive creation app.directive("myDir", function () { return { restrict: "E", scope: { title: '@ ...

Tips for updating the state of an individual component in ReactJS without having to re-render the entire component

As a beginner in ReactJS, I am seeking guidance on how to modify the state of a specific component that was created within a Map function. Imagine I have a basic component named panels, with multiple panel-items. Each panel-item is essentially one componen ...

show a notification once the maximum number of checkboxes has been selected

I came across this code snippet from a previous question and I'm interested in making some modifications to it so that a message can be displayed after the limit is reached. Would adding a slideToggle to the .checkboxmsg within the function be the mos ...

Convert a relative path to an absolute path using the file:// protocol

When I scrape a website with similar html content, I come across the following code: <a href="/pages/1></a> In addition to this, I have access to the window.location object which contains: origin:"http://www.example.org" This allows me to ...