Search code examples
javascriptthree.jstextureslightinggltf

Three js, MeshStandardMaterial looks yellow


Hi i am loading a GLTF model in my scene. But the model looks too yellow i assume this has to do with the material. But i have no clue what is causing it, it is not the model itself since if i check it on donmccurdy's gltf viewer it looks perfect.

See a reference below:
GLTF Viewer:
enter image description here

And this is how the same model looks in my scene:
enter image description here

I have added an environment map to the scene this fixed may things but not the yellowness.. See current code below:

let scene, camera, renderer, controls;
let dummy = new THREE.Object3D();
let mat4 = new THREE.Matrix4();

const loader = new THREE.GLTFLoader();
let clock = new THREE.Clock();


function loadModel(url, callback) {
    loader.load(
        url,
        function ( gltf ) {
            const model = gltf.scene.children[0];
            callback(model);
        },
        function ( xhr ) {
            console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
        },
        function ( error ) {
            console.log( 'An error happened', error );
        }
    );
}

function generateInstances(model, count) {
    const geometry = model.geometry;
    geometry.scale(0.1, 0.1, 0.1);
    const material = model.material;
    return new THREE.InstancedMesh(geometry, material, count);
}

function setInstancePositions(instances, startPos, counts, spacing) {
    if(instances.count < counts.x * counts.y * counts.z) throw Error("counts exceeds max instanciated meshes");

    let index = 0;
    for (let x = 0; x < counts.x; x++) {
        for (let y = 0; y < counts.y; y++) {
            for (let z = 0; z < counts.z; z++) {
                dummy.position.addVectors(startPos, new THREE.Vector3(x * spacing.x, y * spacing.y, z * spacing.z));
                dummy.updateMatrix();
                instances.setMatrixAt(index, dummy.matrix);
                index++;
            }
        }
    }

    return instances;
}

function init() {
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
    camera.position.set(50, 75, 100);
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(innerWidth, innerHeight);
    renderer.setClearColor(0xFFFFFF);
    renderer.physicallyCorrectLights = true;
    document.body.appendChild(renderer.domElement);

    new THREE.RGBELoader()
        .load('assets/enviroment.hdr', function ( texture ) {
            texture.mapping = THREE.EquirectangularReflectionMapping;
            scene.environment = texture;
        });


    let controls = new THREE.OrbitControls(camera, renderer.domElement);

    const light1  = new THREE.AmbientLight(0xffffff, 0.3);
    light1.name = 'ambient_light';
    scene.add( light1 );

    loadModel('assets/100-dollars.glb', (model) => {
        let instances = generateInstances(model, 1500);
        instances = setInstancePositions(instances, new THREE.Vector3(), new THREE.Vector3(5, 30, 10), new THREE.Vector3(27, 3, 13));
        scene.add(instances);
    });


    renderer.setAnimationLoop(() => {

        camera.lookAt(scene.position);
        renderer.render(scene, camera);
    });
}

init();

here is the hdr file: url
and here is the model: url


Solution

  • Using GLTFLoader requires a sRGB workflow which is not configured in your app. Add the following line and see if it fixes the color issue:

    renderer.outputEncoding = THREE.sRGBEncoding;
    

    Besides, consider to turn on antialiasing and the usage of setPixelRatio() for better quality:

    renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setPixelRatio(window.devicePixelRatio);