What are some techniques to maintain consistent color blending while orbiting a three-dimensional object in Three.js?

Is there a way to maintain consistent colors on a rectangle while rotating around it? The colors currently change based on the normals when using the orbitcontrols library addon.

Check out the jsfiddle and code below:

/* import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r110/build/three.module.js'; */
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r110/examples/jsm/controls/OrbitControls.js';

let camera, scene, renderer, controls;

init();
render();

function init() {
    let width = $('#container').width();
    let height = $('#container').height();
  renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width,height);
  $("#container").html(renderer.domElement);
  
  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
  camera.position.z = 4;

  scene = new THREE.Scene();
  
  const geometry = new THREE.BufferGeometry();
  const vertices = [
    -2, -1, 0,
    2, -1, 0,
    2, 1, 0,
    -2, 1, 0
  ];

  const indices = [
    0, 1, 2, // first triangle
    2, 3, 0 // second triangle
  ];
  
  const normals = [
  1,0,0, // bottom left
  0,0,1, // bottom right
  0,0,1, // top right
  1,0,0  // top left
  ];
  
  geometry.setIndex(indices);
  geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
  geometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3));

  const material = new THREE.MeshNormalMaterial({vertexColors:true,flatShading:false});

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

  controls = new OrbitControls( camera, renderer.domElement );
  controls.target.set(0, 0, 0);
  controls.update();
  
  animate();

}

function animate() {
    requestAnimationFrame( animate );
    controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
    render();
}

function render() {

  renderer.render(scene, camera);

}

https://jsfiddle.net/ZQVerse/2an9edhL/

While attempting to display multiple colors on the rectangle faces by setting the normals attribute, the colors change depending on the camera's orbit. How can I keep the colors consistent regardless of rotation?

I've searched online for solutions to this issue but have found no helpful examples. I suspect the normals are being altered during camera movement, and that I might need to update the normals to maintain correct colors based on rotation, but I'm unsure how to solve this.

Answer №1

The appearance of a material typically changes based on the angle between the surface normal and the camera. This behavior is default as normals are primarily used for lighting purposes. It is crucial to determine if the surface is reflecting light towards the camera, which involves ensuring that the surface normal directly faces the camera (although this explanation may be oversimplified).

For those interested, there is a repository containing a new normal material that utilizes world space instead of view space (combining Normal Position and Camera Position): https://github.com/maximeq/three-js-mesh-world-normal-material

Additionally, an updated jsfiddle with a custom shader that does not take the view into account can be found here: https://jsfiddle.net/szamkh5w/1/

const material = new THREE.ShaderMaterial( { vertexShader: [

"varying vec3 vPositionW;",
"varying vec3 vNormalW;",

"void main() {",
"   vNormalW = normalize( vec3( vec4( normal, 0.0 ) * modelMatrix ) );",
"   gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}" ].join( "\n" ),
fragmentShader: [
"varying vec3 vNormalW;",

"void main() {",
"   gl_FragColor = vec4( vNormalW, 1.);",

"}"
].join( "\n" )
} );

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

Eliminating attributes in mapStateToProps

When wrapping material TextField with a redux component, it is important to consider that some properties should be used in mapStateToProps only and not passed directly to the component. Otherwise, an Unknown prop warning may occur. Even specifying an unde ...

Include a clickable hyperlink within a column in JQGrid that, when clicked, triggers a specific Jquery function

I am dealing with a JQgrid that only has 5 columns. Below is the code I have attempted: jQuery("#grdAnn6InvstDetails").jqGrid({ url: RootUrl + 'FDIAS/Ann6InvDtlsGridData', datatype: 'json', mtype: 'POST&ap ...

Displaying Mustache.js in an HTML template

I attempted to integrate mustache.js into my web application. After loading the mustache.js file, I included the following script in my code: <script type="text/javascript> $(document).ready(function () { var person = { first ...

Transferring JSON data using $.post in Express/NodeJS

Below is the contents of my app.js file: var express = require('express'); var app = express(); var path = require('path'); var $ = require('jquery'); var nodemailer = require('nodemailer'); app.use('/static&a ...

Searching for the intersection with Object3d in Three.js

I have a Revit json model that was exported using the RvtVa3c tool. I successfully added the model to the scene using ObjectLoader. var loader = new THREE.ObjectLoader(manager); loader.load( 'mesa.js', function ( object ) { scene.add(object); ...

What is the process for retrieving the result of a promise at a later time?

var screencastId = 'abc' var a = youtube.get(screencastId); a.then(function(screencast) { // Great, the screencast information is now available. console.log(screencast); }); // How can I access the `screencast` variable below? connection.be ...

Tips on retrieving the status code from a jQuery AJAX request

I am trying to figure out how to retrieve the ajax status code in jQuery. Here is the ajax block I am currently working with: $.ajax{ type: "GET", url: "keyword_mapping.html", data:"ajax=yes&sf="+status_flag, success: callback.success ...

Count the unique entries for each item in Mongodb

I am seeking a way to display the following information Data /* 1 */ { "name" : "Dash" } /* 2 */ { "name" : "Dash" } /* 3 */ { "name" : "Pink" } /* 4 */ { "name" : "Pink" } /* 1 */ { "name" : "Jamie" } Currently, using db.getCollecti ...

Are there any conventional methods for modifying a map within an Aerospike list?

Attempting to modify an object in a list using this approach failed const { bins: data } = await client.get(key); // { array: [{ variable: 1 }, { variable: 2 }] } const { array } = await client.operate(key, [Aerospike.maps.put('array', 3).withCon ...

I am curious about the distinction between two closures

Can someone please explain the distinction between these two closure examples? (function(window, undefined) { // JavaScript code })(window); Here's another example: (function(window) { // JavaScript code })(window, undefined); ...

When trying to integrate Angular.ts with Electron, an error message occurs: "SyntaxError: Cannot use import statement

Upon installing Electron on a new Angular app, I encountered an error when running electron. The app is written in TypeScript. The error message displayed was: import { enableProdMode } from '@angular/core'; ^^^^^^ SyntaxError: Cannot use impor ...

Guide on configuring remix using aws cdk

Currently, I am delving into the world of remix and attempting to configure a remix project that utilizes AWS CDK for the server. I stumbled upon this GitHub example: https://github.com/ajhaining/remix-cloudfront-cdk-example However, it lacks clarity on ...

Tips for correcting geometrical issues in Three.js

I'm currently working on translating geometry canvas2d commands from a separate library to three.js webgl output. I have taken one example and created a canvas2d output in one fiddle, as well as the corresponding three.js fiddle. The three.js output i ...

Is there a way to eliminate the 'All Files' option from an HTML file input field?

I have implemented a feature to allow users to upload custom files using . Currently, I am restricting the allowed file types to only ".Txt, .SVG, .BMP, .JPEG" by using accept=".Txt,.SVG,.BMP,.JPEG". This setting causes the browser's file-select dial ...

How can we programmatically trigger a click action on an element obtained through an HTTP request with the help of Set

window.addEventListener("load" , () => { setInterval(() => { let xhttp = new XMLHttpRequest(); xhttp.open("GET", "./messagedUsers.php", true); xhttp.onload = () => { if(xhttp.re ...

The error message "gaq is not defined in opencart 2.0" indicates

While attempting to monitor transactions in OpenCart, I encountered the following error message: Uncaught ReferenceError: _gaq is not defined(anonymous function) This is the method I am using for tracking in my catalog/view/theme/default/template/commo ...

Transfer the "file" from the busboy to the GM for FTP uploading

I'm looking to resize an uploaded image using nodejs and send it via ftp. I'll be utilizing nodejs, busboy, GraphicsMagick, and jsftp. var uploadFile = function(dir, req, cb) { req.busboy.on('file', function(fieldname, file, filename, ...

Transitioning from the login screen to the main page in Ionic with the help of Angular

My code is running smoothly, but I encountered an issue when clicking the login button. It changes the state as depicted in the image, altering the URL but failing to open the subsequent page. Can anyone provide guidance on how to redirect to the next page ...

Position the label and the select dropdown side by side within the sweetalert 2 component

Can anyone provide an example of aligning a label and dropdown in the same row using sweetalert2? I attempted to customize the label placement, but it appears on a separate line. I would like to log the selected dropdown item upon clicking the OK button. ...

How can you display or conceal an HTML page in Jquery Mobile?

This code snippet is used for toggling the visibility of a div. $("[id*=viewMeButton]").click(function(){ $("[id*=viewMe]").toggle(); $("[id*=viewMeButton]").show(); }); In Jquery Mobile, similar functionality can be implemented to show/hide a ...