Three.js加载OBJ&MTL文件时纹理无法显示的问题求助
Hey there, let's dig into why your textured OBJ model isn't displaying correctly and fix that GL error you're seeing. I've worked through similar issues before, so here are the most likely fixes to try:
1. Verify Texture Path Resolution
Even though you've set setPath('obj/') for the MTLLoader, sometimes the texture paths in the MTL file don't get resolved properly. Let's explicitly set the texture path for each material to ensure it points to your obj/ folder:
var mtlLoader = new THREE.MTLLoader(); mtlLoader.setPath('obj/'); mtlLoader.load('74.mtl', function(materials) { materials.preload(); // Manually ensure each texture uses the correct base path Object.values(materials.materials).forEach(mat => { if (mat.map) { mat.map.setPath('obj/'); } }); var objLoader = new THREE.OBJLoader(); objLoader.setMaterials(materials); objLoader.setPath('obj/'); objLoader.load('74.obj', function(object) { scene.add(object); }); });
2. Fix Missing/Invalid UV Coordinates
The GL error GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 2 points directly to UV coordinate issues—attribute 2 is almost always the UV attribute in Three.js. Your model might have faces without proper UV mapping, which breaks when a texture is applied.
Let's check and add default UVs if missing when loading the OBJ:
objLoader.load('74.obj', function(object) { object.traverse(child => { if (child.isMesh) { // Check if UV attribute exists if (!child.geometry.attributes.uv) { // Generate basic default UVs (adjust scale based on your model's size) const uvArray = []; const vertices = child.geometry.attributes.position.array; for (let i = 0; i < vertices.length; i += 3) { uvArray.push(vertices[i] * 0.1, vertices[i+1] * 0.1); } child.geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvArray), 2)); } // Force material/geometry update to apply changes child.material.needsUpdate = true; child.geometry.needsUpdate = true; } }); scene.add(object); });
3. Ensure Textures Fully Load Before Adding the Model
The materials.preload() call starts loading textures, but it doesn't wait for them to finish. If the OBJ loads before textures are ready, you might see missing textures or glitches. Let's use promises to wait for all textures to load:
mtlLoader.load('74.mtl', function(materials) { // Create promises for each texture load const textureLoadPromises = []; Object.values(materials.materials).forEach(mat => { if (mat.map) { textureLoadPromises.push(new Promise(resolve => { mat.map.onLoad = resolve; mat.map.load(); // Explicitly trigger texture load })); } }); // Wait for all textures to load before loading the OBJ Promise.all(textureLoadPromises).then(() => { var objLoader = new THREE.OBJLoader(); objLoader.setMaterials(materials); objLoader.setPath('obj/'); objLoader.load('74.obj', function(object) { scene.add(object); }); }); });
4. Quick Checks to Rule Out Simple Issues
- Open Chrome DevTools > Network tab: Confirm
stone_1.jpgloads with a 200 status code. If not, double-check file names and folder structure (case sensitivity matters on some systems!). - Check if the image is corrupted: Try opening
stone_1.jpgin an image editor to make sure it's valid. You could also test with a different JPG/PNG to rule out format issues. - Use the Three.js DevTools extension to inspect your model's materials—verify that the
mapproperty is set and the texture is loaded.
Start with the path and UV checks first—those are the most common culprits here. Let me know if any of these work for you!
内容的提问来源于stack exchange,提问作者Shao-Kui

