前言
本文将介绍 Three.js 中的 UV 映射,包括 UV 映射的概念、与顶点位置的关系和区别,以及如何在 Geometry 中设置 UV 坐标。
uv映射
什么是UV映射?
UV映射是一种将二维纹理映射到三维模型表面的技术。在这个过程中,3D模型上的每个顶点都会被赋予一个二维坐标(U, V)。U和V分别表示纹理坐标的水平和垂直方向。这些坐标用于将纹理图像上的像素与模型表面上的点进行对应。通过UV映射,我们可以在模型上精确地控制纹理的位置和方向。
纹理贴图UV坐标范围
顶点UV坐标可以在0~1.0之间任意取值,纹理贴图左下角对应的UV坐标是(0,0)
,右上角对应的坐标(1,1)
。
UV坐标与顶点位置的关系和区别
顶点位置(Position)表示3D模型中每个顶点的空间坐标(x, y, z)。
UV坐标则表示该顶点在纹理上的二维坐标(U, V)。
顶点位置用于确定模型在场景中的形状,而UV坐标用于确定纹理在模型上的分布。
两者之间的主要区别在于:
- 顶点位置是三维坐标,描述了一个顶点在三维空间中的位置。
- UV坐标是二维坐标,描述了一个顶点在纹理图像上的位置。
如何设置uv坐标
- 首先我们创建两个
平面缓冲几何体
.不同的是一个使用PlaneGeometry
创建,另一个使用BufferGeometry
创建。
let uvTexture = new THREE.TextureLoader().load("./texture/uv_grid_opengl.jpg");
// 创建平面几何体
const planeGeometry = new THREE.PlaneGeometry(2, 2);
console.log(planeGeometry);
// // 创建材质
const planeMaterial = new THREE.MeshBasicMaterial({
map: uvTexture,
});
// // 创建平面
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
// // 添加到场景
scene.add(planeMesh);
planeMesh.position.x = -3;
// 创建平面几何体
const geometry = new THREE.BufferGeometry();
// 使用索引绘制
const vertices = new Float32Array([
-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0,
]);
// 创建顶点属性
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
// 创建索引
const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
// 创建索引属性
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// 创建材质
const material = new THREE.MeshBasicMaterial({
map: uvTexture,
});
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);
plane.position.x = 3;
得到:
为什么我们使用不同的方式创建了两个平面几何体并给它们添加了相同的纹理图片,呈现出来的结果却不相同呢?
将两个平面几何体打印出来,对比可以看到:
PlaneGeometry
带有uv坐标
,BufferGeometry
没有uv坐标
。
没有uv坐标便不能定位到纹理图像上的位置。所以BufferGeometry
创建的平面几何体没有渲染出纹理图像。
那应该如何给BufferGeometry
添加uv坐标
呢?
- 给
BufferGeometry
添加uv坐标
// 设置uv坐标
const uv = new Float32Array([
0,0,
1,0,
1,1,
0,1, // 正面
]);
// 创建uv属性
geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));
这时:
对比两个平面几何体可以看到,此时都已有uv坐标
:
对于BufferGeometry
创建的几何体可以自定义uv坐标
。例如:我们给BufferGeometry
创建的平面几何体指定uv坐标为:
// 设置uv坐标
const uv = new Float32Array([
0,0,
1,0,
1,1,
0,0, // 正面
]);
// 创建uv属性
geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));
这时:
设置的最后一个uv坐标是:0,0表示取纹理图片(0,0)处的颜色。
总结
对于uv坐标
,需要记住的是:UV坐标用于确定纹理在模型上的分布。对于BufferGeometry
创建的几何体,需要自定义uv坐标
。如有错误之处,欢迎大家指出,谢谢大家了。