2. 光照 (Lights) 与阴影 (Shadows)


文档摘要

光照 (Lights) 与阴影 (Shadows) Three.js 光照 (Lights) 与阴影 (Shadows) 光照是 Three.js 场景中至关重要的组成部分,它赋予了场景深度、真实感和氛围。阴影则进一步增强了这种真实感,使物体能够相互遮挡光线,从而创建更具沉浸感的视觉体验。 光照类型 (Light Types) Three.js 提供了多种不同类型的光照,每种光照都有其独特的特性和用途。 AmbientLight (环境光): 环境光是一种均匀照射场景中所有物体的光。它没有方向,不会产生阴影。通常用作场景中的基础照明,以确保即使在没有其他光源的情况下,物体也能被看到。 DirectionalLight (平行光): 平行光模拟来自无限远的光源,例如太阳。

2. 光照 (Lights) 与阴影 (Shadows)

Three.js 光照 (Lights) 与阴影 (Shadows)

光照是 Three.js 场景中至关重要的组成部分,它赋予了场景深度、真实感和氛围。阴影则进一步增强了这种真实感,使物体能够相互遮挡光线,从而创建更具沉浸感的视觉体验。

1. 光照类型 (Light Types)

Three.js 提供了多种不同类型的光照,每种光照都有其独特的特性和用途。

  • AmbientLight (环境光):

    环境光是一种均匀照射场景中所有物体的光。它没有方向,不会产生阴影。通常用作场景中的基础照明,以确保即使在没有其他光源的情况下,物体也能被看到。

    const ambientLight = new THREE.AmbientLight(0x404040); // soft white light scene.add(ambientLight);
  • DirectionalLight (平行光):

    平行光模拟来自无限远的光源,例如太阳。它具有特定的方向,所有光线都沿该方向平行传播。平行光可以产生阴影。

    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); directionalLight.castShadow = true; // 启用阴影投射 scene.add(directionalLight);
  • PointLight (点光源):

    点光源从一个点向所有方向发射光线。类似于灯泡。点光源可以产生阴影。

    const pointLight = new THREE.PointLight(0xffffff, 1, 100); // color, intensity, distance pointLight.position.set(0, 5, 0); pointLight.castShadow = true; scene.add(pointLight);
  • SpotLight (聚光灯):

    聚光灯从一个点向一个锥形区域发射光线。类似于手电筒或舞台灯光。聚光灯可以产生阴影。

    const spotLight = new THREE.SpotLight(0xffffff, 1); spotLight.position.set(5, 5, 5); spotLight.target.position.set(0, 0, 0); spotLight.angle = Math.PI / 6; spotLight.penumbra = 0.2; spotLight.decay = 2; spotLight.distance = 200; spotLight.castShadow = true; scene.add(spotLight); scene.add(spotLight.target); // 聚光灯需要一个目标
  • HemisphereLight (半球光):

    半球光模拟户外环境光,它从天空和地面两个方向发射不同颜色的光。它没有方向,不会产生阴影。

    const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x080820, 1); // skyColor, groundColor, intensity scene.add(hemisphereLight);
  • RectAreaLight (矩形区域光):

    矩形区域光从一个矩形区域发射光线。这种光照类型可以创建更柔和、更逼真的阴影,但计算成本较高。 需要RectAreaLightUniformsLib

    import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; RectAreaLightUniformsLib.init(); const rectLight = new THREE.RectAreaLight( 0xffffff, 5, 4, 10 ); rectLight.position.set( 5, 5, 0 ); rectLight.lookAt( 0, 0, 0 ); scene.add( rectLight ) const rectLightHelper = new RectAreaLightHelper( rectLight ); rectLight.add( rectLightHelper );

2. 阴影 (Shadows)

要在 Three.js 中启用阴影,需要执行以下步骤:

  1. 启用渲染器的阴影:

    renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 可选的阴影类型
  2. 启用光源的阴影投射:

    directionalLight.castShadow = true;
  3. 启用物体的阴影接收和投射:

    mesh.receiveShadow = true; // 接收阴影 mesh.castShadow = true; // 投射阴影
  4. 调整阴影贴图参数 (可选):

    可以调整光源的 shadow 属性来优化阴影质量和性能。

    directionalLight.shadow.mapSize.width = 1024; directionalLight.shadow.mapSize.height = 1024; directionalLight.shadow.camera.near = 0.5; directionalLight.shadow.camera.far = 500; directionalLight.shadow.camera.left = -10; directionalLight.shadow.camera.right = 10; directionalLight.shadow.camera.top = 10; directionalLight.shadow.camera.bottom = -10;

3. 代码实践 (Code Example)

以下是一个简单的 Three.js 场景,展示了如何使用平行光和阴影:

import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; // 创建场景 const scene = new THREE.Scene(); // 创建相机 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 5, 10); // 创建渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMap.enabled = true; // 启用阴影 renderer.shadowMap.type = THREE.PCFSoftShadowMap; document.body.appendChild(renderer.domElement); // 创建轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; // 创建平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); directionalLight.castShadow = true; // 启用阴影投射 directionalLight.shadow.mapSize.width = 1024; directionalLight.shadow.mapSize.height = 1024; directionalLight.shadow.camera.near = 0.5; directionalLight.shadow.camera.far = 50; scene.add(directionalLight); // 创建环境光 const ambientLight = new THREE.AmbientLight(0x404040); scene.add(ambientLight); // 创建平面 const planeGeometry = new THREE.PlaneGeometry(10, 10); const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x808080 }); const plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = -Math.PI / 2; plane.receiveShadow = true; // 接收阴影 scene.add(plane); // 创建立方体 const cubeGeometry = new THREE.BoxGeometry(1, 1, 1); const cubeMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.position.set(0, 0.5, 0); cube.castShadow = true; // 投射阴影 scene.add(cube); // 动画循环 function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } animate(); // 窗口大小调整 window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); });

4. 阴影优化 (Shadow Optimization)

阴影计算可能会对性能产生影响,尤其是在复杂的场景中。以下是一些优化阴影的方法:

  • 使用适当的阴影贴图大小: 较小的阴影贴图可以提高性能,但会降低阴影质量。

  • 调整阴影相机参数: 优化阴影相机的 near, far, left, right, top, bottom 属性,使其紧密贴合场景中的阴影区域。

  • 使用 ShadowMapViewer: ShadowMapViewer 可以帮助你可视化阴影贴图,从而更容易地调整阴影相机参数。

  • 使用阴影类型: THREE.PCFSoftShadowMap 提供更柔和的阴影,但计算成本更高。THREE.BasicShadowMap 性能最高,但阴影质量较低。

  • 避免不必要的阴影投射: 只让需要投射阴影的物体投射阴影。

5. 常见问题 (Common Issues)

  • 阴影不显示: 确保渲染器的阴影已启用,光源的 castShadow 属性已设置为 true,并且物体的 receiveShadowcastShadow 属性已正确设置。

  • 阴影质量差: 尝试增加阴影贴图的大小,或调整阴影相机参数。

  • 性能问题: 尝试降低阴影贴图的大小,或使用性能更高的阴影类型。

6. 总结 (Summary)

光照和阴影是 Three.js 中创建逼真场景的关键。通过理解不同类型的光照以及如何启用和优化阴影,可以创建更具吸引力和沉浸感的 3D 体验。 记住,良好的光照和阴影设计可以显著提升你 Three.js 项目的视觉效果。


发布者: 作者: 转发
评论区 (0)
U