使用Three.js ObjectLoader导入Blender场景的颜色纹理位置问题排查
问题分析与解决方案
看起来你遇到的问题大概率是代码逻辑错误+Blender导出设置不当共同导致的,咱们一步步拆解解决:
一、代码里的几个明显问题
1. 错误包裹加载后的模型
你写了mesh = new THREE.Mesh(loadedObj);,但loadedObj本身就是Three.js能直接识别的Object3D/Group对象,不需要再用Mesh包裹它——这会直接破坏模型的层级结构,导致位置、材质全部混乱。直接删掉这行代码就行。
2. 相机视锥体范围太小
你的相机far值设为10,如果Blender里的场景尺寸超过10个单位,物体就会被裁切掉或者显示异常。把far调大,比如改成1000:
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 1000);
3. 光照不足导致颜色异常
仅用AmbientLight虽然能照亮场景,但如果Blender里用的是PBR材质或者依赖方向光的材质,单一环境光会让颜色显得灰暗、失真。建议添加一个方向光辅助:
function initLights() { var ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); // 添加方向光,模拟太阳光 var directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(5, 10, 7.5); scene.add(directionalLight); }
二、Blender导出的关键注意事项(这是核心!)
很多新手忽略Blender导出的细节,这往往是模型显示异常的根源:
1. 必须使用Three.js官方导出插件
确保你在Blender里安装了Three.js Exporter(Blender 2.8+可以在插件市场搜索安装),不要用默认的JSON导出,要选择Three.js格式导出。
2. 导出前的模型准备
- 给所有物体应用变换:选中所有物体,按
Ctrl+A,依次选择位置、旋转、缩放——如果不应用,导出后的模型会带有隐藏的变换数据,在Three.js里位置、大小完全不对。 - 检查平面的UV展开:如果平面没有正确UV展开,即使赋予了纹理,导出后也无法显示。在Blender里进入编辑模式,按
U选择合适的UV展开方式(比如智能UV投影)。
3. 导出设置要点
- 勾选Include Materials和Include Textures:不勾选的话,材质和纹理根本不会被导出,自然显示异常。
- 坐标转换:Blender是Z轴向上,Three.js是Y轴向上,导出时一定要勾选Convert to Three.js Coordinate System,否则模型会整体旋转90度,位置完全错乱。
- 纹理路径设置:选择Relative Path(相对路径),确保纹理文件和导出的
city.json在同一目录下,否则Three.js找不到纹理文件,平面就会显示缺失纹理的状态。
三、修正后的完整代码示例
var scene, camera, renderer; var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; function init() { scene = new THREE.Scene(); initCamera(); initLights(); initRenderer(); document.body.appendChild(renderer.domElement); // 监听窗口大小变化 window.addEventListener('resize', onWindowResize, false); } function initCamera() { camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 1000); camera.position.set(0, 3.5, 5); camera.lookAt(scene.position); } function initRenderer() { renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(WIDTH, HEIGHT); // 开启阴影(如果需要) renderer.shadowMap.enabled = true; } function initLights() { var ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); var directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); directionalLight.position.set(5, 10, 7.5); directionalLight.castShadow = true; scene.add(directionalLight); } // 加载模型 var loader = new THREE.ObjectLoader(); loader.load('./city.json', function(loadedObj) { // 直接添加加载后的对象,不需要再包裹Mesh scene.add(loadedObj); // 可以在这里调试单个物体 console.log(loadedObj.getObjectByName("plane")); console.log(loadedObj.getObjectByName("building1")); }); function onWindowResize() { WIDTH = window.innerWidth; HEIGHT = window.innerHeight; camera.aspect = WIDTH / HEIGHT; camera.updateProjectionMatrix(); renderer.setSize(WIDTH, HEIGHT); } function render() { requestAnimationFrame(render); renderer.render(scene, camera); } init(); render();
按照上面的步骤调整后,应该能解决颜色、纹理、位置的问题。如果还有异常,可以打开浏览器控制台看是否有纹理加载失败的报错,或者检查Blender里的材质是否正确设置。
内容的提问来源于stack exchange,提问作者DaChoj
相关产品推荐
相关产品推荐

