[SOLVED] Glb model is very dark

SOLVED :grinning:
Hey, when I load a glb model into threejs it is very dark. The problem model is good_bush.glb. It’s near the bottom of the code. It looks fine when I upload it to https://gltf-viewer.donmccurdy.com/ but it behaves weird with me. I don’t know if this is a lighting issue or a renderer settings issue. Any help is appreciated.

bush notes bush

import * as THREE from 'three';
import * as OrbitControls from './utils/three-orbit-controls';
import GLTFLoader from 'three-gltf-loader';
import * as Stats from 'stats.js';

var stats = new Stats();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.001, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
const loader = new GLTFLoader();
const controls = new OrbitControls(camera, renderer.domElement);
const modelScale = [1, 1, 1];
const medievalScale = [0.5, 0.5, 0.5];
const lightPosition = [75, 300, -75]
const ambientLight = new THREE.AmbientLight(0xaaaaaa);
const pointLight = new THREE.DirectionalLight(0xffffff, 0.5);
const sun = new THREE.Group();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio( window.devicePixelRatio );
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;
renderer.physicallyCorrectLights = true;

document.body.appendChild(renderer.domElement);
camera.position.set(0, 0, 3);
scene.background = new THREE.Color( 0x11f8bb );

sun.add(pointLight);
sun.position.set(75, 300, -75);
scene.add(sun);
scene.add(ambientLight);

//lerp and rate    > rate --> Faster the animation
controls.enableDamping = true;
controls.dampingFactor = 0.2;
controls.rotateSpeed = 0.3;

//show stats
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom );

loadModels();

window.addEventListener('resize', () => {
    let width = window.innerWidth;
    let height = window.innerHeight;
    renderer.setSize(width, height);
    camera.aspect = width / height;
    //update camera frustum
    camera.updateProjectionMatrix();
});

//Render --> This is works for vr
//and requestAnimationFrame doesn't
//so we'll future proof rn instead of later
renderer.setAnimationLoop( () => {
    stats.begin();
    controls.update();
    controls.runKeyBinds();
    renderer.render(scene, camera);
    stats.end();
});

function stop() {
    renderer.setAnimationLoop( null );
}

function loadModels() {
    //make a sphere around the light so we can see it
    const lightBox = new THREE.Mesh(
        new THREE.SphereBufferGeometry( 5, 32, 32 ),
        new THREE.MeshBasicMaterial({
            color: 0xffffff
        })
    );
    lightBox.position.set(3, 100, 1);
    scene.add(lightBox);

    //create ground
    let ground = new THREE.Mesh(
        new THREE.BoxBufferGeometry(200, 0, 200 ),
        new THREE.MeshStandardMaterial({
            color: 0x1d7500,
            roughness: 0.8
    }));
    ground.position.set(0, -1.75, 0);
    scene.add(ground);

    //add trees
    loader.load( "/models/tree_snub_trunk.gltf", 
        // called when the resource is loaded
        function ( gltf ) {
            const model = gltf.scene.children[0];
            model.scale.set(...modelScale);
            model.position.set(0, -1.25, 0);

            let material = model.material;
            material.flatShading = true;
            let geometry = model.geometry;
            
            for(let i = 1; i < 100; ++i) {
                const xRand = Math.random() * 200 - 100;
                const yRand = Math.random() * 200 - 100;
                const object = new THREE.Mesh(geometry, material);
                object.position.set(xRand, -1.25, yRand);
                scene.add(object);
            }
        }
    );

    loader.load( "/models/christmas_tree.gltf", 
        // called when the resource is loaded
        function ( gltf ) {
            const model = gltf.scene.children[0];
            model.scale.set(...modelScale);
            model.position.set(0, -1.25, 0);
            
            let material = model.material;
            material.flatShading = true;
            let geometry = model.geometry;
            
            for(let i = 1; i < 100; ++i) {
                const xRand = Math.random() * 200 - 100;
                const yRand = Math.random() * 200 - 100;
                const object = new THREE.Mesh(geometry, material);
                object.position.set(xRand, -1.25, yRand);
                scene.add(object);
            }
        }
    );

    loader.load( "/models/shrub2.gltf", 
        // called when the resource is loaded
        function ( gltf ) {
            const model = gltf.scene.children[0];
            model.scale.set(...modelScale);
            model.position.set(0, -1.25, 0);
            
            let material = model.material;
            material.flatShading = true;
            let geometry = model.geometry;
            
            for(let i = 1; i < 100; ++i) {
                const xRand = Math.random() * 200 - 100;
                const yRand = Math.random() * 200 - 100;
                const object = new THREE.Mesh(geometry, material);
                object.position.set(xRand, -1.25, yRand);
                scene.add(object);
            }
        }
    );

    loader.load( "/models/good_bush.glb", 
        //TODO fix this
        function ( gltf ) {
            gltf.scene.position.set(0, -1.5, 0);
            scene.add(gltf.scene);
            console.log('added bush');

        }
    );

    // //bushes
    // for(let i = 1; i < 150; ++i) {
    //     loader.load( "/models/bush_berries.gltf", 
    //         // called when the resource is loaded
    //         function ( gltf ) {
    //             let xRand = Math.random() * 200 - 100;
    //             let zRand = Math.random() * 200 - 100;
    //             gltf.scene.rotateY(Math.random() * 6.28);
    //             gltf.scene.scale.set(1.2, 1.2, 1.2);
    //             gltf.scene.position.set(xRand, -1.25, zRand);
    //             scene.add( gltf.scene );
    //         }
    //     );
    // }
}

Remove your previous light setup and try it with this:

var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 300, 0 );
scene.add( hemiLight );

var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( 75, 300, -75 );
scene.add( dirLight );

You should only set WebGLRenderer.physicallyCorrectLights to true if you also apply correct units to the lights. For now, don’t set it and see if the above code improves your lighting.

1 Like

Hey I really appreciate the response, but no luck. Still looks the same. I looked at some of the gltf viewer source code and tried to copy some of it (that’s why I added physicallyCorrectLights) but yeah it didn’t change anything.

Here’s the output after the changes

04

Can you please share a live demo or small repo (as a zip file), that demonstrates the issue?

Yeah, I edited my previous comment and added the link to my firebase app

1 Like

Make sure that the model material isn’t metallic – it should have material.metalness=0. If it is metallic, it will likely need an environment map to look correct.

5 Likes

I LOVE YOU
This problem has messed with me for days.
Thank you so much.
I had to console.log the structure of the models because of the multiple meshes.
Anyways this is the winning code

loader.load( "/models/good_bush.glb", 
    function ( gltf ) {
        gltf.scene.position.set(0, -1.5, -2);
        const model = gltf.scene.children[6];
        model.children[0].material.metalness = 0;
        model.children[1].material.metalness = 0;
        scene.add(model);
    }
);
2 Likes