系列文章目录
Three.js 快速入门教程【一】开启你的 3D Web 开发之旅
Three.js 快速入门教程【二】透视投影相机
Three.js 快速入门教程【三】渲染器
Three.js 快速入门教程【四】三维坐标系
Three.js 快速入门教程【五】动画渲染循环
Three.js 快速入门教程【六】相机控件 OrbitControls
Three.js 快速入门教程【七】常见几何体类型
Three.js 快速入门教程【八】常见材质类型
Three.js 快速入门教程【九】光源类型
Three.js 快速入门教程【十】常见的纹理类型
Three.js 快速入门教程【十一】天空盒的多种实现方式
Three.js 快速入门教程【十二】外部模型加载
Three.js 快速入门教程【十三】外部模型加载后常见的处理操作
Three.js 快速入门教程【十四】使用Stats.js监控渲染帧率和性能优化
Three.js 快速入门教程【十五】交互神器DragControls使用详解,实现对物体或模型拖拽
Three.js 快速入门教程【十六】调试神器 gui.js使用详解,可视化面板控制场景参数提高开发效率
Three.js 快速入门教程【十七】射线拾取模型——射线与射线投射器Raycaster介绍
Three.js 快速入门教程【十八】射线拾取模型——鼠标点击屏幕选中模型或物体
Three.js 快速入门教程【十九】CSS2D渲染器介绍,实现场景中物体或设备标注标签信息
Three.js 快速入门教程【二十】三维模型优化实战:使用gltf-pipeline与Draco对模型进行压缩,提高加载速度和流畅性
Three.js 快速入门教程【二十一】CSS3D渲染器(CSS3DRenderer、CSS3DObject 、CSS3DSprite)介绍,实现场景中物体标注标签信息
Three.js 快速入门教程【二十二】动画神器Tween.js使用指南
一、前言
在3D场景中,光源是赋予物体材质灵魂的关键,它不仅赋予场景真实感,还能引导用户的注意力,营造出独特的氛围。本文将深入探讨 Three.js 中各种类型的光,以及如何运用它们来打造令人惊叹的 3D 场景。
二、常见光的类型
1、环境光(AmbientLight)
环境光为整个场景提供均匀的背景照明,它没有特定的方向,就像在一个充满柔和光线的房间里,每个角落都被均匀照亮。环境光的作用在于提供基本的亮度,让场景中的物体可见。然而,由于它没有方向,不会产生明显的阴影,所以通常需要与其他类型的光结合使用,以增加场景的层次感和真实感。
特性
均匀照亮所有物体表面,没有方向,无阴影支持
构造函数
new THREE.AmbientLight(color : Integer, intensity : Float);
参数说明
- color:十六进制颜色值(默认0xffffff),可选参数
- intensity:光照强度,范围无上限(默认1),可选参数
示例代码
// 创建一个颜色为白色(0xffffff),光照强度0.5的环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
最佳实践
配合其他光源使用,避免纯黑阴影
2、点光源(PointLight)
点光源从一个特定的点向各个方向发射光线,类似于现实生活中的灯泡。点光源的光线强度会随着距离的增加而衰减,其效果可以模拟局部的照明,比如房间里的吊灯。
特性
360°全方位照射,有方向,有阴影,会衰减
构造函数
new THREE.PointLight(color : Integer, intensity : Float,distance: Float,decay: Float);
参数说明
- color:十六进制颜色值(默认0xffffff),可选参数
- intensity:光照强度,范围无上限(默认1),可选参数
- distance:光照有效距离(默认0无限),可选参数
- decay:衰减系数(推荐2实现物理衰减),可选参数
示例代码
// 创建一个点光源,颜色为白色(0xffffff),强度为 1,有效距离为 100
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
// 设置点光源的位置
pointLight.position.set(5, 5, 5);
// 将点光源添加到场景中
scene.add(pointLight);
应用场景
- 在室内场景(如客厅、餐厅、酒店大堂)中模拟吊灯
- 游戏中的魔法物品发光
- 在工业场景(如工厂车间、机械维修场景)中机器设备照明等
3、聚光灯(SpotLight)
聚光灯从一个点向特定方向发射出一个锥形的光线区域,类似于手电筒或舞台上的聚光灯,它具有很强的方向性和聚焦性。聚光灯的优势在于能够精确控制光线的方向和范围,可以用来突出场景中的特定物体或区域,营造出戏剧性的效果
特性
舞台灯光效果,很强方向性、聚焦性
构造函数
new THREE.SpotLight( color : Integer, intensity : Float, distance : Float, angle : Float, penumbra : Float, decay : Float )
参数说明
- color:十六进制颜色值(默认0xffffff),可选参数
- intensity:光照强度,范围无上限(默认1),可选参数
- distance:光照有效距离(默认0无限),可选参数
- angle:聚光灯锥体的最大角度(以弧度为单位),取值范围是 0 到 Math.PI / 2(默认Math.PI / 3),可选参数
- penumbra:聚光灯锥体的衰减程度,取值范围是 0 到 1(默认0),值越大,聚光灯边缘越模糊,可选参数
- decay:衰减系数(推荐2实现物理衰减)(默认值为 1),可选参数
示例代码
// 创建一个颜色为白色、强度为 1、射程为 100、圆锥角为 45 度、衰减系数为 0.1 到 0.9 的聚光灯
const spotLight = new THREE.SpotLight(0xffffff, 1, 100, Math.PI / 4, 0.1, 0.9);
spotLight.position.set(0, 10, 0); // 设置聚光灯的位置
spotLight.target.position.set(0, 0, 0); // 设置聚光灯的目标位置
scene.add(spotLight); // 将聚光灯添加到场景中
应用场景
聚光灯的参数较多,通过调整这些参数可以精确控制其光照范围、阴影效果等,常用于突出场景中的特定物体或区域,例如:
- 舞台表演演员聚焦
- 展厅展品展示
- 游戏中目标标记
- 建筑轮廓突出
4、平行光(DirectionalLight)
平行光从一个方向发射出平行的光线,类似于太阳光线照射到地球上的效果。平行光的光线没有衰减,所有物体在平行光的照射下都会受到相同强度的光照。适用于模拟太阳光等远距离光源。由于其光线平行,产生的阴影也是平行的,常用于室外场景的照明。
特性
模拟太阳光,无衰减,光照强度相同
构造函数
new THREE.DirectionalLight( color : Integer, intensity : Float)
参数说明
- color:十六进制颜色值(默认0xffffff),可选参数
- intensity:光照强度,范围无上限(默认1),可选参数
示例代码
// 创建一个平行光,颜色为白色(0xffffff),强度为 0.8
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
// 设置平行光的方向,这里将方向向量归一化
directionalLight.position.set(-1, 1, 0).normalize();
// 将平行光添加到场景中
scene.add(directionalLight);
应用场景
- 在构建户外自然场景(如森林、草原、海滩、山脉等)时,平行光可完美模拟太阳光,模拟不同的天气状况
- 建筑外观展示
- 产品外观展示
5、矩形区域光(RectAreaLight)
矩形区域光可以模拟像大型窗户透进来的光线或者电影片场的柔光灯箱等具有矩形形状的光源。
特性
矩形分布,光照强度均匀
构造函数
new THREE.RectAreaLight( color : Integer, intensity : Float, width : Float, height : Float )
参数说明
- color:十六进制颜色值(默认0xffffff),可选参数
- intensity:光照强度,范围无上限(默认1),可选参数
- width:矩形区域光的宽度,可选参数
- height:矩形区域光的高度,可选参数
示例代码
// 需要导入RectAreaLightUniformsLib
import { RectAreaLightUniformsLib } from 'three/addons/libs/RectAreaLightUniformsLib.js';
RectAreaLightUniformsLib.init();
const rectLight = new THREE.RectAreaLight(
0xffffff,
5, // 强度
3, // 宽度
2 // 高度
);
rectLight.position.set(0, 3, 0);
应用场景
- 室内场景:模拟窗户透进来的自然光,使室内场景更加逼真。比如在一个房间模型中,在窗户的位置放置一个矩形区域光,就能很好地模拟阳光照进房间的效果。
- 影视片场模拟:在创建影视片场相关的 3D 场景时,矩形区域光可以模拟柔光灯箱等设备发出的光线,营造出专业的拍摄灯光环境。
- 商业展示场景:在展示商品的场景中,使用矩形区域光可以突出展示商品,并且通过调整光的颜色和强度来营造不同的氛围,吸引观众的注意力。
二、通用属性
不同类型的光虽然有各自独特的特点,但也存在一些通用属性,部分构造函数的入参也可通过通用属性来设置或修改
属性名称 | 类型 | 说明 | 默认值 |
---|---|---|---|
color | THREE.Color | 光的颜色,它以十六进制值的形式表示 | 0xffffff |
intensity | Float | 光的强度,它是一个浮点数。强度值越大,光就越亮;反之,光就越暗 | 1 |
position | THREE.Vector3 对象 | 用于指定光在三维空间中的位置 | (0, 0, 0) |
castShadow | Boolean | 控制光是否能投射阴影 | false |
visible | Boolean | 用于控制光是否可见。当设置为 false 时,光将不会对场景产生照明效果,就好像它被关闭了一样;设置为 true 时光正常工作 | true |
name | String | 为光指定一个名称,方便在代码中识别和引用 | ‘’ |
matrix | THREE.Matrix4 对象 | 光的本地变换矩阵 | 单位矩阵(一个 4x4 的矩阵,对角线上元素为 1,其余为 0) |
matrixWorld | HREE.Matrix4 对象 对象 | 在世界坐标系中的变换矩阵 | 单位矩阵 |
up | THREE.Vector3 对象 | 定义光的上方向,用于确定光的朝向 | (0, 1, 0) |
示例
const pointLight = new THREE.PointLight();//创建一个点光源
pointLight.color.set(0xff0000); // 将点光源颜色设置为红色
pointLight.intensity = 0.5; // 将点光源光强度设置为 0.5
pointLight.position.set(2, 3, 1); // 设置点光源的位置
pointLight.castShadow = true; // 允许点光源投射阴影
pointLight.visible = false; // 隐藏点光源
scene.add(pointLight );//点光源添加到场景中
二、显示物体阴影
以上讲述的五个灯光类型除了环境光其他都能让物体产生阴影,想让物体在虚拟场景中呈阴影,需要四个核心环节协同工作。
1、启用渲染器阴影支持
const renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true; // 必须开启
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 柔化阴影边缘
2、 配置光源投射阴影
// 以点光源为例
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.castShadow = true; // 光源投射阴影
pointLight.position.set(5, 8, 3);
3、 物体投射阴影
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(1),
new THREE.MeshStandardMaterial()
);
sphere.castShadow = true; // 物体投射阴影
4. 地面接收阴影
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(20, 20),
new THREE.MeshPhongMaterial({ color: 0x808080 })
);
floor.receiveShadow = true; // 地面接收阴影
floor.rotation.x = -Math.PI / 2;
效果:
三、开启灯光辅助
开启灯光辅助可以帮助开发者直观地了解场景中灯光的位置、方向和范围,从而更方便地对光照效果进行调试和优化。如上图开启点光源辅助所呈现的效果,下面为你详细介绍如何为不同类型的灯光开启辅助
1、点光源(PointLight)
// 创建点光源
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(2, 2, 2);
scene.add(pointLight);
// 创建点光源辅助对象
const pointLightHelper = new THREE.PointLightHelper(pointLight, 1);
scene.add(pointLightHelper);
上述代码中,创建了一个点光源并设置其位置,然后使用 THREE.PointLightHelper 创建辅助对象,第二个参数 1表示辅助对象的大小,最后将辅助对象添加到场景中。
2、聚光灯(SpotLight)
// 创建聚光灯
const spotLight = new THREE.SpotLight(0xffffff, 1, 100, Math.PI / 6);
spotLight.position.set(0, 5, 0);
spotLight.target.position.set(0, 0, 0);
scene.add(spotLight);
scene.add(spotLight.target);
// 创建聚光灯辅助对象
const spotLightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotLightHelper);
3、平行光(DirectionalLight)
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// 创建平行光辅助对象
const directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight, 1);
scene.add(directionalLightHelper);
4、矩形区域光(RectAreaLight)
// 初始化矩形区域光库
THREE.RectAreaLightUniformsLib.init();
// 创建矩形区域光
const rectLight = new THREE.RectAreaLight(0xffffff, 5, 3, 2);
rectLight.position.set(0, 2, 0);
rectLight.lookAt(0, 0, 0);
scene.add(rectLight);
// 创建矩形区域光辅助对象
const rectLightHelper = new THREE.RectAreaLightHelper(rectLight);
rectLight.add(rectLightHelper);
五、总结
在 Three.js 中,光的运用是打造出色 3D 场景的关键因素之一。通过了解和掌握不同类型光的特点和使用方法,以及光与材质的交互原理,我们可以创造出更加真实、生动和富有吸引力的虚拟世界。无论是简单的演示场景还是复杂的游戏环境,合适的光照设置都能为作品增色不少。
更多three.js入门知识点请关注该系列教程后续的更新。