ThreeJs object stays dark even after applying lights

Hello friends, I have created a .glb file using point cloud data and now I am using it to render a model on my website. No matter what I do, and how many lights I add the scene and object remains dark, it is barely visible. I am attaching my code in case anyone wants to have a look. Anything would be helpful!

import * as THREE from 'three';
import { OrbitControls } from 'three-stdlib';
import React, { useRef, useEffect } from 'react';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

import { Box } from '@mui/material';

interface GLTFViewerProps {
  modelPath: string; // Path to the GLTF/GLB file
  texturePath: string; // Path to the orthophoto texture (e.g., .jpg or .png)
}

const GLTFViewer: React.FC<GLTFViewerProps> = ({ modelPath, texturePath }) => {
  const containerRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    // Initialize Three.js scene
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.toneMapping = THREE.NoToneMapping; // Disable tone mapping for full brightness
    renderer.toneMappingExposure = 2; // Increase exposure for vivid brightness

    // Append the renderer canvas to the DOM
    if (containerRef.current && !containerRef.current.contains(renderer.domElement)) {
      containerRef.current.appendChild(renderer.domElement);
    }

    // OrbitControls for camera movement
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.25;
    controls.screenSpacePanning = false;

    const ambientLight = new THREE.AmbientLight(0xffffff, 20); // Brighter ambient light
    scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 30); // Stronger directional light
    directionalLight.position.set(10, 20, 15);
    directionalLight.castShadow = true; // Enable shadows if needed
    scene.add(directionalLight);

    // Add a spotlight to highlight the model
    const spotLight = new THREE.SpotLight(0xffffff, 50); // Spotlight with high intensity
    spotLight.position.set(15, 30, 10);
    spotLight.target.position.set(0, 0, 0); // Point it at the model's center
    scene.add(spotLight);
    scene.add(spotLight.target);

    // Multiple point lights for illumination from all sides
    const pointLightPositions = [
      [10, 10, 10], // Front-top-right
      [-10, 10, 10], // Front-top-left
      [10, -10, 10], // Front-bottom-right
      [-10, -10, 10], // Front-bottom-left
      [0, 10, -10], // Back-top
      [0, -10, -10], // Back-bottom
    ];

    pointLightPositions.forEach(([x, y, z]) => {
      const pointLight = new THREE.PointLight(0xffffff, 2, 10); // Adjust intensity
      pointLight.position.set(x, y, z);
      scene.add(pointLight);
    });

    const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 10); // Extra bright hemisphere light
    scene.add(hemisphereLight);

    // Load texture asynchronously
    const textureLoader = new THREE.TextureLoader();
    textureLoader.load(
      texturePath,
      (texture) => {
        console.log('Texture loaded successfully');

        // Load GLTF model once texture is ready
        const loader = new GLTFLoader();
        fetch(modelPath)
          .then((response) => {
            if (!response.ok) throw new Error(`Failed to load model: ${response.statusText}`);
            return response.arrayBuffer();
          })
          .then((data) => {
            loader.parse(data, '', (gltf) => {
              if (gltf.scene) {
                gltf.scene.traverse((child) => {
                  if (child instanceof THREE.Mesh) {
                    if (child.material instanceof THREE.MeshStandardMaterial) {
                      child.material.metalness = 0.1; // Slightly metallic
                      child.material.roughness = 0.8; // More diffuse reflection
                      child.material.map = texture; // Apply texture
                      child.material.emissive = new THREE.Color(0x222222); // Add emissive property
                      child.material.emissiveIntensity = 0.5; // Control emissive intensity
                      child.material.needsUpdate = true;
                    }
                  }
                });

                gltf.scene.scale.set(0.1, 0.1, 0.1);
                const box = new THREE.Box3().setFromObject(gltf.scene);
                const center = box.getCenter(new THREE.Vector3());
                gltf.scene.position.sub(center);

                scene.add(gltf.scene);
              }
            });
          })
          .catch((error) => console.error('Error loading GLTF model:', error));
      },
      undefined,
      (error) => {
        console.error('Error loading texture:', error);
      }
    );

    // Camera position
    camera.position.set(0, 0, 10);
    (renderer as any).outputEncoding = 3001;
    renderer.toneMapping = THREE.ReinhardToneMapping; // Use Reinhard or another tone mapping
    renderer.toneMappingExposure = 1.5; // Adjust exposure

    // Render loop
    const animate = () => {
      requestAnimationFrame(animate);
      controls.update();
      renderer.render(scene, camera);
    };
    animate();

    // Handle resizing
    const onWindowResize = () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    };
    window.addEventListener('resize', onWindowResize);

    // Cleanup
    return () => {
      window.removeEventListener('resize', onWindowResize);
      renderer.dispose();
      controls.dispose();
    };
  }, [modelPath, texturePath]);

  return (
    <Box
      sx={{
        width: '100%',
        height: '100%',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
      }}
    >
      <div ref={containerRef} style={{ width: '100%', height: '100%' }} />
    </Box>
  );
};

export default GLTFViewer;

Sometimes model have not got normals and then dark. Bring model file here

Hello, thank you for your reply. My .glb file is quite big and it’s not letting me upload it here. How can I share it with you?

Cut model to decrease size or try:
Change this code

if (child instanceof THREE.Mesh) {
                    if (child.material instanceof THREE.MeshStandardMaterial) {
                      child.material.metalness = 0.1; // Slightly metallic
                      child.material.roughness = 0.8; // More diffuse reflection
                      child.material.map = texture; // Apply texture
                      child.material.emissive = new THREE.Color(0x222222); // Add emissive property
                      child.material.emissiveIntensity = 0.5; // Control emissive intensity
                      child.material.needsUpdate = true;
                    }
                  }

To this and look at browser console

if (child instanceof THREE.Mesh) {
 if (child.material instanceof THREE.MeshStandardMaterial) {
console.log(child.geometry.attributes.normal.array);
                    }
                  }

Oh thanks! I will try this. Also here is the file link:

Just tried the code you told me to replace. It didnt print anything on console which means the following condition is not true:

                  if (child instanceof THREE.Mesh) 

I wonder what could be the reason.

For points need to use points material. StandardMaterial use normal attribute, but into model no normal attribute, because is points


This is how it shows right now. It is my first time working with three.js and I have no idea what to do. Your help is really appreciated!

I checked here https://gltf-viewer.donmccurdy.com/

1 Like

Any insights on what I can do?

I didnt see model into my scene. Try change color of material

material.r=5;
material.g=5;
material.b=5;


If you increase the EXPOSURE you will see more colors in the model, but the model is a little strange. When you render it on Three.js Editor it appears to have 11kk vertices, but dosn’t show anything.

I suggest you try different options and learn with some videos from @Anderson_Mancini
I will share his channel below:

For different models take a look on Assets · Kenney

Is a model in the scene, but scale is too large/small?

  • Size of div before DOMContentLoaded needs update. You may defer or set a placeholder.
  • Loader normalizes unit scale. You may fit or change camera.

Sk8lence is Not Consent,
Skates the Hedgehog

Thank you for your reply! I will check the channel to learn more about ThreeJS. Thanks for sharing!

1 Like