Intersecting Objects - Shadow Problem - Three.js

Viewed 38

When I have intersecting objects there is a weird line of light in the shadow where the objects intersect. I’ve tried different types of lights, materials, browsers (MacOS), and render settings. It occurs with one or more lights.

I found that adjusting the shadow bias (spotLight.shadow.bias = 0.0005) and using a relatively large shadowmap helped reduce the lines but did not get rid of them entirely. I'm guessing that this is issue relates to how the shadowmap is rendered.

Does anyone have any ideas for what is causing this, and how to solve it?

Example image showing lines of light in shadow on intersecting objects - Demo code: https://codepen.io/henryegloff/pen/eYyRJpx



import * as THREE from 'three';
import { OrbitControls } from 'https://unpkg.com/three@0.139.0/examples/jsm/controls/OrbitControls.js';


let scene, camera, renderer, controls;
let cube_mesh;




init();



function init() {


    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xffffff);

    camera = new THREE.PerspectiveCamera(25, window.innerWidth / window.innerHeight, 0.1,1000);
    camera.position.set(0,1.5,-10);

    renderer = new THREE.WebGLRenderer({ antialias:true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    //renderer.shadowMap.type = THREE.PCFShadowMap;

    renderer.setAnimationLoop( animation );
    renderer.toneMapping = THREE.LinearToneMapping;
    renderer.physicallyCorrectLights = true;

    
    document.body.appendChild(renderer.domElement);
    window.addEventListener('resize', onWindowResize);

    controls = new OrbitControls(camera, renderer.domElement);
    controls.target = new THREE.Vector3(0, 1, 0);
      


    // Spotlight

    const spotLight = new THREE.SpotLight( 0xffffff, 11 );
    spotLight.position.set( 2, 4, -2 );

    spotLight.castShadow = true;
    // spotLight.shadow.bias = 0.0005;

    spotLight.shadow.mapSize.width = 2048;
    spotLight.shadow.mapSize.height = 2048;
    spotLight.angle = 0.6;
    spotLight.penumbra = 1;
    // spotLight.decay = 1;

    // const spotLightHelper = new THREE.SpotLightHelper( spotLight );
    // scene.add( spotLightHelper );

    scene.add( spotLight );


    // Materials

    const material_1 = new THREE.MeshPhongMaterial({color: 0xffffff,});
    const material_2 = new THREE.MeshPhongMaterial({color: 0xbbbbbb,});


    // Ground Plane

    const ground_geometry = new THREE.PlaneGeometry(20, 20);
    const ground_mesh = new THREE.Mesh(ground_geometry, material_2);
    ground_mesh.receiveShadow = true;
    ground_mesh.rotateX(-Math.PI / 2);
    scene.add(ground_mesh);


        
    // Cube

    const cube_geometry = new THREE.BoxGeometry(1, 1, 1);

    cube_mesh = new THREE.Mesh(cube_geometry, material_1);
    cube_mesh.castShadow = true;
    cube_mesh.position.y = 2;
    scene.add(cube_mesh);


    // Sphere

    const sphere_geometry = new THREE.SphereGeometry( .75, 128,128 );
    const sphere = new THREE.Mesh( sphere_geometry, material_1 );

    sphere.castShadow = true;
    sphere.receiveShadow = true;
    sphere.position.set(0,.75,0);

    scene.add( sphere );


    const sphere_2_geometry = new THREE.SphereGeometry( 1, 128, 128 );
    const sphere_2 = new THREE.Mesh( sphere_2_geometry, material_1 );

    sphere_2.castShadow = true;
    sphere_2.receiveShadow = true;
    sphere_2.position.set(-1,1.5,1);

    scene.add( sphere_2 );


}



function animation(time) {

    cube_mesh.rotation.x += 0.01;
    cube_mesh.rotation.y += 0.01;

    controls.update();
    renderer.render(scene, camera);
    
}





// Resize Window

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}
0 Answers
Related