node.jsthree.js3d-modelthreejs-editor

Shadows not casted/received with HDR environment texture in Three js


I am new to three js and I’ve been working on a project where I want to cast a shadow of the import 3D model which is download from this link also download the HDR file from the link free pack.

As per the videos avaliable on the internet and while googling my problem I have found some of the issue in my code which I have changed like scene.environment = texture;. I have the mesh of the model to castShadow = true and receiveShadow = true also added the to receiveShadow = true. But still I am not able to cast the shadow.

Library version I am using:

three - v0.162.0 node - v20.11.1 vite - v5.2.0

Here is my index.js file code:

import * as THREE from "three";
import "./style.css";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
// Scene
const scene = new THREE.Scene();

// Sizes
const sizes = {
  width: 800,
  height: 500,
};

const gltfLoader = new GLTFLoader();

const rgbeloader = new RGBELoader();

let car3;
rgbeloader.load(
  "./WhiteNeons_NAD.hdr",
  (texture) => {
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.environment = texture;
    scene.castShadow = true;

    gltfLoader.load(
      "./models/car3/scene.gltf",
      (gltf) => {
        const model = gltf.scene;
        model.position.set(0, 0, 0);
        model.traverse((node) => {
          node.castShadow = node.isMesh;
          node.receiveShadow = node.isMesh;
        });
        scene.add(model);
        car3 = model;
      },
      undefined,
      (error) => {
        console.error(error);
      }
    );
  },
  undefined,
  (err) => {
    console.error("HDR:: ", err);
  }
);

// Plane
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const planeMat = new THREE.MeshBasicMaterial({ color: 0x5a5a5a });
const plane = new THREE.Mesh(planeGeometry, planeMat);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);

const gridHelper = new THREE.GridHelper();
gridHelper.receiveShadow = true;
scene.add(gridHelper);
// Camera
const camera = new THREE.PerspectiveCamera(
  45,
  sizes.width / sizes.height,
  0.1,
  1000
);
camera.position.set(5, 2, 0);
// camera.position.z = 20;
scene.add(camera);

// Renderer
const canvas = document.querySelector(".webgl");
const renderer = new THREE.WebGLRenderer({ canvas });

renderer.setClearColor(0xa3a3a3);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 6;

renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.render(scene, camera);

// Controls
const controls = new OrbitControls(camera, canvas);

window.addEventListener("resize", () => {
  camera.updateProjectionMatrix();
});

function animate(time) {
  if (car3) {
    car3.rotation.y = -time / 1000;
  }
  controls.update();
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

Solution

  • In three.js it is not possible to cast shadows with environment maps.

    You have to use a shadow casting light like a directional, point or spot light or fake shadows somehow. One option is to use THREE.ShadowMesh but this would only produce a planar shadow so it's not a full replacement of classic shadow mapping.