自定义THREE.js球体几何体UV映射异常:纹理条纹问题排查
解决自定义球体几何体的UV纹理条纹问题
你的纹理条纹是因为UV坐标在θ=±π(纹理U方向的0/1边界)处的不连续导致的。浮点计算的精度误差和错误的UV添加逻辑,使得边界处的纹理坐标出现跳变,最终形成拉伸条纹。以下是修复后的代码及关键说明:
修复后的UV分配函数
function assignUVs(geometry, r) { function cartesian2polar(position){ return { phi: Math.acos(Math.max(-1, Math.min(1, position.y / r))), // 避免数值精度导致acos返回NaN theta: Math.atan2(position.z, position.x) }; } function polar2canvas(polarPoint) { return { y: polarPoint.phi / Math.PI, x: (polarPoint.theta + Math.PI) / (2 * Math.PI) }; } const polarVertices = geometry.vertices.map(cartesian2polar); geometry.faceVertexUvs[0] = []; geometry.faces.forEach(function(face) { const uvs = []; const ids = ['a', 'b', 'c']; for(let i = 0; i < ids.length; i++) { const vertexIndex = face[ids[i]]; let vertex = {...polarVertices[vertexIndex]}; // 复制对象,避免污染原数组 // 处理θ边界:将接近π的θ转为-π,保证UV在0点连续 const thetaEpsilon = 0.001; // 浮点精度容差 if(Math.abs(vertex.theta - Math.PI) < thetaEpsilon) { vertex.theta = -Math.PI; } const canvasPoint = polar2canvas(vertex); uvs.push(new THREE.Vector2(1.0 - canvasPoint.x, 1.0 - canvasPoint.y)); } // 每个面仅添加一组UV(对应三个顶点),修正原循环内重复添加的错误 geometry.faceVertexUvs[0].push(uvs); }); geometry.uvsNeedUpdate = true; }
关键修复点说明
浮点精度容错:
在cartesian2polar中对position.y/r做了 clamp 处理,避免因浮点计算误差导致acos函数返回NaN,确保极坐标转换的稳定性。θ边界统一处理:
用小容差判断顶点θ值是否接近π,将其转为-π。因为θ=π和θ=-π在球体上是同一位置,对应UV的U值从1变为0,保证纹理在边界处的连续性,消除拉伸条纹。修正UV添加逻辑:
原代码在遍历顶点的for循环内重复添加UV组,导致每个面被错误注册3次。修复后将geometry.faceVertexUvs[0].push(uvs)移到循环外,每个面仅添加一组对应三个顶点的UV数据,符合Three.js的UV结构要求。
内容的提问来源于stack exchange,提问作者Domantas Motiejunas
相关产品推荐
相关产品推荐

