Shadows not working at all [Parcel, Node]

I can’t get objects to cast shadows with any type of light.
My init:

function init(){
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(conf.fov, window.innerWidth/window.innerHeight, conf.near, conf.far);
    camera.position.set(conf.camX,conf.camY,conf.camZ);
    
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth,window.innerHeight);
    renderer.shadowMap.enable = true;
    
    controls = new PointerLockControls(camera, renderer.domElement);

    document.body.appendChild(renderer.domElement);

    dirLight = new THREE.DirectionalLight(0xffffff);
    dirLight.castShadow = true;
    dirLight.position.set(1,1,1);
    
    let d = 5;
    dirLight.shadow.camera.left = -d;
    dirLight.shadow.camera.right = -d;
    dirLight.shadow.camera.top = -d;
    dirLight.shadow.camera.bottom = -d;
    dirLight.shadow.camera.near = 1;
    dirLight.shadow.camera.far = 1;
    scene.add(dirLight)
    
    dirHelp = new THREE.DirectionalLightHelper(dirLight);
    scene.add(dirHelp);

    let geometry = new THREE.PlaneGeometry(10,10);
    let material = new THREE.MeshPhongMaterial({color: 0xffffff});
    plano = new THREE.Mesh(geometry,material);
    plano.rotation.x = -Math.PI/2;
    plano.receiveShadow = true;
    scene.add(plano);
    
    geometry = new THREE.SphereGeometry(0.5);
    esf = new THREE.Mesh(geometry,material);
    esf.position.y = 1;
    scene.add(esf);

    instructions.addEventListener('click', function(){
        controls.lock();
    });
    controls.addEventListener('lock', function(){
        instructions.style.display = 'none';
        blocker.style.display = 'none';
    });
    controls.addEventListener('unlock', function(){
        blocker.style.display = 'block';
        instructions.style.display = '';
    });

    camera.lookAt(scene.position);
    animate();
}

How it looks:


Im using node with parcel.

d

Still the same

esf.castShadow = true


It still doesn’t work, the shadow camera doesn’t match the direction of the light either.

It’s not clear from the screenshot, the light seems way-off, I suggest you share a jsFiddle of your scene, and here is a working example jsfiddle

Idk how to make jsfiddle to work with my code, im pretty noob on js environments, this is the code from the video:

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

var conf = {
        fov : 45,
        near : 1,
        far : 1000,
};

function init(){
    scene=new THREE.Scene();
    camera=new THREE.PerspectiveCamera(conf.fov,window.innerWidth/window.innerHeight,conf.near,conf.far);
    camera.position.set(5,2,0);

    renderer=new THREE.WebGLRenderer({antialias: true});
    renderer.shadowMap.enable=true
    renderer.setSize(window.innerWidth,window.innerHeight);

    controls = new OrbitControls(camera,renderer.domElement);
    document.body.appendChild(renderer.domElement);

    let material = new THREE.MeshPhongMaterial();
    
    let geometry = new THREE.PlaneGeometry(10, 10);
    let plane = new THREE.Mesh(geometry, material);
    plane.rotation.x = -Math.PI/2;
    plane.receiveShadow = true;
    scene.add(plane);

    geometry = new THREE.SphereGeometry(1)
    let esf = new THREE.Mesh(geometry, material); 
    esf.position.set(0,1,-2);
    esf.castShadow = true;
    scene.add(esf);

    directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.castShadow=true;
    directionalLight.position.set(5,5,5);
    directionalLight.target = esf;

    scene.add(directionalLight);
    
    dirhelper = new THREE.DirectionalLightHelper(directionalLight);
    scene.add(dirhelper)

    helper = new THREE.CameraHelper(directionalLight.shadow.camera);
    scene.add(helper);
    
    camera.lookAt(scene.position);
    animate();
}

function animate(){
    requestAnimationFrame(animate);
    renderer.render(scene,camera);
}

window.addEventListener( 'resize', function () {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );

} );

window.onload = init;

For what I understand the shadow camera of the light its not matching the light target, but i even create a plane perpendicular to see if the shadow was projected in the direction of the camera frustrum, but didnt cast any kind of shadow either.

Change your line
renderer.shadowMap.enable=true
to
renderer.shadowMap.enabled=true

As my reply to mjurczyk first comment, I still have the same problem. Could it be the browser cache?

I currently have

shadowMap.enabled=true;
esf.castShadow=true;
light.castShadow=true;
plane.receiveShadow=true;

All objects use MeshPhongMaterial too.

This bit of code that you posted 2 hours ago, shows that you didn’t fix mjurczyk’s suggestion.

Here is a simplified version of your code. Start from something that works, and then add your complications bit by bit so that you have a better idea what breaks it.

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100)
camera.position.set(5, 2, 0)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

new OrbitControls(camera, renderer.domElement)

const material = new THREE.MeshPhongMaterial()

const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), material)
plane.rotation.x = -Math.PI / 2
plane.receiveShadow = true
scene.add(plane)

const esf = new THREE.Mesh(new THREE.SphereGeometry(1), material)
esf.position.set(0, 1, -2)
esf.castShadow = true
scene.add(esf)

const light = new THREE.DirectionalLight(0xffffff, Math.PI)
light.castShadow = true
light.position.set(5, 5, 5)
light.target = esf
light.shadow.camera.far = 15
scene.add(light)

scene.add(new THREE.DirectionalLightHelper(light))

scene.add(new THREE.CameraHelper(light.shadow.camera))

window.addEventListener('resize', function () {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
})

function animate() {
    requestAnimationFrame(animate)
    renderer.render(scene, camera)
}

animate()

This is what I see

1 Like

Yeah, i made the shadows work but one more question.

Why the directional shadow looks like this?

I changed the frustrum to cover all the scene

Shadow map size probably

https://sbcode.net/threejs/directional-light-shadow/

1 Like

*frustum frustum - Wiktionary, the free dictionary

The tuning of shadowmaps is a whole thing. You can try expanding the coverage by updating the shadow.camera left/right/top/bottom… (which it sounds like you did!)

and you can increase/decrease the resolution (width/height) of the shadowmap…

And you can adjust the “bias” on the light.shadow by + or - very small values to get rid of “shadow acne”/“peter panning”

There are other settings as well that are different between the different types of shadowmapping.