在 Three.js 的魔法世界里,我们已经搭建起了酷炫的 3D 模型,摆弄过各种神奇的灯光,但总觉得少了点什么 ------ 就像给房子刷完墙,却忘了装窗户,看不到外面的风景。别慌!环境贴图(Environment Maps)就是那扇能让你的 3D 场景瞬间 "活" 过来的窗户,它能把整个世界的光影都搬进你的虚拟空间里。
一、什么是环境贴图?
环境贴图就像是给 3D 模型戴上的 "变色眼镜",它会根据周围的环境信息,给模型表面 "染上" 对应的颜色和光影效果。想象一下,你把一颗金属球扔进了北极冰川,它表面就会映出冰川的蓝色和白色;要是把它丢进火山口,那金属球就会反射出炽热的红色和橙色。在 Three.js 里,环境贴图就是通过一张特殊的图片,来模拟这种物体与周围环境的交互效果。
从底层原理来说,环境贴图利用了光线追踪的思想简化版。在真实世界中,光线从四面八方射向物体,再反射进我们的眼睛。而环境贴图则是把整个环境 "拍" 成一张图,当计算物体表面颜色时,就去这张图里找对应的光线信息。这就好比有个 "光影数据库",模型表面的每个点都能从中查到自己该呈现什么颜色和亮度。
二、环境贴图的类型
在 Three.js 的工具箱里,主要有两种常用的环境贴图类型:立方体纹理贴图(CubeTexture)和平铺环境贴图(通常用全景图实现)。
立方体纹理贴图
立方体纹理贴图就像是给 3D 场景套上了一个六面的 "魔盒"。它由六张正方形图片组成,分别对应着上、下、左、右、前、后六个方向。当模型表面需要计算反射光时,Three.js 就会像个勤劳的小蜜蜂,飞到对应的 "面" 上采集光线信息。这种贴图方式非常适合模拟真实的反射效果,比如打造一面锃亮的镜子,或者一辆闪瞎眼的跑车车身。
平铺环境贴图
平铺环境贴图通常使用一张 360 度全景图,就像我们用手机拍摄的那种 "小行星" 全景照片。它把整个环境 "卷" 成一张长方形的图,通过特殊的算法在 3D 空间里展开。这种方式适合营造整体的环境氛围,比如让你的虚拟房间充满海边日落的温暖色调,或者打造一个神秘的星空穹顶。
三、在 Three.js 中使用环境贴图
现在,让我们穿上 "代码战衣",动手在 Three.js 里施展环境贴图的魔法!
1. 准备图片资源
首先,你需要准备好环境贴图的图片。对于立方体纹理贴图,准备六张正方形图片;对于平铺环境贴图,准备一张全景图。把这些图片放在你的项目目录下,方便后续引用。
2. 加载环境贴图
在 JavaScript 代码里,我们要先创建一个加载器来读取图片。Three.js 提供了CubeTextureLoader和TextureLoader分别用于加载立方体纹理和平铺纹理。
javascript
// 加载立方体纹理贴图示例
import { CubeTextureLoader } from 'three';
const cubeTextureLoader = new CubeTextureLoader();
// 假设你的六张图片命名为px.jpg, nx.jpg, py.jpg, ny.jpg, pz.jpg, nz.jpg
const envMap = cubeTextureLoader.load([
'textures/px.jpg',
'textures/nx.jpg',
'textures/py.jpg',
'textures/ny.jpg',
'textures/pz.jpg',
'textures/nz.jpg'
]);
// 加载平铺环境贴图示例
import { TextureLoader } from 'three';
const textureLoader = new TextureLoader();
const envMap = textureLoader.load('textures/panorama.jpg');
3. 应用环境贴图
加载好环境贴图后,我们要把它应用到场景中的物体上。这里以一个简单的球体为例,给它的材质加上环境贴图。
ini
import * as THREE from 'three';
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 加载环境贴图
const cubeTextureLoader = new THREE.CubeTextureLoader();
const envMap = cubeTextureLoader.load([
'textures/px.jpg',
'textures/nx.jpg',
'textures/py.jpg',
'textures/ny.jpg',
'textures/pz.jpg',
'textures/nz.jpg'
]);
// 创建球体几何体
const geometry = new THREE.SphereGeometry(1, 32, 32);
// 创建材质并应用环境贴图
const material = new THREE.MeshStandardMaterial({
roughness: 0.4, // 设置粗糙度,值越小越光滑
metalness: 0.8, // 设置金属度,值越大越像金属
envMap: envMap // 应用环境贴图
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// 设置相机位置
camera.position.z = 5;
// 渲染函数
function animate() {
requestAnimationFrame(animate);
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
在上述代码中,我们创建了一个球体,使用MeshStandardMaterial材质,并通过envMap属性将加载好的环境贴图应用到球体上。同时,通过调整roughness(粗糙度)和metalness(金属度)属性,来控制物体表面对环境贴图的反射效果。粗糙度越低,物体表面越光滑,反射效果越清晰;金属度越高,物体看起来越像金属,反射的环境贴图颜色也会更鲜艳。
四、进阶技巧:让环境贴图更逼真
1. 调整反射强度
除了材质的粗糙度和金属度,我们还可以通过envMapIntensity属性来控制环境贴图的反射强度。它就像是一个 "亮度调节器",数值越大,物体表面反射的环境贴图就越亮。
php
const material = new THREE.MeshStandardMaterial({
roughness: 0.4,
metalness: 0.8,
envMap: envMap,
envMapIntensity: 1.5 // 增强反射强度
});
2. 使用预过滤的环境贴图
为了让反射效果更加真实自然,Three.js 还提供了预过滤的环境贴图技术。它会提前对环境贴图进行一些计算,模拟不同粗糙度下的反射效果。这样在渲染时,就能根据物体的粗糙度快速生成对应的反射画面,大大提升了效率和真实感。
ini
import { PMREMGenerator } from 'three';
const pmremGenerator = new PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
const envMap = pmremGenerator.fromEquirectangular(envMap).texture;
上述代码中,我们使用PMREMGenerator对加载好的环境贴图进行预处理,生成适合不同粗糙度反射的纹理。
五、总结
环境贴图就像是 Three.js 世界里的 "光影魔术师",能让你的 3D 场景从单调变得生动,从平凡走向惊艳。通过掌握立方体纹理和平铺环境贴图的使用方法,调整材质属性,以及运用进阶技巧,你就能打造出媲美电影特效的虚拟世界。下次当你想让模型 "照照镜子",或者给场景换个梦幻背景时,别忘了环境贴图这个神奇的工具!现在,快去用代码创造属于你的光影奇迹吧!
以上从多方面介绍了 Three.js 环境贴图。若你在实践中遇到问题,或想了解环境贴图更多高级玩法,欢迎和我分享。