Search code examples
javascriptthree.jsshadow

THREE.JS does not cast shadows


I was doing a Three js tutorial and this code should cast shadows, but when render shadows does not exists over the plane.

What is wrong on code? I'm reading documentation and other codes and I can not find the problem.

Best regards!

EDIT:

If i make a loop with requestAnimationFrame just works... but only in that case... why?

<!DOCTYPE html>
<html>
    <head>
        <title>Learning THREE JS Basic</title>
        <script src="../../libs/three.js"></script>
        <script src="../../libs/jquery.js"></script>

        <style>
        body {
            margin   : 0;
            overflow : hidden;
        }
        </style>
    </head>

    <body>
        <div id="visor"></div>

        <script>
            $(function () {
                var scene = new THREE.Scene();

                var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);

                var renderer = new THREE.WebGLRenderer();
                renderer.setClearColor(0xEEEEEE);
                renderer.setSize(window.innerWidth, window.innerHeight);
                renderer.shadowMap.enabled = true;

                var axes = new THREE.AxisHelper(20);
                scene.add(axes);

                var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
                var planeMaterial = new THREE.MeshLambertMaterial({
                    color: 0xFFFFFF 
                });

                var plane = new THREE.Mesh(planeGeometry, planeMaterial);

                plane.rotation.x = -0.5*Math.PI;

                plane.position.x = 15;
                plane.position.y = 0;
                plane.position.z = 0;

                plane.receiveShadow = true;

                scene.add(plane);

                var cubeGeometry = new THREE.BoxGeometry(4,4,4);
                var cubeMaterial = new THREE.MeshLambertMaterial({
                    color: 0xFF0000
                });

                var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

                cube.position.x = -4;
                cube.position.y = 3;
                cube.position.z = 0;

                cube.castShadow = true;

                scene.add(cube);

                var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
                var sphereMaterial = new THREE.MeshLambertMaterial({
                    color: 0x7777FF
                });

                var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

                sphere.position.x = 20;
                sphere.position.y = 4;
                sphere.position.z = 2;

                sphere.castShadow = true;

                scene.add(sphere);

                var spotLight = new THREE.SpotLight(0xFFFFFF);
                spotLight.position.set(-40, 60, -10);
                spotLight.castShadow = true;

                scene.add(spotLight);

                camera.position.x = -30;
                camera.position.y = 40;
                camera.position.z = 30;
                camera.lookAt(scene.position);

                $("#visor").append(renderer.domElement);
                renderer.render(scene, camera);
            });
        </script>
    </body>
</html>

Solution

  • three.js r.74 and r.75 have a bug in which shadows are not always rendered in the first call to render(). This bug has been fixed in three.js r.76dev.

    Your work-around is to call renderer.render( scene, camera ) a 2nd time, or to have an animation loop.

    three.js r.75