Skip to content

理解UV坐标

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坐标,以映射纹理的不同部分。

Theme by threelab