What is causing the poor color and contrast of equirectangular backgrounds in Three.js, and what steps can be taken to improve them?

Using Three.js for a website project with a construction company, I created 360° photospheres using my Google Pixel 5. The client also requested a 3D representation of one of their projects, making Three.js the ideal solution.

Comparison:

Original photo in Google Photos

Three.js rendering

The colors in the Three.js version appear distorted (contrast, white balance, etc.) compared to the original image.

This is my initial Three.js code:

Scene Setup:

async connectedCallback() {
    // Scene
    this.scene = new THREE.Scene();

    // Background equirectangular texture
    const background_img = this.getAttribute('background');
    if (background_img) this.loadBackground(background_img);

    // Camera
    this.camera = new THREE.PerspectiveCamera(60, this.clientWidth / this.clientHeight, 1, 5000);

    // Lights
    // this.scene.add(new THREE.HemisphereLight(0xffeeb1, 0x080820, 0));

    const spotLight = new THREE.SpotLight(0xffa95c, 5);
    spotLight.position.set(20, 20, 20);
    spotLight.castShadow = true;
    spotLight.shadow.bias = -0.0001;
    spotLight.shadow.mapSize.width = 1024 * 4;
    spotLight.shadow.mapSize.height = 1024 * 4;
    this.scene.add(spotLight);

    // Renderer
    this.renderer = new THREE.WebGLRenderer({ antialias: true });
    this.renderer.toneMapping = THREE.ReinhardToneMapping;
    this.renderer.toneMappingExposure = 2.3;
    this.renderer.shadowMap.enabled = true;
    this.renderer.setPixelRatio(devicePixelRatio);
    this.renderer.setSize(this.clientWidth, this.clientHeight);
    this.appendChild(this.renderer.domElement);

    // Orbit controls
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    this.controls.autoRotate = true;

    // Resize event
    addEventListener('resize', e => this.resize());

    // Load model
    const url = this.getAttribute('model');
    if (url) this.loadModel(url);

    // Animate
    this.resize();
    this.animate();

    // Resize again in .1s
    setTimeout(() => this.resize(), 100);

    // Init observer
    new IntersectionObserver(entries => this.classList.toggle('visible', entries[0].isIntersecting), { threshold: 0.1 }).observe(this);
}

Setting Background (photosphere):

loadBackground(src) {
    const equirectangular = new THREE.TextureLoader().load(src);
    equirectangular.mapping = THREE.EquirectangularReflectionMapping;

    // Modifying filters suggested by Github Copilot does not affect colors significantly
    equirectangular.magFilter = THREE.LinearFilter;
    equirectangular.minFilter = THREE.LinearMipMapLinearFilter;
    equirectangular.format = THREE.RGBFormat;
    equirectangular.encoding = THREE.sRGBEncoding;
    equirectangular.anisotropy = 16;

    this.scene.background = equirectangular;
}

Answer №1

In a comment, Marquizzo pointed out:

When you adjust the renderer's tone mapping and exposure, it's expected that there will be differences in the color output.

I initially believed the issue wasn't with the lines suggested by Github Copilot, but after removing them one by one, I discovered that this particular line was causing the problem:

equirectangular.format = THREE.RGBFormat;

Although my result now appears darker compared to Google Photos', the colors are now accurate! Learning never stops, and I have much more to explore.

Check out the Three.js screenshot after eliminating the troublesome line

A big thank you to Marquizzo for the help!

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

Unable to retrieve the parent element of an event target in AngularJS when using Internet Explorer 11

function determineClosestAncestor(startElement, callback) { const parent = startElement.parentElement; if (!parent) return undefined; return callback(parent) ? parent : determineClosestAncestor(parent, callback); }; $document.on('click', e ...

Hiding content with a fixed Bootstrap menu

How can I prevent the fixed menu in my web page from hiding content, especially when the screen size is reduced and responsive menu hides even more content? Here's an example of the code: <nav class="navbar navbar-inverse navbar-fixed-top" styl ...

display the designated image as a priority

I am designing a loading screen for my website that includes the loading of multiple images, scripts, and other elements. While the HTML and CSS part is working well, I need to ensure that the "loading..." image is loaded before anything else on the page. ...

Different perspectives displayed simultaneously on a single page, achieved without the need for routes

On my page, users have the ability to sort items using various filters. When the filter is set to Newest, the items are simply listed by name. But when the filter is set to By collection, the items within a specific collection are displayed under that col ...

What is the best way to organize divs in a grid layout that adapts to different screen sizes, similar to the style

Is there a way to align multiple elements of varying heights against the top of a container, similar to what is seen on Wolfram's homepage? I noticed that they used a lot of JavaScript and absolute positioning in their code, but I'm wondering if ...

404 error occurs when attempting to load SVG files in Webpack 2

Recently, I delved into the world of webpack. However, I encountered a problem when trying to load an SVG file referenced in one of my CSS files. Despite trying various loaders such as this, that, and the other, I keep receiving a 404 error. Can anyone pro ...

Generating rows within Angular while implementing ng-repeat

In my code, I am facing an issue where posts from the API are being repeated and displayed in rows of 9. My objective is to create a grid layout with 3 rows, each containing 3 posts. Unfortunately, the solution I attempted did not work as expected. I also ...

Top technique for verifying the presence of duplicates within an array of objects

How can I efficiently check for duplicates in typescript within a large array of objects and return true or false based on the results? let testArray: { id: number, name: string }[] = [ { "id": 0, "name": "name1" }, ...

Revamp the sequence of divs using jQuery

<div class="example first">111</div> <div class="example second">222</div> <div class="example third">333</div> Can the order of these divs be changed using jQuery? I am looking to get: <div class="example second"&g ...

Learn how to dynamically insert an element into an angular scope using a click event

Currently, I am working on a function called onGroundUserClick within the Scope passedScope. The goal is to have a function triggered upon the completion of loading the iframe that will establish ng-click. var $tdName = $("<td/>", { ...

Once it hits the fourth tab, it must not cycle back to the first one

Hi there, I'm new to JavaScript I noticed that when I click the left and right arrows, the tabs circle back to the beginning However, I would like the circle to stop. When it reaches the fourth tab, it should not go back to the first. This should also ...

When utilizing the JavaScript createElement() method to create elements on keydown, it will not be compatible with jQuery's draggable() method

I'm currently developing a drag and drop feature for a project, allowing users to add items to a work area and then position them by dragging. I'm facing an issue where I want to create multiple instances of the same element using a key code, but ...

Leveraging jQuery chosen for interactive form elements

This Table Row contains 5 input fields, with the first being a select box. I am utilizing the chosen jQuery plugin to enable search functionality for the select items. Since this is a dynamic form, I am duplicating these rows. However, I am facing an issu ...

Move the accordion slider to the top of the browser

I'm working with an accordion menu that has some long content. To make it more user-friendly, I want to add a slide effect when the accordion items are opened. Right now, if you open the first two menu items, the last item's content is cut off a ...

ReactAppI am facing an issue where the browser fails to refresh the page upon saving changes in my JavaScript file using the VS code editor

Can anyone remind me of the tool we can install to refresh the browser page automatically whenever we save changes in our editor? ...

Issues arise when trying to manage HTML received as a response from a server in plain text

I have a scenario where I am dynamically generating an HTML table on the server side using Java and then sending it to the client as JSON data. The response looks something like this: <table class="table"></table><thead class="thead-dark"&g ...

My Vue.js accordion menu component is experiencing issues with toggle flags, causing it to malfunction

I have been working on my test case using Vue and I recently created a component called MultiAccordion. My intention was to open each slide based on the value of the status[index] flag. However, I am encountering an issue as this component does not seem ...

The message "jest command not recognized" appears

My test file looks like this: (I am using create-react-app) import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/Calculator'; import { getAction, getResult } from './actions/' ...

Steer clear of retrieving all the elements from the HTML DOM at once

Scenario I am working on a HTML5+CSS+JS slideshow project that needs to be synchronized across 50 clients in a local area network using a single wireless router. Challenge Due to the heavy content, particularly images, of the slides, I intend to dynamic ...

Should a checkbox be added prior to the hyperlink?

html tags <ul class="navmore"> <li><a href="link-1">Link 1</a></li> <li><a href="link-2">Link 2</a></li> </ul> Jquery Implementation in the footer $(".navmore li a").each(function(){ v ...