2.2光照属性


文档摘要

2.2光照属性 Three.js 光照属性详解与实践 2.2 光照属性详解 Three.js 提供了多种光照类型,每种光照类型都有其独特的属性,用于控制光照的颜色、强度、距离、衰减等。下面我们将逐一介绍这些属性。 2.2.1 通用光照属性 所有光照类型都继承了一些通用的属性: (Color):光照的颜色。默认为白色 (0xffffff)。可以使用 对象来设置颜色,例如: (Number):光照的强度。默认为 1。较高的值会使光照更亮。 (String):光照的名称。这对于在场景中识别和管理光照非常有用。 (Boolean):是否投射阴影。默认为 。只有 、 和 支持投射阴影。 (LightShadow):光照的阴影属性。只有当 为 时,此属性才有效。它包含控制阴影质量、分辨率和范围的属性。

2.2光照属性

Three.js 光照属性详解与实践

2.2 光照属性详解

Three.js 提供了多种光照类型,每种光照类型都有其独特的属性,用于控制光照的颜色、强度、距离、衰减等。下面我们将逐一介绍这些属性。

2.2.1 通用光照属性

所有光照类型都继承了一些通用的属性:

  • color (Color):光照的颜色。默认为白色 (0xffffff)。可以使用 THREE.Color 对象来设置颜色,例如:

    const light = new THREE.AmbientLight(0xff0000); // 红色环境光
  • intensity (Number):光照的强度。默认为 1。较高的值会使光照更亮。

    light.intensity = 0.5; // 将光照强度设置为一半
  • name (String):光照的名称。这对于在场景中识别和管理光照非常有用。

    light.name = "My Red Ambient Light";
  • castShadow (Boolean):是否投射阴影。默认为 false。只有 DirectionalLightPointLightSpotLight 支持投射阴影。

    light.castShadow = true; // 允许光照投射阴影
  • shadow (LightShadow):光照的阴影属性。只有当 castShadowtrue 时,此属性才有效。它包含控制阴影质量、分辨率和范围的属性。我们将在后续章节详细讨论阴影属性。

    light.shadow.mapSize.width = 512; // 阴影贴图宽度 light.shadow.mapSize.height = 512; // 阴影贴图高度 light.shadow.camera.near = 0.5; // 阴影相机近平面 light.shadow.camera.far = 500; // 阴影相机远平面

2.2.2 环境光 (AmbientLight)

环境光是一种均匀的光照,它会照亮场景中的所有物体,而不会产生阴影。它通常用于模拟场景中的间接光照。

  • AmbientLight 没有特定的属性,它只继承了通用光照属性,如 colorintensity
const ambientLight = new THREE.AmbientLight(0x404040); // 柔和的灰色环境光 scene.add(ambientLight);

2.2.3 方向光 (DirectionalLight)

方向光模拟来自无限远的光源,例如太阳。它会沿着特定方向照射场景中的所有物体。

  • position (Vector3):光的照射方向。虽然 DirectionalLight 有一个 position 属性,但它实际上定义了光的方向,而不是光的位置。光的方向是从 position 指向场景原点 (0, 0, 0) 的向量。

  • target (Object3D):光照的目标。光的方向是从光的位置指向目标的向量。 默认情况下,目标是场景原点。你可以通过设置 target.position 来更改目标位置。

  • shadow.camera.left, shadow.camera.right, shadow.camera.top, shadow.camera.bottom (Number):用于定义阴影相机的视锥体的边界。调整这些值可以控制阴影的覆盖范围和精度。

  • shadow.camera.near, shadow.camera.far (Number):阴影相机的近平面和远平面。这些值决定了阴影相机的深度范围。

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(1, 1, 1); // 从 (1, 1, 1) 指向原点 directionalLight.target.position.set(0, 0, 0); // 目标是原点 directionalLight.castShadow = true; 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 = -5; directionalLight.shadow.camera.right = 5; directionalLight.shadow.camera.top = 5; directionalLight.shadow.camera.bottom = -5; scene.add(directionalLight); scene.add(directionalLight.target); // 必须将 target 添加到场景中

2.2.4 点光源 (PointLight)

点光源从一个点向所有方向发射光线,类似于灯泡。

  • distance (Number):光照的最大距离。超过此距离,光照强度将变为 0。默认为 0 (无限远)。

  • decay (Number):光照的衰减量。默认为 2。衰减值越高,光照衰减越快。Three.js 使用物理上更精确的平方反比衰减模型。

const pointLight = new THREE.PointLight(0xff0000, 1, 100); // 红色点光源 pointLight.position.set(0, 5, 0); pointLight.distance = 50; pointLight.decay = 2; pointLight.castShadow = true; pointLight.shadow.mapSize.width = 512; pointLight.shadow.mapSize.height = 512; pointLight.shadow.camera.near = 0.5; pointLight.shadow.camera.far = 50; scene.add(pointLight);

2.2.5 聚光灯 (SpotLight)

聚光灯从一个点向一个锥形区域发射光线,类似于手电筒。

  • target (Object3D):聚光灯的目标。光的方向是从光的位置指向目标的向量。 默认情况下,目标是场景原点。

  • distance (Number):光照的最大距离。超过此距离,光照强度将变为 0。默认为 0 (无限远)。

  • angle (Number):光锥的张角,以弧度表示。默认为 Math.PI / 3。

  • penumbra (Number):光锥边缘的模糊程度。值在 0 到 1 之间。默认为 0。

  • decay (Number):光照的衰减量。默认为 2。

  • shadow.camera.near, shadow.camera.far (Number):阴影相机的近平面和远平面。

const spotLight = new THREE.SpotLight(0xffffff, 1); spotLight.position.set(0, 10, 0); spotLight.target.position.set(0, 0, 0); spotLight.angle = Math.PI / 6; spotLight.penumbra = 0.2; spotLight.distance = 50; spotLight.decay = 2; spotLight.castShadow = true; spotLight.shadow.mapSize.width = 1024; spotLight.shadow.mapSize.height = 1024; spotLight.shadow.camera.near = 0.5; spotLight.shadow.camera.far = 50; scene.add(spotLight); scene.add(spotLight.target);

2.2.6 半球光 (HemisphereLight)

半球光是一种模拟天空光照的光源。它从上方照射的光线颜色和从下方照射的光线颜色不同。

  • skyColor (Color):从上方照射的光线的颜色。默认为白色 (0xffffff)。

  • groundColor (Color):从下方照射的光线的颜色。默认为白色 (0xffffff)。

  • intensity (Number):光照的强度。默认为 1。

const hemisphereLight = new THREE.HemisphereLight(0xaaaaaa, 0x444444, 1); hemisphereLight.position.set(0, 10, 0); scene.add(hemisphereLight);

2.2.7 区域光 (RectAreaLight)

区域光是一种模拟矩形区域光源的光源,例如荧光灯管或窗口。注意:RectAreaLight 需要 RectAreaLightUniformsLib 才能正常工作,并且只能与 MeshStandardMaterialMeshPhysicalMaterial 一起使用。

  • width (Number):光的宽度。默认为 1。

  • height (Number):光的高度。默认为 1。

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.3 阴影属性详解

阴影是光照的重要组成部分,它能增加场景的真实感。只有 DirectionalLightPointLightSpotLight 支持投射阴影。

  • shadow.mapSize.width, shadow.mapSize.height (Number):阴影贴图的宽度和高度。较高的值会产生更清晰的阴影,但会消耗更多的资源。常用的值有 512, 1024, 2048。

  • shadow.camera.near, shadow.camera.far (Number):阴影相机的近平面和远平面。这些值决定了阴影相机的深度范围。

  • shadow.bias (Number):一个小的偏移量,用于解决阴影自遮挡问题。默认为 0。

  • shadow.normalBias (Number):沿着物体法线的偏移量,用于解决阴影自遮挡问题。默认为 0。

  • shadow.radius (Number):用于模糊阴影边缘的半径。仅在使用 PCFSoftShadowMap 时有效。默认为 1。

阴影类型

Three.js 提供了几种不同的阴影类型:

  • THREE.BasicShadowMap: 最简单的阴影贴图,性能最高,但质量最差。

  • THREE.PCFShadowMap: 使用 Percentage Closer Filtering (PCF) 来平滑阴影边缘。

  • THREE.PCFSoftShadowMap: 使用 PCF 的更柔和的版本,产生更平滑的阴影,但性能略低。

  • THREE.VSMShadowMap: 使用 Variance Shadow Maps (VSM),可以产生非常柔和的阴影,但可能会出现光渗漏问题。

可以通过设置渲染器的 shadowMap.type 属性来选择阴影类型:

renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap;

2.4 代码实践:调整光照属性

以下是一个完整的代码示例,演示如何调整各种光照属性:

import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; // 初始化场景、相机和渲染器 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true }); 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); // 设置相机位置 camera.position.z = 5; // 创建一个立方体 const geometry = new THREE.BoxGeometry(); const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(geometry, material); cube.castShadow = true; cube.receiveShadow = true; scene.add(cube); // 创建一个地面 const planeGeometry = new THREE.PlaneGeometry(10, 10); const planeMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff }); const plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = -Math.PI / 2; plane.receiveShadow = true; scene.add(plane); // 添加环境光 const ambientLight = new THREE.AmbientLight(0x404040); scene.add(ambientLight); // 添加方向光 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 = 500; scene.add(directionalLight); // 添加点光源 const pointLight = new THREE.PointLight(0xff0000, 1, 10); pointLight.position.set(0, 2, 0); pointLight.castShadow = true; pointLight.shadow.mapSize.width = 512; pointLight.shadow.mapSize.height = 512; pointLight.shadow.camera.near = 0.5; pointLight.shadow.camera.far = 10; scene.add(pointLight); // 添加聚光灯 const spotLight = new THREE.SpotLight(0xffffff, 1); spotLight.position.set(0, 5, 0); spotLight.target.position.set(0, 0, 0); spotLight.castShadow = true; spotLight.shadow.mapSize.width = 1024; spotLight.shadow.mapSize.height = 1024; spotLight.shadow.camera.near = 0.5; spotLight.shadow.camera.far = 20; scene.add(spotLight); scene.add(spotLight.target); //添加半球光 const hemisphereLight = new THREE.HemisphereLight(0xaaaaaa, 0x444444, 1); hemisphereLight.position.set(0, 5, 0); scene.add(hemisphereLight); // 添加区域光 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 ); // 动画循环 function animate() { requestAnimationFrame(animate); // 旋转立方体 cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); controls.update(); } animate();

2.5 光照属性关系图

以下是一个使用 mermaid 语法绘制的光照属性关系图:

结论

理解和掌握 Three.js 中的光照属性对于创建逼真的场景至关重要。通过调整颜色、强度、距离、衰减等属性,你可以创造出各种各样的光照效果,从而提升你的 Three.js 应用的视觉体验。 此外,合理使用阴影也能增加场景的深度和真实感。记住,光照和阴影是相辅相成的,需要仔细调整才能达到最佳效果。 通过本文的学习,你应该能够熟练地运用 Three.js 中的各种光照类型,并根据需要调整其属性,从而创造出令人惊叹的 3D 场景。


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