首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

WebGL 加載 JSON 模型貼圖混亂:Three.js 材質 wrapS/wrapT 重複模式修正

     編輯:程式設計疑難解答

現象

3ds Max 導出 OBJ+MTL → 轉 JSON → Three.js 加載,模型貼圖出現錯位、重複、拉伸等混亂現象 (見題主截圖)。

根本原因

  • 模型 UV 坐標超出 `[0,1]` 範圍,或模型本身設計為平鋪貼圖。
  • Three.js 默認材質 `Texture.wrapS = Texture.wrapT = ClampToEdgeWrapping` (邊緣拉伸),不會自動重複。
  • JSON 導出過程可能丟失 MTL 中的 `map_Kd` 重複屬性聲明。

解決方案:手動設置重複模式


// 加載器回調中
loader.load('model.json', function(geometry, materials) {
    var material = new THREE.MeshFaceMaterial(materials); // 或單一材質
    
    // 關鍵:遍歷所有材質的貼圖,啟用重複
    material.materials.forEach(function(mat) {
        if (mat.map) {
            mat.map.wrapS = THREE.RepeatWrapping; // 水平重複
            mat.map.wrapT = THREE.RepeatWrapping; // 垂直重複
            // 若需鏡像重複:THREE.MirroredRepeatWrapping
        }
        // 同理處理 normalMap, specularMap 等
        if (mat.normalMap) {
            mat.normalMap.wrapS = THREE.RepeatWrapping;
            mat.normalMap.wrapT = THREE.RepeatWrapping;
        }
    });
    
    var mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
});

進階:根據 UV 範圍動態設置


// 計算 UV 最大值 (需 geometry 有 uv 屬性)
var uvAttr = geometry.attributes.uv;
var maxU = 0, maxV = 0;
for (var i = 0; i < uvAttr.count; i++) {
    maxU = Math.max(maxU, uvAttr.getX(i));
    maxV = Math.max(maxV, uvAttr.getY(i));
}
if (maxU > 1 || maxV > 1) {
    // UV 超出 [0,1] 必須啟用 RepeatWrapping
    material.materials.forEach(m => {
        if (m.map) { m.map.wrapS = m.map.wrapT = THREE.RepeatWrapping; }
    });
}

批量修正建議

  • 美術端:在 3ds Max 中確保 UV 在 `[0,1]` 內,或明確告知導出設置包含平鋪屬性。
  • 工具端:編寫腳本遍歷所有 JSON 模型材質,自動檢測 UV 範圍並注入 `wrapS/wrapT` 配置。
  • 運行時:統一在材質創建工廠方法中默認啟用 `RepeatWrapping`,除非明確標記為 `ClampToEdge`。

總結

貼圖混亂核心是 **UV 坐標與材質重複模式不匹配**。Three.js 默認 `ClampToEdge`,模型若需平鋪必須顯式設置 `material.map.wrapS = material.map.wrapT = THREE.RepeatWrapping`。建議在材質工廠層統一處理,避免單模型單獨修正。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved