Three.js(16)——Shadows(一)

304 阅读2分钟

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

激活阴影

想要激活并使用阴影,就得先在渲染器 renderer 的 .shadowMap.enabled 属性中设置开启,允许在场景中使用阴影贴图。

renderer.shadowMap.enabled = true;

检查每个对象,确定它是否可以使用castshadow投射阴影,以及是否可以使用receiveshadow接收阴影。 现在我们的场景里有一个球体和一块平面,光源有环境光 AmbientLight 和平行光 DirectionalLight。
场景中存在一球体与一平面。

// 创建球体
const sphere = new THREE.Mesh(
    new THREE.SphereBufferGeometry(0.5, 32, 32),
    material
);
// 为sphere开启投射阴影
sphere.castShadow = true;

// 创建一平面
const plane = new THREE.Mesh(
    new THREE.PlaneBufferGeometry(5, 5),
    material
);
plane.rotation.x = -Math.PI * 0.5;
plane.position.y = -0.5;
// plane接收投射阴影
plane.receiveShadow = true;

scene.add(sphere, plane);

注意:只有平行光、点光源和聚光灯支持阴影

平行光阴影

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
// 改变光的方向
directionalLight.position.set(2, 2, -1);
// 使用castShadow激活directionalLight灯光上的阴影
directionalLight.castShadow = true;

此时,平行光下的阴影还是比较模糊,不够清晰,我们可以设置贴图尺寸为2的n次幂,我们会发现当数值越高,阴影就拥有月清晰的细节,数值越低,阴影就越模糊。

directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
directionalLight.shadow.camera.top = 2;
directionalLight.shadow.camera.right = 2;
directionalLight.shadow.camera.bottom = -2;
directionalLight.shadow.camera.left = -2;
directionalLight.shadow.camera.near = 1;
// 灯光相机的可视范围越小,阴影越精确,当然如果设置得实在太小,阴影将会被裁剪掉
directionalLight.shadow.camera.far = 6;
// 我们可以通过radius属性控制阴影模糊程度,它不会改变灯光相机与物体的距离
directionalLight.shadow.radius = 10;

// 用于模拟相机视锥体的辅助对象:CameraHelper
const directionalLightCameraHelper = new THREE.CameraHelper(
  // 参数为:被模拟的相机
  directionalLight.shadow.camera
);
directionalLightCameraHelper.visible = false;
scene.add(directionalLightCameraHelper);

此时效果为:

微信截图_20220823152838.png

阴影贴图

有不同类型的算法可以应用于阴影贴图:

种类特点
THREE.BasicShadowMap性能非常好但是质量很差
THREE.PCFShadowMap性能较差但边缘更平滑(默认)
THREE.PCFSoftShadowMap性能较差但边缘更柔和
THREE.VSMShadowMap性能差,约束多,但能够产生意想不到的效果

PCF柔软阴影贴图

注意点:renderer.shadowMap 的 type 为 PCFSoftShadowMap 时,shadow.radius 不生效,阴影不存在模糊程度。

renderer.shadowMap.type = THREE.PCFSoftShadowMap;

此时效果为下图所示:

微信截图_20220823153201.png

关于聚光灯阴影和点光源阴影,我们下一篇再来讨论(≖ᴗ≖)✧