3.2纹理映射 Three.js 纹理映射详解 纹理 (Textures) 与材质贴图 在 Three.js 中,纹理和材质贴图是为 3D 模型添加细节和视觉效果的关键。它们可以模拟表面的颜色、光泽、粗糙度等属性,从而使模型看起来更逼真。 3.2 纹理映射 (Texture Mapping) 纹理映射是一种将 2D 图像(纹理)“粘贴”到 3D 模型表面的技术。它允许我们为模型添加复杂的细节,而无需增加模型的几何复杂度。简单来说,就是将图像的像素(纹素)映射到 3D 模型的表面。 3.2.1 纹理映射的原理 纹理映射的核心在于建立纹理坐标 (UV 坐标) 与 3D 模型表面顶点之间的对应关系。UV 坐标是 2D 坐标,通常范围在 0 到 1 之间,分别代表纹理图像的水平和垂直方向。
在 Three.js 中,纹理和材质贴图是为 3D 模型添加细节和视觉效果的关键。它们可以模拟表面的颜色、光泽、粗糙度等属性,从而使模型看起来更逼真。
纹理映射是一种将 2D 图像(纹理)“粘贴”到 3D 模型表面的技术。它允许我们为模型添加复杂的细节,而无需增加模型的几何复杂度。简单来说,就是将图像的像素(纹素)映射到 3D 模型的表面。
纹理映射的核心在于建立纹理坐标 (UV 坐标) 与 3D 模型表面顶点之间的对应关系。UV 坐标是 2D 坐标,通常范围在 0 到 1 之间,分别代表纹理图像的水平和垂直方向。
当 Three.js 渲染模型时,它会根据顶点的 UV 坐标从纹理图像中采样颜色,并将该颜色应用于顶点。然后,通过插值计算,可以得到模型表面上每个像素的颜色。
UV 坐标定义了纹理图像如何“包裹”在 3D 模型上。不同的模型可能需要不同的 UV 坐标,以实现所需的纹理映射效果。
标准 UV 坐标: 通常,UV 坐标的原点 (0, 0) 位于纹理图像的左下角,(1, 1) 位于右上角。
UV 展开 (UV Unwrapping): 将 3D 模型的表面“展开”成 2D 平面,并为每个顶点分配 UV 坐标的过程。这是创建良好纹理映射的关键步骤。
UV 映射类型: Three.js 支持多种 UV 映射类型,例如平面映射、立方体映射、球形映射等。
在 Three.js 中,可以使用 THREE.TextureLoader 加载纹理图像,然后将其分配给材质的 map 属性。
代码示例:
// 创建场景、相机和渲染器 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 geometry = new THREE.BoxGeometry(); // 加载纹理 const textureLoader = new THREE.TextureLoader(); const texture = textureLoader.load('path/to/your/texture.jpg'); // 替换为你的纹理图像路径 // 创建材质并将纹理分配给 map 属性 const material = new THREE.MeshBasicMaterial({ map: texture }); // 创建网格 const cube = new THREE.Mesh(geometry, material); scene.add(cube); camera.position.z = 5; // 渲染循环 function animate() { requestAnimationFrame(animate); cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); } animate();
代码详解:
创建场景、相机和渲染器: 这是 Three.js 应用程序的标准设置。
创建立方体: 使用 THREE.BoxGeometry 创建一个立方体几何体。
加载纹理: THREE.TextureLoader 用于异步加载纹理图像。load() 方法接受纹理图像的 URL 作为参数。
创建材质: THREE.MeshBasicMaterial 是一种简单的材质,它不受光照影响,直接显示纹理颜色。将加载的纹理分配给材质的 map 属性,即可将纹理应用于模型。
创建网格: THREE.Mesh 将几何体和材质组合在一起,形成一个可渲染的 3D 对象。
渲染循环: animate() 函数不断更新模型的位置和旋转,并使用 renderer.render() 渲染场景。
THREE.Texture 对象具有许多属性,可以控制纹理的显示方式:
wrapS 和 wrapT: 定义纹理在水平和垂直方向上的重复方式。常用的值包括:
THREE.RepeatWrapping (重复)
THREE.ClampToEdgeWrapping (拉伸边缘像素)
THREE.MirroredRepeatWrapping (镜像重复)
minFilter 和 magFilter: 定义纹理在缩小和放大时的过滤方式。常用的值包括:
THREE.NearestFilter (最近邻插值,像素化效果)
THREE.LinearFilter (线性插值,平滑效果)
THREE.NearestMipmapNearestFilter
THREE.LinearMipmapLinearFilter
repeat: 控制纹理在水平和垂直方向上的重复次数。
offset: 控制纹理在水平和垂直方向上的偏移量。
rotation: 控制纹理的旋转角度。
center: 旋转的中心点
代码示例:
// 设置纹理的重复方式和重复次数 texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping; texture.repeat.set(4, 4); // 设置纹理的过滤方式 texture.minFilter = THREE.LinearFilter; texture.magFilter = THREE.LinearFilter;
除了颜色贴图 (diffuse map),还有许多其他类型的材质贴图可以用于增强模型的视觉效果:
法线贴图 (Normal Map): 模拟表面的凹凸细节,而无需增加模型的几何复杂度。
粗糙度贴图 (Roughness Map): 控制表面的粗糙程度,影响光线的反射方式。
金属度贴图 (Metalness Map): 控制表面的金属程度,影响光线的反射方式。
环境光遮蔽贴图 (Ambient Occlusion Map): 模拟物体表面的阴影效果,增加深度感。
高度贴图 (Height Map) / 位移贴图 (Displacement Map): 实际改变模型的顶点位置,创建真实的凹凸效果。
代码示例 (使用法线贴图):
// 加载法线贴图 const normalTexture = textureLoader.load('path/to/your/normal_map.jpg'); // 创建材质并将法线贴图分配给 normalMap 属性 const material = new THREE.MeshStandardMaterial({ map: texture, // 颜色贴图 normalMap: normalTexture });
纹理映射会消耗 GPU 资源,因此需要注意以下几点:
纹理大小: 使用适当大小的纹理。过大的纹理会浪费内存,过小的纹理会导致图像模糊。
纹理格式: 使用压缩纹理格式 (如 DDS, PVRTC, ETC) 可以减少纹理的内存占用。
Mipmapping: 启用 Mipmapping 可以提高渲染性能,尤其是在观察远处物体时。
纹理重复: 合理使用纹理重复可以减少纹理的数量。
纹理映射是 Three.js 中一项强大的技术,可以为 3D 模型添加丰富的细节和视觉效果。通过理解 UV 坐标、纹理属性和不同类型的材质贴图,可以创建出令人惊叹的 3D 场景。