Skip to content

在 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 材质

一旦加载了立方体贴图,就可以将其应用到MeshStandardMaterialMeshPhysicalMaterial上,以实现反射效果。

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 材质和环境贴图,模拟了金属效果和反射。

Theme by threelab