Determining Light Intensity and Pixel Values at Specific x/y/z Coordinates in ThreeJS

Is there a way to retrieve the light intensity and pixel values (rgba) of a specific point in a scene?

For example, if I have a scene where a moving light is illuminating a cube, how can I determine the brightness of certain points on the cube?

// Here is the Javascript code for our scenario.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

var renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true });
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshLambertMaterial( );
var cube = new THREE.Mesh( geometry, material );
cube.rotation.x += 0.4;
cube.rotation.y += 0.4;
scene.add( cube );

var plane_geo = new THREE.PlaneGeometry(2,2,2);
var plane = new THREE.Mesh( plane_geo, material );
plane.rotation.x = -1;
plane.position.y = -0.5;
scene.add( plane );

var light = new THREE.SpotLight( 0xff0000, 1, 100 );
//var light = new THREE.PointLight( 0xff0000, 1, 100 );
light.position.set( 3, 2, 2 );
scene.add( light );

var sphereSize = 0.1;
var pointLightHelper = new THREE.PointLightHelper( light, sphereSize );
scene.add( pointLightHelper );

var lightX = 0.5;
var lightY = 0.5;

camera.position.z = 5;



animate();


document.addEventListener("mousemove",mousemove_handler);


function animate() {
requestAnimationFrame( animate );


light.position.set(lightX,lightY,1);

renderer.render( scene, camera );

}

function mousemove_handler(event)
{

// Obtain Mouse Coords mapped to the 3D Vector
var vector = new THREE.Vector3();

vector.set(
    (event.clientX/window.innerWidth) * 2 - 1,
    - (event.clientY/window.innerHeight) * 2 + 1, 
    0.5);

vector.unproject(camera);

var dir = vector.sub(camera.position).normalize();

var distance = - camera.position.z / dir.z;

var pos = camera.position.clone().add(dir.multiplyScalar(distance));

lightX = pos.x;
lightY = pos.y;


}
body { margin: 0; }
canvas { width: 100%; height: 100% }
<!DOCTYPE html>
<html>

<head>
<meta charset=utf-8>
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>


<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
  </body>
 </html>

Answer №1

There are numerous factors to take into consideration in this scenario.

Let's start with the basics:

In real-life, light calculation relies on various elements such as interference, candela, wavelength, etc. It is not advisable to utilize webGL lights for scientific calculations, like determining solar performance.

Additionally:

In 3D, light uses shader passes, which means lighting is a pass over the scene. If your scene contains semi-transparent objects like windows, positioning the camera directly over the point of interest will render it clearly. Remember, we can only measure a point when it faces the camera, but complications arise if there is aggressive fog present.

To determine the light intensity on a specific pixel, follow these steps:

  • Identify the surface point you want information about.
  • Determine the screen position of that pixel.
  • Access the canvas context.
  • Retrieve the context pixel position.
  • Obtain the RGBA value of the pixel.
  • Convert the RGBA value to grayscale.

However, there is a caveat:

The process of converting to grayscale is not as straightforward as it may seem. Consider how Photoshop offers different methods for grayscale conversion, including average, luminosity, intensity, lightness,, and more.

Here is a fiddle that demonstrates this process upon clicking. The values are shown as floats ranging from 0-1, where 0 represents black.

Sample Fiddle:

https://jsfiddle.net/schnfteb/

//assuming webGL renderer
renderer.domElement.addEventListener("click",function(event){

    var mousePos = getMousePos(this, event);
    var y = mousePos.y;
    var x = mousePos.x;

    var offscreenCanvas = document.createElement("canvas");
    offscreenCanvas.width = this.width;
    offscreenCanvas.height = this.height;
    var ctx = offscreenCanvas.getContext("2d");

    ctx.drawImage(this,0,0);
    var imageData = ctx.getImageData(x,y, 1, 1);
    var c = imageData.data;
    c = [c[0], c[1], c[2]];
    var lightness = ((Math.max.apply(null, c) + Math.min.apply(null, c)) / 2)/255;
    var intensity = (65536 * c[0] + 256 * c[1] + c[2])/16777216;
    var average = ((c[0]+c[1]+c[2]) / 3)/255;
    var luminosity = ((0.21 * c[0]) + (0.72 * c[1]) + (0.07 * c[2]))/255;
    console.log(lightness, intensity, average, luminosity);

},false);

Taking it further:

If you need to convert a specific world point to a screen pixel rather than using mouse position, refer to this stackoverflow post:Converting 3D position to 2d screen position [r69!]

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 simulate a library in jest?

Currently, I am attempting to simulate the file-type library within a jest test scenario. Within my javascript document, this particular library is utilized in the subsequent manner: import * as fileType from 'file-type'; .... const uploadedFil ...

Filter and search functionality using React.js within a nested tree component

I am currently practicing beginner-level exercises on React.js and have developed a tree view component using material-ui. My next goal is to incorporate a search bar to enable users to search for specific keywords within the tree view structure. Below is ...

JavaScript Parallel Processing Simulation: A New Approach

I'm just starting to delve into JavaScript so please bear with me as I learn. Whenever there is a need for intensive calculations, it often involves recursive loops. These loops may encompass multiple functions that traverse the entire DOM tree, read ...

"Enhance your website with Ajax code that enables automatic refreshing of a PHP file, keeping its values up-to-date

Before diving in, I want to make it clear that my understanding of ajax is limited. I'm currently working on a small application where I have a load.php file that echoes 3 variables: $loadout[0]; $loadout[1]; $loadout[2]; The PHP file is functioning p ...

Creating multiple nested ng-repeats in an AngularJS table

Managing a large amount of data on users' availability by hour for multiple days can be challenging. The data is structured as follows: availData = { "date1":arrayOfUsers, "date2":arrayOfUsers, ... } arrayOfUsers= [ userArray, userArray, ... ] user ...

The specialized element encountered an issue with mapping

For a while now, I've been trying to create my own custom component but it's not working as expected. The interaction seems fine, but for some reason, it only renders the last item in the arrays. export default class MyComponent extends Comp ...

How can I retrieve the identical fingerprint used by AWS from x.509 using node-forge?

Is there a way to obtain the certificate ID / fingerprint of an x.509 certificate using the node-forge library? Update I am trying to configure AWS IoT and believe that AWS uses a specific fingerprint algorithm to generate the certificate ID. This inform ...

What could be causing this ajax request to return a 400 error?

I'm encountering a persistent 400 error and can't seem to figure out why. I've tried multiple approaches, but the error persists when using the request through admin-ajax.php. JQUERY: function handle_ajax_request(){ if(is_page(1404)){ ?> ...

What is the best way to print a canvas element once it has been modified?

My goal is to include a "Print Content" button on a webpage that will print a canvas element displaying workout metrics. However, the canvas content, which consists of a visual graph of workout data, changes based on the selected workout (bench, squat, etc ...

Utilizing Lodash to extract properties, dividing arrays, and obtaining distinct values

I found a more effective method to accomplish the task in my JavaScript project by utilizing the Lodash library. The approach involves extracting properties, splitting arrays, and obtaining unique values. var taskobj = [ {'taskno':'a&apos ...

Refresh the Google Maps location using GPS coordinates

Currently, I am working with an Arduino that has a GPS chip and processing NMEA strings with Python. I have an HTML file set to auto-refresh every x seconds to update the marker's position. However, I would like to update the position information with ...

What is the best way to generate a Google chart inside a newly added element using jQuery?

Currently, I am in the process of constructing a webpage that showcases a Google chart for all active sports games happening on that particular day. A data feed will provide information on the number of active games (as shown below, with 3 ongoing games). ...

As the background image shifts, it gradually grows in size

I'm attempting to create an interesting visual effect where a background image moves horizontally and loops seamlessly, creating the illusion of an infinite loop of images. Using only HTML and CSS, I've run into an issue where the background ima ...

The currency exchange script is malfunctioning and not functioning properly

Is there a solution for accessing the JSON value that is currently eluding me? If anyone has any suggestions, I would greatly appreciate it. function forex() { var to = document.getElementById("to").value; alert(to); var from = document.getE ...

The NodeJS nedb function seems to be ignoring the await keyword

The time it takes for the function checkExists to run is too lengthy. Despite attempting to implement await and async functions, using var exists = await checkExists(data.email); still results in undefined value due to not properly awaiting for checkExists ...

Fetching information from WebMethod with Jquery Ajax in c#

I have a jQuery variable that contains the following values: var data = [['Vikas', 75], ['Sumit', 55], ['Rakesh', 96], ['Shivam', 123], ['Kapil', 34], ['Rana', 104]]; Now, according to my requir ...

React Component Div Containing a Hydration Error

Can someone help me resolve the Hydration error related to a nested div issue? I am working on a component that has two main functions - fetching data and mapping it. However, I keep encountering a hydration error and I'm not sure why it's happe ...

What is the significance of static in react?

export class NavMenu extends Component { static displayName = NavMenu.name; constructor (props) { super(props); this.toggleNavbar = this.toggleNavbar.bind(this); this.state = { collapsed: true }; } I attempted to research the ...

What's the secret behind generating a crisp 400 on paper?

Understanding Why it Prints 400 I'm struggling to comprehend the logic behind this var x = {}, y = { key: "y" }, z = { key: "z" }; x[y] = 100; x[z] = 200; console.log(x[y] + x[z]); ...

Attempting to spread a non-iterable instance is invalid. For non-array objects to be iterable, they must have a [Symbol.iterator]() method

data(){ return { tables:[] } }, mounted(){ this.fetchData() }, methods:{ fetchData(){ var subscription = web3.eth.subscribe('logs', { address: '0x123456..', topics: ['0x12345. ...