理解UV坐标
UV坐标是二维纹理映射到三维模型的一组坐标,它们定义了如何将纹理图像的像素映射到模型的表面。在Three.js中,UV坐标与模型的顶点位置坐标一一对应。
UV坐标的范围
- UV坐标的范围从0到1,其中(0,0)代表纹理图像的左下角。
- (1,1)代表纹理图像的右上角。
查看默认UV坐标
Three.js几何体默认生成UV坐标,但有时我们需要自定义这些坐标以满足特定的纹理映射需求。
自定义UV坐标
自定义UV坐标涉及创建一个新的Float32Array
来存储UV值,并将其设置给几何体的.attributes.uv
属性。
实例代码
以下是创建自定义UV坐标并应用到平面几何体上的完整示例:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Three.js Custom UV Coordinates</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";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
// 初始化场景、相机和渲染器
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 controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.update();
// 添加光源
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 2, 4).normalize(); // 将位置向量标准化为方向向量
scene.add(directionalLight);
// 创建几何体
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
0,
0,
0, //顶点1坐标
10,
0,
0, //顶点2坐标
10,
10,
0, //顶点3坐标
0,
10,
0, //顶点6坐标
]);
// 定义三角形的索引
const indices = [
0,
1,
2, // 第一个三角形的顶点索引
2,
3,
0, // 第二个三角形的顶点索引
];
// 将索引添加到几何体中
geometry.setIndex(indices);//
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
// // 自定义UV坐标
const uvs = new Float32Array([
0, 0, // 左下角
1, 0, // 右下角
1, 1, // 右上角
0, 1 // 左上角
]);
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
// 加载纹理图像
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('./img/logo.png');
// 创建材质
const material = new THREE.MeshBasicMaterial({
map: texture,
// color: 0x00ff00, // 绿色
side: THREE.DoubleSide // 确保双面都应用纹理
});
// 创建网格模型
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 设置相机位置
camera.position.z = 5;
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
请将path/to/your/texture.jpg
替换为您的纹理图像的实际路径。此示例创建了一个平面几何体,自定义了其UV坐标,并加载了一个纹理图像,然后应用了这个纹理到模型上。
获取纹理的一部分
如果您只希望将纹理图像的某一部分映射到模型上,您可以调整UV坐标来实现。例如,要映射左下角的四分之一:
javascript
const uvs = new Float32Array([
0, 0, // 左下角开始
0.5, 0, // 向右移动到一半
0.5, 0.5, // 向上移动到一半
0, 0.5 // 回到左上角
]);
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
作业题
自己尝试 换成下面的几何是一个什么情况
javascript
// const geometry = new THREE.BoxGeometry(1, 1, 1); //长方体
// const geometry = new THREE.SphereGeometry(1, 30, 30);//球体
通过这个教程和示例代码,您应该能够理解如何在Three.js中自定义UV坐标,并将其应用于模型以实现精确的纹理映射。您可以根据模型的具体需求调整UV坐标,以映射纹理的不同部分。