使用Three.js加载OBJ模型时网格显示黑色的问题求助
解决Three.js加载OBJ+MTL模型显示黑色的问题
模型显示黑色大概率是纹理未正确加载或者灯光配置时机有问题,给你几个针对性的修改方案:
1. 修正MTL纹理路径
MTL文件里的纹理路径是相对MTL文件本身的,但默认MTLLoader会以当前页面为基准查找纹理,所以需要设置setPath指定纹理的基准目录:
const mtlLoader = new MTLLoader(); mtlLoader.setPath('House/v2/'); // 指向MTL和纹理所在的文件夹 mtlLoader.load('texturedMesh.mtl', function(materials) { // ... 原有代码 });
2. 提前添加灯光到场景
你现在是等OBJ加载完成后才添加灯光,初始渲染时场景没有灯光,模型自然变黑。把灯光代码移到加载逻辑外面:
// 把灯光放到加载代码之前,确保场景一开始就有光照 const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x404040, 1); scene.add(hemisphereLight); // 再执行MTL和OBJ加载逻辑 const mtlLoader = new MTLLoader(); // ...
3. 验证纹理加载状态
给加载器添加进度和错误回调,同时在OBJ加载完成后遍历模型,确认材质和纹理是否正确加载:
mtlLoader.load( 'texturedMesh.mtl', function(materials) { materials.preload(); const objLoader = new OBJLoader(); objLoader.setMaterials(materials); objLoader.load( 'texturedMesh.obj', function(object) { // ... 原有模型缩放、添加逻辑 // 遍历模型检查材质 object.traverse(function(child) { if (child.isMesh) { console.log('Mesh材质:', child.material); if (child.material.map) { console.log('纹理已加载:', child.material.map); } else { console.log('该Mesh无绑定纹理'); } } }); }, (xhr) => console.log(`OBJ加载进度: ${(xhr.loaded/xhr.total*100).toFixed(2)}%`), (err) => console.error('OBJ加载失败:', err) ); }, (xhr) => console.log(`MTL加载进度: ${(xhr.loaded/xhr.total*100).toFixed(2)}%`), (err) => console.error('MTL加载失败:', err) );
完整修改后的script.js代码
import * as THREE from 'three'; import { MTLLoader } from 'MTLLoader'; import { OBJLoader } from 'OBJLoader'; import { OrbitControls } from 'OrbitControls'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x808080); document.body.appendChild(renderer.domElement); // 提前添加灯光,避免初始无光照渲染 const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x404040, 1); scene.add(hemisphereLight); // 加载材质与模型 const mtlLoader = new MTLLoader(); mtlLoader.setPath('House/v2/'); // 指定MTL和纹理所在目录 mtlLoader.load( 'texturedMesh.mtl', function(materials) { materials.preload(); const objLoader = new OBJLoader(); objLoader.setMaterials(materials); objLoader.load( 'texturedMesh.obj', function(object) { object.scale.set(0.5, 0.5, 0.5); object.position.y = -1; scene.add(object); // 验证材质与纹理加载状态 object.traverse(function(child) { if (child.isMesh) { console.log('当前Mesh材质:', child.material); if (child.material.map) { console.log('纹理状态:', child.material.map.isTexture ? '已加载' : '未加载'); } else { console.log('该Mesh未绑定纹理'); } } }); camera.position.set(0, 0, 5); camera.lookAt(scene.position); const controls = new OrbitControls(camera, renderer.domElement); function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } animate(); }, (xhr) => console.log(`OBJ加载进度: ${(xhr.loaded/xhr.total*100).toFixed(2)}%`), (err) => console.error('OBJ加载失败:', err) ); }, (xhr) => console.log(`MTL加载进度: ${(xhr.loaded/xhr.total*100).toFixed(2)}%`), (err) => console.error('MTL加载失败:', err) ); // 窗口大小调整处理 window.addEventListener('resize', function() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); });
另外注意检查:纹理文件名和MTL文件中指定的名称是否完全一致(包括大小写),文件名不匹配也是纹理加载失败的常见原因。
内容的提问来源于stack exchange,提问作者Goz532
相关产品推荐
相关产品推荐

