You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js:能否为PlaneGeometry的特定面加载独立纹理?

解决方案:为PlaneGeometry的特定三角面单独映射纹理

你遇到的核心问题是默认的UV坐标是为整个PlaneGeometry生成的,所以即使给不同面分配了带纹理的材质,纹理也会基于全局UV被拉伸/重复到所有面上。要实现给特定三角面贴独立纹理,你需要为这些目标面单独设置UV坐标,配合多材质系统来完成。

下面是针对你的需求的可行实现方案,基于你提供的r87版本Three.js:

完整代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Plane Geometry Specific Face Texture</title>
    <meta charset="utf-8">
    <style>
        body { font-family: Monospace; background-color: #f0f0f0; margin: 0px; overflow: hidden; }
    </style>
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
    <script>
        var camera, scene, renderer, geometry, materials, mesh;

        init();
        animate();

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
            camera.position.z = 500;
            scene.add(camera);

            // 几何参数设置
            var thumbnail_width = 32;
            var thumbnail_height = 32;
            var width_segments = 10;
            var height_segments = 10;
            var plane_geometry_width = width_segments * thumbnail_width;
            var plane_geometry_height = height_segments * thumbnail_height;

            geometry = new THREE.PlaneGeometry(plane_geometry_width, plane_geometry_height, width_segments, height_segments);

            // 1. 加载纹理并配置
            var texture = new THREE.TextureLoader().load("image_small/item_1.png");
            texture.flipY = true; // 修正Three.js默认的Y轴翻转问题
            texture.needsUpdate = true;

            // 2. 创建多材质:索引0是纹理材质,1、2是颜色材质
            materials = [
                new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({ color: 0x00ff00, side: THREE.DoubleSide })
            ];

            // 3. 为目标面分配材质索引并修改UV
            var targetFaceIndices = [0, 1]; // 这里指定你要贴纹理的三角面索引(比如前2个三角面)
            var uvs = geometry.faceVertexUvs[0];

            for (var i = 0; i < geometry.faces.length; i++) {
                if (targetFaceIndices.includes(i)) {
                    // 给目标面分配纹理材质索引
                    geometry.faces[i].materialIndex = 0;
                    // 修改该面的UV坐标,让纹理完整显示在这个三角面上
                    // 三角面的三个顶点对应纹理的(0,0), (0,1), (1,0) 或 (0,1), (1,1), (1,0),根据面的朝向调整
                    if (i % 2 === 0) {
                        uvs[i][0].set(0, 0);
                        uvs[i][1].set(0, 1);
                        uvs[i][2].set(1, 0);
                    } else {
                        uvs[i][0].set(0, 1);
                        uvs[i][1].set(1, 1);
                        uvs[i][2].set(1, 0);
                    }
                } else {
                    // 其他面分配颜色材质索引(按你的需求循环)
                    geometry.faces[i].materialIndex = (i % 3) === 0 ? 1 : 2;
                }
            }

            // 4. 标记几何体UV需要更新,按材质索引排序优化渲染
            geometry.uvsNeedUpdate = true;
            geometry.sortFacesByMaterialIndex();

            // 创建网格并添加到场景
            mesh = new THREE.Mesh(geometry, materials);
            scene.add(mesh);

            // 渲染器设置
            renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
        }

        function animate() {
            requestAnimationFrame(animate);
            render();
        }

        function render() {
            renderer.render(scene, camera);
        }
    </script>
</body>
</html>

关键要点解释

  1. UV坐标修改:
    PlaneGeometry默认的UV是将整个纹理映射到整个平面,每个三角面的UV只对应纹理的一小部分。我们需要手动修改目标面的UV,让三个顶点的UV坐标覆盖(0,0)到(1,1)的范围,这样纹理就能完整显示在单个三角面上。

  2. 材质索引分配:
    明确给需要贴纹理的面设置materialIndex = 0(对应我们的纹理材质),其他面分配颜色材质的索引,确保渲染时每个面使用正确的材质。

  3. 几何体更新标记:
    修改UV后必须设置geometry.uvsNeedUpdate = true,让Three.js重新计算UV数据。sortFacesByMaterialIndex()可以让相同材质的面批量渲染,提升性能。

为什么之前的尝试没生效?

  • UPDATE方案:仅设置纹理重复但未修改UV,纹理还是基于全局UV重复到整个平面,每个面依然显示重复后的纹理片段,无法实现单个面的独立纹理。
  • UPDATE2方案:将所有面的materialIndex设为0,导致所有面都使用纹理材质,同时修改了所有面的UV,不符合你只给特定2个三角面贴纹理的需求。

内容的提问来源于stack exchange,提问作者mrgloom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:01:56