You need to enable JavaScript to run this app. Three.js中如何给已加载OBJ对象附着自定义图像:避免贴图重复并定位到中心
优惠活动
大模型
产品
解决方案
定价
更多

Three.js中如何给已加载OBJ对象附着自定义图像:避免贴图重复并定位到中心

问题根源
  • 现在贴图反复铺满的核心原因:加载的OBJ文件自带的UV坐标,是模型导出时适配原有纹理的平铺逻辑做的映射,和你想要“单张图居中显示”的需求完全不匹配。
  • 你已经设置的ClampToEdgeWrapping,只是规定UV值超出0-1范围时不重复采样边缘,根本不会修改模型本身已经存在的UV映射关系,所以解决不了重复的问题。
实现方案

不用纠结读的UV映射理论找不到落地场景,只要直接把模型原来的旧UV替换掉,根据模型本身的大小重新生成一套“把整张纹理刚好居中铺满整个模型范围”的UV就行,不需要改动OBJ文件本身。

可直接复用的修改代码

把你现有代码里的核心逻辑替换成下面的版本,已经把重算UV的逻辑写进去了:

var mtlLoader = new MTLLoader();
mtlLoader.load("~~~.mtl", function (materials) {
  materials.preload();
  var objLoader = new THREE.OBJLoader();
  objLoader.setMaterials(materials);
  objLoader.load("~~.obj", function (geometry) {
    var textureLoader = new THREE.TextureLoader();
    var texture = textureLoader.load("~~.jpg");
    // 纹理基础配置,杜绝重复
    texture.minFilter = THREE.LinearFilter;
    texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
    texture.repeat.set(1, 1);
    texture.generateMipmaps = false;

    var material = new THREE.MeshLambertMaterial({
      transparent: true,
      map: texture
    });

    geometry.traverse(function (child) {
      if (child instanceof THREE.Mesh) {
        // 计算当前Mesh的空间边界
        const box = new THREE.Box3().setFromObject(child);
        const size = new THREE.Vector3();
        const center = new THREE.Vector3();
        box.getSize(size);
        box.getCenter(center);

        // 清除旧UV,生成新的居中映射UV
        const posAttr = child.geometry.attributes.position;
        const newUV = new Float32Array(posAttr.count * 2);
        // 按模型最大边长等比计算,避免纹理拉伸
        const maxSide = Math.max(size.x, size.y, size.z);

        for (let i = 0; i < posAttr.count; i++) {
          const px = posAttr.getX(i);
          const py = posAttr.getY(i);
          // 把顶点坐标映射到0-1的UV区间,中心位置对齐纹理中心
          const u = (px - center.x) / maxSide + 0.5;
          const v = (py - center.y) / maxSide + 0.5;
          newUV[i * 2] = u;
          newUV[i * 2 + 1] = v;
        }
        child.geometry.setAttribute('uv', new THREE.BufferAttribute(newUV, 2));
        child.material = material;
      }
    });
    scene.add(geometry);
  });
});
灵活调整提示
  • 如果不想把纹理投射到模型的所有曲面上,只想让纹理出现在模型正对着镜头的平面上,只需要调整UV生成时的坐标计算维度就行:比如正对着屏幕的平面只需要映射顶点的x、y坐标,其他维度的UV固定在0.5的中心位置即可。
  • 要调整纹理的投射方向,只要换计算UV用的顶点坐标维度:比如从顶部看模型,就用顶点的x、z坐标算UV;从侧面看模型,就用顶点的y、z坐标算UV。
  • 原来的MTL加载逻辑完全可以保留,重算UV和替换材质的操作会直接覆盖原有材质的纹理配置,不会产生冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.12 07:54:07