Peeke Kuepers
Peeke Kuepers

Reputation: 193

Shadow not visible in (THREE.js r82)

I'm trying to cast a shadow from a cube onto a plain with MeshLambertMaterial, but no shadows are showing.

Solutions I've found usually boil down to the objects not being inside the frustum, but the object seems to be in the frustum.

Do you know what I'm doing wrong here? Am I setting some property to a crazy value? Any help would be greatly appreciated. I've included a fiddle to show my working code here: https://jsfiddle.net/44jwvbt6/

// import Ticker from 'timing/Ticker';

class World {

    constructor() {

        this._renderer = new THREE.WebGLRenderer({ antialias: true });
        this._renderer.shadowMap.enabled = true;
        this._renderer.shadowMap.type = THREE.PCFShadowMap;
        // this._renderer.shadowMap.cullFace = THREE.CullFaceBack;

        this._scene = new THREE.Scene();
        this._scene.background = new THREE.Color( 0x333333 );

        const width = window.innerWidth;
        const height = window.innerHeight;

        this._camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, -400, 400 );
        this._camera.position.set(0, 0, 100);

        const geometry = new THREE.BoxGeometry(100, 100, 100);
        const material = new THREE.MeshLambertMaterial({ color: 0xff0000 });

        const light = new THREE.DirectionalLight(0xffffff, 1);
        light.position.set( 0, 200, 400 );
        light.castShadow = true;
        light.shadow.camera.near = -1000;
        light.shadow.camera.far = 2000;
        // light.shadow.camera.fov = 30;
        light.shadow.bias = 0.0038;
        light.shadow.mapSize.width = 1024;
        light.shadow.mapSize.height = 1024;
        // light.shadow.camera.left = -width / 2;
        // light.shadow.camera.right = width / 2;
        // light.shadow.camera.top = -height / 2;
        // light.shadow.camera.bottom = height / 2;
        this._scene.add(light);
        this._scene.add(new THREE.CameraHelper( light.shadow.camera ));

        const mesh1 = new THREE.Mesh(geometry, material);
        mesh1.position.set(0, 0, 100);
        mesh1.castShadow = true;
        this._scene.add(mesh1);

        const plane = new THREE.PlaneGeometry(width, height);
        const mesh4 = new THREE.Mesh(plane, material);

        // mesh2.castShadow = true;
        // mesh3.castShadow = true;
        mesh4.receiveShadow = true;
        this._scene.add(mesh4);

        const controls = new THREE.OrbitControls( this._camera, this._renderer.domElement );

        window.addEventListener('resize', this._resize.bind(this));

        this._resize();

        this.animate();
        // this._ticker = new Ticker(1000 / 60);
        // this._ticker.onTick(this.animate.bind(this));

    }

    get element() {
        return this._renderer.domElement;
    }

    get scene() {
        return this._scene;
    }

    _resize() {
        this._renderer.setSize(window.innerWidth, window.innerHeight);
    }

    animate() {
        this._renderer.render(this._scene, this._camera);
        requestAnimationFrame(this.animate.bind(this));
    }

}

const world = new World;
document.body.appendChild(world.element);

// export default World;

Upvotes: 1

Views: 960

Answers (1)

spirulence
spirulence

Reputation: 721

Two problems here: one is the re-use of materials. Not sure why this is an issue, but this solves it.

const mesh4 = new THREE.Mesh(plane, new THREE.MeshLambertMaterial({ color: 0xff0000}));

The other is that you've commented out the lines that make your directional light cast sizeable shadows. Directional lights in particular only cast shadows within the box defined by all those light.shadow.camera.* properties. Make sure these are uncommented:

light.shadow.camera.left = -width / 2;
light.shadow.camera.right = width / 2;
light.shadow.camera.top = -height / 2;
light.shadow.camera.bottom = height / 2;

Fiddle with these changes: https://jsfiddle.net/nrbojkoo/1/

Upvotes: 3

Related Questions