在 Three.js 中,环境贴图(envMap
)是一种强大的技术,它可以用来模拟物体表面反射周围环境的效果,这对于实现逼真的 PBR(基于物理的渲染)材质至关重要。以下是关于环境贴图
环境贴图的基本概念
https://threejs.org/examples/?q=envMap#webgl_materials_envmaps_exr
环境贴图是一种立方体贴图,它由六张图片组成,分别代表 3D 空间中的前后、左右、上下方向。这些图片模拟了物体周围 360 度的环境,当应用于材质上时,可以创建出反射效果。
使用 CubeTextureLoader 加载环境贴图
Three.js 提供了CubeTextureLoader
来加载立方体贴图。与普通的TextureLoader
不同,CubeTextureLoader
需要六张图片来构成完整的立方体纹理。
javascript
const cubeTextureLoader = new THREE.CubeTextureLoader();
const path = "path/to/your/cubemap/";
const format = ".jpg"; // 确保所有面使用相同的格式
const urls = [
path + "px" + format,
path + "nx" + format, // x轴正反面
path + "py" + format,
path + "ny" + format, // y轴正反面
path + "pz" + format,
path + "nz" + format, // z轴正反面
];
const textureCube = cubeTextureLoader.load(urls);
应用环境贴图到 PBR 材质
一旦加载了立方体贴图,就可以将其应用到MeshStandardMaterial
或MeshPhysicalMaterial
上,以实现反射效果。
javascript
const material = new THREE.MeshStandardMaterial({
metalness: 1.0,
roughness: 0.2,
envMap: textureCube,
});
环境贴图的反射率
MeshStandardMaterial
提供了envMapIntensity
属性,用来控制环境贴图对材质反射效果的影响程度。
javascript
material.envMapIntensity = 1.0; // 调整环境贴图的强度
场景环境属性
如果场景中的所有模型都需要使用相同的环境贴图,Three.js 允许你通过设置场景的environment
属性来实现这一点,这将影响场景中所有使用 PBR 材质的模型。
javascript
scene.environment = textureCube;
纹理和渲染器颜色空间一致性
为了确保颜色的正确显示,环境贴图的颜色空间应与渲染器的输出编码保持一致。
javascript
renderer.outputEncoding = THREE.sRGBEncoding;
textureCube.encoding = THREE.sRGBEncoding;
完整示例代码
以下是完整的 HTML 示例,展示如何在 Three.js 中加载和应用环境贴图:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Three.js Environment Mapping</title>
<style>
body {
margin: 0;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "https://threejs.org/build/three.module.js",
"three/addons/": "https://threejs.org/examples/jsm/"
}
}
</script>
<script type="module">
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);
// 设置渲染器输出编码为sRGB
renderer.outputEncoding = THREE.sRGBEncoding;
// 创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 加载立方体贴图
const cubeTextureLoader = new THREE.CubeTextureLoader();
const path = "path/to/your/cubemap/";
const format = ".jpg";
const urls = [
path + "px" + format,
path + "nx" + format,
path + "py" + format,
path + "ny" + format,
path + "pz" + format,
path + "nz" + format,
];
const textureCube = cubeTextureLoader.load(urls);
textureCube.encoding = THREE.sRGBEncoding; // 确保颜色空间一致性
// 创建PBR材质并设置环境贴图
const material = new THREE.MeshStandardMaterial({
metalness: 1.0,
roughness: 0.2,
envMap: textureCube,
envMapIntensity: 1.0,
});
// 创建网格模型并添加到场景
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 设置相机位置
camera.position.z = 5;
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
请将path/to/your/cubemap/
替换为您的立方体贴图图片的实际路径。此示例创建了一个立方体,并为其应用了 PBR 材质和环境贴图,模拟了金属效果和反射。