Three.js中ExtrudeGeometry纹理映射异常问题求助
解决Three.js ExtrudeGeometry纹理UV映射异常问题
这个问题我之前处理过不少——ExtrudeGeometry默认的UV生成逻辑确实没法很好适配这种带倾斜边的形状,尤其是侧面的映射,完全是按挤出路径的轴向硬套的,自然会乱。下面给你一套可行的手动修正UV的方案:
问题根源
ExtrudeGeometry默认的UV计算是把形状的平面(正面/背面)按形状的边界框分配UV,而挤出的侧面则简单把挤出方向作为T轴、形状边的轴向作为S轴,完全没考虑边的倾斜角度和实际长度,所以斜向的边就会出现拉伸、错位的情况。
解决方案:手动重新计算UV
我们需要遍历几何体的所有面,针对挤出侧面重新计算UV,让纹理沿着形状的边包裹,挤出方向保持统一的T轴映射。
步骤1:计算形状各边的长度
先算出你定义的Shape每条边的实际长度,后续用来分配UV的S轴比例:
// 获取Shape的所有顶点(边的端点) const edges = shape.getPoints(); let edgeLengths = []; let totalLength = 0; // 计算每条边的长度和总周长 for (let i = 0; i < edges.length - 1; i++) { const p1 = edges[i]; const p2 = edges[i + 1]; const length = p1.distanceTo(p2); edgeLengths.push(length); totalLength += length; }
步骤2:遍历并修正侧面的UV
ExtrudeGeometry的面中,前两个是形状的正面和背面,从第3个面开始都是挤出的侧面(每个边对应两个三角面)。我们给这些侧面重新分配UV:
// 获取几何体的UV数组 const faceVertexUvs = geometry.faceVertexUvs[0]; let currentLength = 0; // 遍历每个边对应的侧面三角面(每个边对应2个三角面) for (let i = 0; i < edgeLengths.length; i++) { const edgeLength = edgeLengths[i]; // 计算当前边对应的UV起始/结束比例(基于总周长) const startU = currentLength / totalLength; const endU = (currentLength + edgeLength) / totalLength; // 当前边对应的两个三角面索引 const faceIndex1 = 2 + i * 2; const faceIndex2 = 2 + i * 2 + 1; // 第一个三角面的UV:沿着边从startU到endU,挤出方向从0到1 faceVertexUvs[faceIndex1] = [ new THREE.Vector2(startU, 0), new THREE.Vector2(endU, 0), new THREE.Vector2(startU, 1) ]; // 第二个三角面的UV:补全四边形的另一部分 faceVertexUvs[faceIndex2] = [ new THREE.Vector2(endU, 0), new THREE.Vector2(endU, 1), new THREE.Vector2(startU, 1) ]; currentLength += edgeLength; } // 标记UV已更新,让Three.js重新识别 geometry.uvsNeedUpdate = true;
步骤3:调整纹理设置
确保纹理设置和手动UV匹配,比如希望纹理沿着形状边重复的话,修改wrapS模式:
texture.wrapS = THREE.RepeatWrapping; texture.wrapT = THREE.ClampToEdgeWrapping; texture.repeat.set(2, 1); // 比如沿着形状边重复2次,挤出方向不重复 texture.needsUpdate = true;
额外说明
- 如果你的波浪结构是多个独立框架,把上面的UV修正逻辑封装成函数,每个框架的几何体都调用一次即可。
- 后续调整Shape形状时,记得重新计算边长度和UV,否则映射会再次出错。
- 正面和背面的UV如果也需要优化,可以用类似逻辑,根据形状的实际尺寸分配比例。
内容的提问来源于stack exchange,提问作者Fabian
相关产品推荐
相关产品推荐

