
在使用 Three.js 创建逼真的 3D 场景时,环境贴图(Environment Map) 和 背景(Background) 是必不可少的两个关键因素。它们可以显著增强渲染效果,特别是在光照、反射和折射方面。
本文将带你系统了解 Three.js 中关于环境贴图与背景的使用方案、类型,并通过 TypeScript 示例一文掌握核心技能。
环境贴图(Environment Map)是一个用来模拟物体反射周围环境的贴图,通常配合 MeshStandardMaterial 或 MeshPhysicalMaterial 来使用。它不仅可以作为反射来源,也能影响材质的高光与镜面反射。
在 Three.js 中,scene.background 与 scene.environment 分别控制:
scene.background: 设置场景的背景图像或颜色;scene.environment: 设置用于物体反射的环境贴图,影响材质的物理光照效果。这两个可以相同也可以不同。
Three.js 支持以下几种主要类型的环境贴图:
由六张面图组成的立方体贴图(通常用于天空盒和反射):
const loader = new THREE.CubeTextureLoader();
const cubeTexture = loader.load([
'px.jpg', 'nx.jpg',
'py.jpg', 'ny.jpg',
'pz.jpg', 'nz.jpg'
]);
scene.environment = cubeTexture;
scene.background = cubeTexture;
通过 RGBELoader 加载 .hdr 文件,效果更逼真,适用于 PBR 材质:
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';
const rgbeLoader = new RGBELoader();
rgbeLoader.load('/env.hdr', (hdrTexture) => {
hdrTexture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = hdrTexture;
scene.background = hdrTexture;
});
注意:HDR 贴图需要开启 PMREM(预过滤的环境贴图)以获得更真实的反射效果,详见下节。
常见于 PNG 或 JPEG 格式的全景图:
const textureLoader = new THREE.TextureLoader();
textureLoader.load('/env.jpg', (texture) => {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = texture;
scene.background = texture;
});
Three.js 推荐使用 PMREMGenerator 来处理环境贴图以提升 PBR 材质效果:
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
const rgbeLoader = new RGBELoader();
rgbeLoader.load('/env.hdr', (hdrTexture) => {
const envMap = pmremGenerator.fromEquirectangular(hdrTexture).texture;
scene.environment = envMap;
scene.background = envMap;
hdrTexture.dispose();
pmremGenerator.dispose();
});
以下是一个完整的 Three.js TypeScript 环境贴图示例:
// src/main.ts
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';
const canvas = document.getElementById('webgl') as HTMLCanvasElement;
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputColorSpace = THREE.SRGBColorSpace;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 1, 3);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// 加载 HDR 贴图作为背景与环境贴图
const pmremGenerator = new THREE.PMREMGenerator(renderer);
new RGBELoader().load('/env.hdr', (hdrTexture) => {
const envMap = pmremGenerator.fromEquirectangular(hdrTexture).texture;
scene.environment = envMap;
scene.background = envMap;
hdrTexture.dispose();
pmremGenerator.dispose();
});
// 添加一个反光球体
const material = new THREE.MeshStandardMaterial({ metalness: 1, roughness: 0 });
const geometry = new THREE.SphereGeometry(1, 64, 64);
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 添加光照(可选)
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 10, 7.5);
scene.add(light);
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
确保 /env.hdr 是一张 Equirectangular 格式的 HDR 图片。
scene.environment 主要影响 MeshStandardMaterial 和 MeshPhysicalMaterial;scene.background 而不设置 scene.environment;PMREMGenerator 获取最佳渲染质量;| 类型 | 用途 | 优点 | 适用 |
|---|---|---|---|
| CubeTexture | 天空盒、基本反射 | 加载简单 | 游戏、低端设备 |
| Equirectangular | 简单 PBR 场景 | 使用广泛 | 全景背景 |
| HDR + PMREM | 高质量 PBR 材质反射 | 效果逼真 | 写实渲染 |