Sunday, 26 February 2023

Sharp lines in corners of Threejs BoxGeometry shadows

I made a structure using BoxGeometry, and I have a DirectionalLight rotating around it. The problem is, I can see aliased light bleed in the corners. I've tried updating the shadow.mapSize, the blur radius, the renderer.shadowMap.type, but nothing has worked so far.

shadow aliasing

const gui = new lil.GUI();

// SCENE
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ antialias: true });


const settings = {
    shadowMapType: "basic",
    physicallyCorrectLights: false,
    shadowMapSize: 2056,
    shadowRadius: 5
}

// CAMERA
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

// RENDERER
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.physicallyCorrectLights = settings.physicallyCorrectLights;
renderer.shadowMap.type = settings.shadowMapType;
renderer.shadowMap.enabled = true;

// CONTROLS
const controls = new THREE.OrbitControls(camera, renderer.domElement);

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

// INIT CAMERA
camera.position.z = 35;
camera.position.x = 7.5;
camera.position.y = 13;
camera.lookAt(7.5, 0, -20)

// INIT HEMISPHERE LIGHT
scene.add(new THREE.AmbientLight( 0xffffff, 0.5 ));

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

// FLOOR
const plane = new THREE.Mesh(new THREE.PlaneGeometry(500, 500, 32), new THREE.MeshPhongMaterial({ color: 0xfab74b}));
plane.rotation.x = - Math.PI / 2
plane.receiveShadow = true
scene.add(plane);


const geometry = new THREE.BoxGeometry( 1, 15, 7 );
const material = new THREE.MeshPhongMaterial( {color: 0xFFFFFF} );
const cube = new THREE.Mesh( geometry, material );
cube.position.y = 7.5; 
cube.position.z = -4.5; 
cube.receiveShadow = true
cube.castShadow = true
scene.add( cube );

const geometry2 = new THREE.BoxGeometry( 1, 15, 7 );
const material2 = new THREE.MeshPhongMaterial( {color: 0xFFFFFF} );
const cube2 = new THREE.Mesh( geometry2, material2);
cube2.position.y = 7.5;
cube2.position.z = -4.5; 
cube2.position.x = 16; 
cube2.receiveShadow = true
cube2.castShadow = true
scene.add( cube2 );


//back wall
const geometry3 = new THREE.BoxGeometry( 1, 15, 15 );
const material3 = new THREE.MeshPhongMaterial( {color: 0xFFFFFF} );
const cube3 = new THREE.Mesh( geometry3, material3);
cube3.position.y = 7.5;
cube3.position.x = 8;
cube3.position.z = -7.5 
cube3.rotateY(Math.PI / 2)
cube3.receiveShadow = true
cube3.castShadow = true
scene.add( cube3 );


//top
const geometry4 = new THREE.BoxGeometry( 1, 7, 17 );
const material4 = new THREE.MeshPhongMaterial( {color: 0xFFFFFF} );
const cube4 = new THREE.Mesh( geometry4, material4);
cube4.position.y = 15.5;
cube4.position.x = 8;
cube4.position.z = -4.5 
cube4.rotateY(Math.PI / 2)
cube4.rotateZ(Math.PI / 2)
cube4.receiveShadow = true
cube4.castShadow = true
scene.add( cube4 );




// DIRECTIONAL LIGHT
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.x += 20
directionalLight.position.y += 20
directionalLight.position.z += 20
directionalLight.castShadow = true
directionalLight.shadow.mapSize.width = settings.shadowMapSize;
directionalLight.shadow.mapSize.height = settings.shadowMapSize;
directionalLight.shadow.radius = settings.shadowRadius
// directionalLight.shadow.blurSamples = 500
const d = 25;
directionalLight.shadow.camera.near = 0.5
directionalLight.shadow.camera.far = 60
directionalLight.shadow.camera.left = - d;
directionalLight.shadow.camera.right = d;
directionalLight.shadow.camera.top = d;
directionalLight.shadow.camera.bottom = - d;
scene.add(directionalLight);

scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );




// ANIMATE
function animate() {
    // TARGET
    const time = Date.now() * 0.0005;
    directionalLight.position.x = Math.sin(time * 0.7) * 20;
    directionalLight.position.z = Math.cos(time * 0.7) * 20;

    renderer.render(scene, camera);
    requestAnimationFrame(animate);
}
document.body.appendChild(renderer.domElement);
animate();

gui.add( settings, 'shadowMapType', ["basic", "pcf","pcfsoft", "vsm"])
    .onChange( value => {
        switch (value) {
          case 'basic':
            renderer.shadowMap.type = THREE.BasicShadowMap;
            break;
          case 'pcf':
            renderer.shadowMap.type = THREE.PCFShadowMap;
            break;
          case 'pcfsoft':
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            break;
          case 'vsm':
            renderer.shadowMap.type = THREE.VSMShadowMap;
            break;
          default:
            console.log('Invalid shadow map type');
        }
        console.log(renderer.shadowMap.type)
    } );
gui.add(settings, "physicallyCorrectLights")
    .onChange( value => {
        renderer.physicallyCorrectLights = settings.physicallyCorrectLights
    })
gui.add( settings, 'shadowMapSize', 0, 12000, 200 )
    .onChange( value => {
        directionalLight.shadow.map.dispose(); // important
        directionalLight.shadow.mapSize = new THREE.Vector2(value,value)
    })

gui.add( settings, 'shadowRadius', 0, 100, 1 )
.onChange( value => {
    directionalLight.shadow.radius = value;
    directionalLight.shadow.updateMatrices(directionalLight);
})
*
{
    margin: 0;
    padding: 0;
}

html,
body
{
    overflow: hidden;
}

.webgl
{
    position: fixed;
    top: 0;
    left: 0;
    outline: none;
}
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/three@0.122.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.122.0/examples/js/controls/OrbitControls.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/three-buffer-geometry-utils@1.0.0/index.min.js"></script>

<script src="https://unpkg.com/lil-gui@0.16.1/dist/lil-gui.umd.js"></script>

<!-- <script src="https://cdn.jsdelivr.net/npm/three-orbitcontrols@2.110.3/OrbitControls.min.js"></script> -->




<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Open Box</title>
</head>
<body>
    <canvas class="webgl"></canvas>
</body>
</html>

Here is a demo with an imported open box cube (rather than several box geometries next to each other), it still has the artifacting. https://main--marvelous-monstera-7ef7c2.netlify.app/



from Sharp lines in corners of Threejs BoxGeometry shadows

No comments:

Post a Comment