Three.js纹理无法加载问题求助(Vite环境3D卡片渲染)
问题:Three.js卡片纹理无法渲染(Vite环境)
用npx vite运行Three.js应用,想要渲染一张卡片。相机和灯光设置正常,能看到卡片的边缘(深度),但正反两面的纹理加载不出来。已确认文件结构正确,用TextureLoader的错误检测也没发现问题,找不到原因。
文件结构
- 项目根目录
- textures/
- citizen1.png
- cardback.png
- main.js
- cards.js
- textures/
代码片段
main.js
import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { CARDS } from './cards'; const gltfLoader = new GLTFLoader() // Scene const scene = new THREE.Scene() // 添加卡片 CARDS.forEach(function(card){ scene.add(card) console.log(card) }) // 灯光 const light = new THREE.PointLight(0xffffff, 1, 100) const ambientLight = new THREE.AmbientLight(0xA3A3A3, 1) scene.add(ambientLight) light.position.set(0, 10, 7) scene.add(light) // 相机 const camera = new THREE.PerspectiveCamera(45, 800/600) camera.position.set(0, 10, 6) camera.lookAt(new THREE.Vector3(0, 6, 2)) scene.add(camera) // 渲染器 const canvas = document.querySelector('.webgl') const renderer = new THREE.WebGL1Renderer({canvas}) renderer.setSize(800, 600) renderer.render(scene, camera)
cards.js
import { MeshBasicMaterial, BoxGeometry, Mesh, SRGBColorSpace, TextureLoader, Vector3 } from 'three'; const textureLoader = new TextureLoader(); const cardGeo = new BoxGeometry(0.4, 0.7, 0.03); const citizen1Texture = textureLoader.load('textures/citizen1.png'); citizen1Texture.colorSpace = SRGBColorSpace; const coverTexture = textureLoader.load('textures/cardback.png'); coverTexture.colorSpace = SRGBColorSpace; const card1Mat = [ new MeshBasicMaterial(), new MeshBasicMaterial(), new MeshBasicMaterial(), new MeshBasicMaterial(), new MeshBasicMaterial({map: citizen1Texture}), new MeshBasicMaterial({map: coverTexture}) ]; const CARDS = []; const cardsPositions = [ new Vector3(0.5, 7.005, 3.21) ]; function configureCard(card, pos, name){ card.name - name; // 笔误 card.castShadow = true; card.position.copy(pos[0]); CARDS.push(card); } const card1 = new Mesh(cardGeo, card1Mat); configureCard(card1, cardsPositions, 'card1'); export { CARDS }
解决方法
1. 修正Vite环境下的纹理路径
Vite加载本地静态资源需要用import.meta.url解析正确路径,否则可能资源找不到(即使控制台无报错)。修改cards.js中的纹理加载代码:
// 替换原纹理加载代码 const citizen1Texture = textureLoader.load(new URL('./textures/citizen1.png', import.meta.url).href); citizen1Texture.colorSpace = SRGBColorSpace; const coverTexture = textureLoader.load(new URL('./textures/cardback.png', import.meta.url).href); coverTexture.colorSpace = SRGBColorSpace;
2. 修复笔误
cards.js中configureCard函数里的card.name - name是语法错误,改为赋值:
card.name = name;
3. 确保纹理加载完成后再渲染
TextureLoader.load是异步操作,可能渲染时纹理还未加载完成。可添加加载回调或用LoadingManager管理资源:
// 使用LoadingManager const loadingManager = new THREE.LoadingManager(); loadingManager.onLoad = function() { console.log('所有资源加载完成'); renderer.render(scene, camera); }; const textureLoader = new TextureLoader(loadingManager); // 或给单个纹理加加载完成回调 citizen1Texture.onLoad = function() { renderer.render(scene, camera); }; coverTexture.onLoad = function() { renderer.render(scene, camera); };
4. 调整卡片视角
BoxGeometry的面索引对应:0-右侧、1-左侧、2-顶部、3-底部、4-正面、5-背面。当前相机位置可能对着卡片顶部/侧面,而非带纹理的前后两面。可在configureCard函数中添加旋转:
card.rotation.x = Math.PI / 2; // 让卡片正面朝向相机,可根据实际情况调整角度
5. 添加渲染循环
当前代码仅渲染一次,添加渲染循环可确保纹理加载完成后自动更新画面:
// 在main.js末尾添加 function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();
内容的提问来源于stack exchange,提问作者sergiutzuu
相关产品推荐
相关产品推荐

