spot light & shadow

with orbitControls, XZgrid, info

by Millieyan

HTML

<div id="info">spot light with shadow
    <br/>(cutout texture)<br/>Press Z to toggle</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/107/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js">


</script>
<script src="http://jyunming-chen.github.io/tutsplus/js/KeyboardState.js"></script>
<script type="x-shader/x-fragment" id="fragmentShaderDepth">
    uniform sampler2D texture;
    varying vec2 vUV;

    vec4 pack_depth(const in float depth) {

        const vec4 bit_shift = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
        const vec4 bit_mask = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
        vec4 res = fract(depth * bit_shift);
        res -= res.xxyz * bit_mask;
        return res;

    }

    void main() {

        vec4 pixel = texture2D(texture, vUV);

        if (pixel.a < 0.5) discard;

        gl_FragData[0] = pack_depth(gl_FragCoord.z);

    }
</script>
<script type="x-shader/x-vertex" id="vertexShaderDepth">
    varying vec2 vUV;

    void main() {

        vUV = 1.0 * uv;

        vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);

        gl_Position = projectionMatrix * mvPosition;

    }
</script>

CSS

#info {
    position: absolute;
    top: 0px;
    width: 100%;
    padding: 10px;
    text-align: center;
    color: #ffff00
}

JavaScript

var camera, scene, renderer, geometry, material, spotLight, controls;
var keyboard = new KeyboardState();
var turn = true;
var angle = 0;
var mesh2, mesh;

init();
animate();

function init() {
    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.z = 500;
    scene.add(camera);
    //////////////////////////////////

    THREE.ImageUtils.crossOrigin = '';
    sidemap = THREE.ImageUtils.loadTexture('https://millieyan.github.io/ex/drum/background2-cutout.png');

    var geometry = new THREE.CircleGeometry(50, 20);
    var material = new THREE.MeshBasicMaterial({
        map: sidemap,
        transparent: true, // for cut-out texture
        side: THREE.DoubleSide
    });

    mesh = new THREE.Mesh(geometry, material);
    mesh.position.set(0, 130, 0);
    mesh.rotation.x = Math.PI / 2;

    ///////////////////////////////////////////////////////////////////
    var uniforms = {
        texture: {
            type: "t",
            value: sidemap
        }
    };
    var vertexShader = document.getElementById('vertexShaderDepth').textContent;
    var fragmentShader = document.getElementById('fragmentShaderDepth').textContent;
    mesh.customDepthMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader
    });

    ////////////////////////////////////////////////////////
    mesh2 = mesh.clone();
    mesh2.position.set (50,80,50);
    mesh2.rotation.x = -Math.PI/2;
    mesh2.customDepthMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader
    });
    
    
    scene.add(mesh);
    scene.add (mesh2);

    spotLight = new THREE.SpotLight(0xffffff, 1.3);
    spotLight.position.set(0, 300, 0);
    spotLight.angle = Math.PI / 3;

    spotLight.castShadow = true;

    spotLight.shadowMapWidth = 1024;
   ...