ThreeJS中Shadow烘焙处理----(18)

494 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情 >


在threejs中,可以通过light去生成阴影,但是当多个灯光作用时,会生成多个阴影,效果不太好,而且threejs的阴影消耗过大,所以本文将通过烘焙实现阴影,达到较好的效果; 本篇所用到的图片资源如下:

bakedShadow.jpg simpleShadow.jpg

所谓烘焙就是将场景中的光照效果,渲染成特殊的静帧图片,我们将这个图片以贴图的形式作用在其产生阴影的物体上,生成了静态的阴影;

实现静态阴影

使用到了第一张素材图

// 加载器
const textureLoader = new THREE.TextureLoader()
// 加载烘焙后的纹理图
const bakedShadow = textureLoader.load('./textures/bakedShadow.jpg')
// 给地板设置上
const plane = new THREE.Mesh(
    new THREE.PlaneGeometry(5, 5),
    new THREE.MeshBasicMaterial({
        map:bakedShadow
    })
)
2022-08-22 153702.gif

如图所示,plane上面好像是生成了球体的阴影,但这个阴影是静态的,他不会跟随我们的球体运动而运动,球体移动的话他就暴露了;

实现静态阴影跟随

const simpleShadow = textureLoader.load('./textures/simpleShadow.jpg')
// 创建shadow面片
const shadowPlane = new THREE.Mesh(
    new THREE.PlaneGeometry(1.5, 1.5),
    // 设置贴图
    new THREE.MeshBasicMaterial({
        alphaMap:simpleShadow,
        transparent:true,
        color:0x000000
    })
)
// 设置合适的位置 位置如果重合会导致GPU不知该渲染哪一个模型,mesh会不断闪烁
shadowPlane.position.y =plane.position.y+0.01;
// 旋转至正确位置
shadowPlane.rotation.x = -Math.PI/2
// 效果如图一
// 添加小球运动
const clock = new THREE.Clock()
function renderScene() {
    let num= clock.getElapsedTime()
    // 小球跳跃动画
    sphere.position.x = Math.cos(num)
    sphere.position.y = Math.abs(Math.sin(num))
    sphere.position.z = Math.abs(Math.sin(num))

    // 设置阴影面片跟随
    shadowPlane.position.x = Math.cos(num)
    // 阴影根据远近透明度变化 距离越远越透
    shadowPlane.material.opacity = 1-  Math.abs(Math.sin(num))

    // 最终实现效果见图二
    
    // 更新轨道控制 实现鼠标可操控
    controls.update();
    // requestAnimationFrame 浏览器自带,一半每秒60帧,在dom不可见时不进行重绘/回流
    requestAnimationFrame(renderScene)
    renderer.render(scene, camera)

}
image.png

图一

2022-08-22 155809.gif

图二

如果有哪里描述不准确或者有问题,欢迎大佬指正!
(≖ᴗ≖)✧