castShadow 是否投射阴影
Three.js 中的castShadow属性用于控制物体是否投射阴影。
定义和作用
castShadow属性用于设置物体是否投射阴影。当设置为true时,物体将投射阴影;设置为false时,物体不投射阴影。默认值为false。具体应用场景和代码示例
在Three.js中,要使一个物体投射阴影,需要在创建光源时设置其castShadow属性为true,并在需要投射阴影的物体上设置其castShadow属性为true。以下是一个简单的示例:
// 创建一个平行光光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(2, 2, -1);
scene.add(directionalLight);
directionalLight.castShadow = true; // 允许投射阴影
// 创建一个需要投射阴影的物体
const object = new THREE.Mesh(geometry, material);
object.castShadow = true; // 设置该物体投射阴影
-
性能影响和优化建议
投射阴影会增加计算量和渲染时间,因此在实际应用中需要注意以下几点以优化性能:- 调整阴影贴图的大小:可以通过调整光源的shadow.mapSize.width和shadow.mapSize.height来控制阴影贴图的大小,从而影响阴影的清晰度。
- 调整阴影相机的视锥体:通过设置光源的shadow.camera.top、shadow.camera.bottom、shadow.camera.right和shadow.camera.left来调整阴影相机的视锥体,决定阴影投射的区域。
- 调整相机的远近平面:通过设置光源的shadow.camera.near和shadow.camera.far来调整阴影相机的远近平面,影响阴影的范围。
receiveShadow 是否接收阴影
Three.js 中的receiveShadow属性用于设置物体是否接收阴影。当receiveShadow属性设置为true时,表示该物体可以接收阴影;设置为false时,表示该物体不接收阴影。默认情况下,receiveShadow属性为false。
- 设置方法
创建物体时设置:在创建物体时,可以通过设置物体的材质来指定其是否接收阴影。例如:
const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), new THREE.MeshStandardMaterial());
plane.receiveShadow = true; // 设置该平面可以接收阴影
修改现有物体的材质:如果物体已经创建,可以通过修改其材质的receiveShadow属性来设置是否接收阴影:
plane.material.receiveShadow = true; // 设置该平面可以接收阴影
场景中的应用示例
在一个场景中,通常会有光源(如平行光、点光源等)和多个物体。为了实现阴影效果,需要确保以下几点:光源设置:光源需要设置castShadow属性为true,以投射阴影。例如:
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(2, 2, -1);
directionalLight.castShadow = true; // 允许投射阴影
scene.add(directionalLight);
- 物体设置:需要接收阴影的物体(如平面、球体等)需要将receiveShadow属性设置为true。例如:
const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), new THREE.MeshStandardMaterial());
plane.receiveShadow = true; // 设置该平面可以接收阴影
scene.add(plane);
- 渲染器设置:确保渲染器的 shadowMap.enabled 属性为true,以允许场景中使用阴影贴图。例如:
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true; // 允许渲染器生成阴影贴图
样例
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// import GUI from 'lil-gui';
const canvas = document.querySelector('canvas.webgl');
const scene = new THREE.Scene();
const textureLoader = new THREE.TextureLoader();
const material = new THREE.MeshStandardMaterial();
//球
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(0.5, 64, 64),
material
);
//平面
const plane = new THREE.Mesh(
new THREE.PlaneGeometry(1, 1),
material
);
//圆环
const torus = new THREE.Mesh(
new THREE.TorusGeometry(0.5, 0.2, 32, 64),
material
);
// 地板
const bakedShadowLoader = new THREE.Mesh(
new THREE.PlaneGeometry(6, 6),
new THREE.MeshStandardMaterial()
)
// 接收阴影
bakedShadowLoader.receiveShadow = true;
bakedShadowLoader.rotation.x = -Math.PI / 2;
bakedShadowLoader.position.y = -0.5;
scene.add(bakedShadowLoader);
sphere.castShadow = true;
plane.castShadow = true;
torus.castShadow = true;
scene.add(sphere, plane, torus);
sphere.position.x = -1.5;
torus.position.x = 1.5;
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 点光源
// const pointLight = new THREE.PointLight(0xffffff, 50);
// pointLight.position.set(2, 2, -1);
// scene.add(pointLight);
// pointLight.castShadow = true; // 开启阴影
// const pointLightHelper = new THREE.PointLightHelper(pointLight, 0.2);
// scene.add(pointLightHelper);
// 聚光灯
const spotLight = new THREE.SpotLight(0x0000ff, 20);
spotLight.position.set(2, 3, -1);
spotLight.castShadow = true; // 开启阴影
scene.add(spotLight);
const spotLightHelper = new THREE.SpotLightHelper(spotLight);
spotLightHelper.visible = true; // 显示辅助灯光
scene.add(spotLightHelper);
//优化阴影效果一个Vector2定义阴影贴图的宽度和高度
spotLight.shadow.mapSize.width=1024
spotLight.shadow.mapSize.height=1024
spotLight.shadow.camera.far=10;
// 平行光
// const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
// directionalLight.position.set(3, 9, -8);
// directionalLight.castShadow = true; // 开启阴影
// scene.add(directionalLight);
// const directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight, 0.2);
// scene.add(directionalLightHelper);
// 半球光(不能投影)
// const hemisphereLight = new THREE.HemisphereLight(0x0000ff, 0xffffff, 0.3);
// scene.add(hemisphereLight);
// const hemisphereLightHelper = new THREE.HemisphereLightHelper(hemisphereLight, 0.2);
// scene.add(hemisphereLightHelper);
// 渲染
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
});
const sizes = {
width: window.innerWidth,
height: window.innerHeight
};
window.addEventListener('resize', () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
// 相机
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100);
camera.position.x = 3;
camera.position.y = 3;
camera.position.z = 6;
scene.add(camera);
// 控制器
const controls = new OrbitControls(camera, canvas);
controls.enableDamping = true;
// 渲染器
renderer.setSize(sizes.width, sizes.height);
renderer.shadowMap.enabled=true //渲染器启用阴影
function tick() {
// 更新控制器
controls.update();
// 渲染场景
renderer.render(scene, camera);
// 循环调用tick函数
window.requestAnimationFrame(tick);
}
tick();