本章主要学习知识点
- 了解环境光贴图,并练习如何使用
- 了解什么事精灵模型
- 使用精灵模型实现标注场景贴图
- 掌握如何使用精灵模型模拟粒子移动
光源环境贴图
光源环境贴图可以理解为一种让物体表面「反射周围环境」的光照技术。它通过一张(或一组)贴图模拟真实世界中物体对周围环境(如天空、地面、建筑)的光线反射效果,使3D场景更逼真。
你可以想象你的手里有一个金属球,把它放在草地上时,球的表面会反射周围的草地、天空和树木。环境贴图就是给这个金属球「贴」上一组周围环境的图片,让它的表面能反射出这些画面。
两种实现环境贴图的方式
立方体贴图 (CubeMap)- 用6张图片分别表示上下、前后、左右六个方向的环境(类似一个立方体盒子包裹住场景)。
HDR贴图 (高动态范围图)- HDR贴图能存储更丰富的亮度和颜色信息,适合模拟真实光照环境。
环境贴图与光源的关系
- 作为环境光AmbientLight的补充
- 环境光只能均匀照亮物体,而环境贴图能根据物体表面角度动态反射周围颜色,增强真实感
- 例如:金属材质在环境贴图下会有动态高光,而纯环境光只能让物体呈现单一颜色
- 间接光源效果
- 环境贴图可以被视为一种「间接光源」。例如,贴图中的明亮区域(如天空)会让物体表面更亮,暗部区域(如地面阴影)则减少反射亮度
上手实践下
创建一个立方体纹理贴图加载器用来加载图片素材
const textureCube = new THREE.CubeTextureLoader()
.setPath('texture/environmentMaps/1/')
.load([
'px.jpg','nx.jpg','py.jpg','ny.jpg','pz.jpg','nz.jpg'
])
导入模型,并设置材质为立方体纹理贴图,贴图强度为1
// 设置子对象的材质的环境贴图
child.material.envMap = textureCube;
// 设置子对象的材质的环境贴图强度
child.material.envMapIntensity = 1;
child.material.needsUpdate = true;
旋转模型,我们就能在玻璃中看到环境贴图的背景,这里要注意添加光源哦,光源负责直接照明,环境贴图负责间接反射。
模拟太阳光和阴影
在three.js中模拟太阳光和阴影主要依靠平行光(DirectionalLight) 和阴影系统配合实现
太阳光的本质——平行光
平行光可以理解为无限远的光源,就像现实中的太阳光,所有光线都朝同一个方向平行照射。它的特点如下:
- 可以设置照射方向(如
position.set(0, 100, 0)表示从天空垂直向下照 - 能产生清晰的投影(比如树木在地面的影子)
总结阴影生效的4个关键设置
1.开启渲染器阴影计算
renderer.shadowMap.enabled = true; //告诉Three.js 要渲染阴影
2.光源投射阴影
sunLight.castShadow = true; //让平行光产生阴影
3.物体投射/接收阴影
cube.castShadow = true; //立方体能投射影子
plane.receiveShadow = true; //地面能接收影子
4.优化阴影质量
sunLight.shadow.mapSize.width = 2048; //阴影贴图分辨率越高越清晰
sunLight.shadow.camera.near = 5; //阴影计算最近距离
sunLight.shadow.camera.far = 200; //阴影计算最远距离
这里我做了一个示例,调整平行光位置,阴影同步改变
值得注意的点
- 支持材质:
MeshStandardMaterial、MeshPhongMaterial等(如金属车身材质) - 不支持材质:
MeshBasicMaterial(基础材质无光影效果)
精灵模型Sprite
精灵模型(Sprite) 可以理解为一种特殊的“二维贴纸”,它能将图片或文字贴在3D场景中,但始终正对摄像机,就像现实中的广告牌或舞台演员始终面向观众一样。
精灵模型有以下几个特点
- 永远面向你
无论你如何旋转3D场景,精灵模型始终正对屏幕,就像一张悬浮的2D纸片 - 轻量级性能
相比复杂3D模型,精灵仅需一个平面和一张贴图,适合大量使用(如雨滴、星星等粒子效果) - 动态内容支持
可以用图片、Canvas绘制的文字(如标签)或动态视频作为贴图,灵活性高
适用场景
-
信息标签
给3D模型添加浮动文字说明(如设备名称、温度数值) -
粒子效果
- 雨雪效果:用大量雨滴/雪花贴图的精灵模拟天气
- 火焰烟雾:通过半透明贴图实现动态粒子
-
UI元素
在3D场景中叠加按钮、指示图标,且不受视角影响 -
性能优化场景
当需要渲染数千个相同物体(如森林中的树木)时,用精灵代替3D模型可大幅提升性能。
创建一个简单的精灵模型
const spriteMaterial = new THREE.SpriteMaterial({
color: '#373737',
rotation: Math.PI / 4 // 旋转精灵
});
const sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(5, 5, 1);
scene.add(sprite);
需要注意的点
-
透明贴图处理
若使用PNG透明贴图,需设置材质属性transparent: true,避免出现黑边 -
性能优化技巧
- 大量重复精灵可使用
THREE.InstancedMesh批量渲染 - 控制贴图分辨率,避免过大导致内存浪费
- 大量重复精灵可使用
-
大小控制
通过.scale属性调整精灵尺寸,但透视相机会导致距离越远精灵越小(可通过正交相机规避)
精灵模型标注场景贴图
精灵模型(Sprite)标注场景贴图 可以理解为一种“智能标签”技术,它能将文字或图标贴在3D场景中的特定位置,并且始终正对屏幕,就像现实中的指示牌一样。
我们通过textureLoader加载纹理贴图,并将贴图应用在精灵材质上
const textureLoader = new THREE.TextureLoader();
const spriteMap = textureLoader.load('texture/environmentMaps/0/pz.jpg');
const spriteMaterial = new THREE.SpriteMaterial({ map: spriteMap });
const sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(1, 1, 1);
sprite.position.set(0, 2 + 1/2, 0);
scene.add(sprite);
需要注意的是,如果我们加载的贴图为png,则需要开启支持透明背景 transparent: true
精灵模型模拟粒子移动
设置精灵模型材质贴图,用来模拟雨滴
const texture = new THREE.TextureLoader().load('texture/particles/8.png')
const spriteMaterial = new THREE.SpriteMaterial({map: texture})
批量创建精灵,并随机它们的位置
const group = new THREE.Group()
for(let i = 0; i < 1000; i++) {
const sprite = new THREE.Sprite(spriteMaterial)
group.add(sprite)
sprite.scale.set(0.5, 0.5, 0.5)
sprite.position.set(
1000*(Math.random()-0.5),
600*Math.random(),
1000*(Math.random()-0.5)
)
scene.add(group)
}
改变精灵模型的位置,模拟下雨的赶脚
const clock = new THREE.Clock();
function loop() {
const t = clock.getDelta();
group.children.forEach((sprite, index) => {
// 将精灵的y坐标减去20*t
sprite.position.y -= 60*t
// 如果精灵的y坐标小于-100
if(sprite.position.y < -100) {
// 将精灵的y坐标设置为400
sprite.position.y = 400;
}
})
requestAnimationFrame(loop)
}
效果如下