three.js N体模拟器添加光照无效 升级报模块加载错误求助
问题描述
- 为数年前开发的旧版N体模拟器添加光照效果,仅完成光源添加配置后无任何效果
- 将粒子使用的现有
ParticleCanvasMaterial替换为MeshLambertMaterial后,粒子直接变为不可见状态 - 不清楚当前使用的旧版three.js版本号,无法确认光照功能兼容性;尝试升级最新版three.js时,因不熟悉新版模块机制配置失败
- 涉及修改的代码存放在GitHub仓库mrdoob分支,与master分支做diff即可查看为实现光照做的少量代码改动,目标是添加阴影效果提升模拟观测体验
已做排查
- 通过grep检索JS文件中的相关方法,未找到可解决问题的接口
- 尝试设置
light.castShadow、particle.receiveShadow属性,均未产生效果 - 尝试采用module方式加载最新版three.js,直接本地打开文件报错:
Module source URI is not allowed in this document: “file:///home/ian/projects/NBody3DJs/js/three”.
- 通过Python HTTP服务运行项目时,报错如下:
Uncaught ReferenceError: THREE is not defined init http://localhost:8000/main.js:26 <anonymous> http://localhost:8000/main.js:13 main.js:26:5 Uncaught TypeError: Error resolving module specifier “three”. Relative module specifiers must start with “./”, “../” or “/”. localhost:8000:20:33 asm.js type error: Disabled because no suitable wasm compiler is available es-module-shims.js Uncaught TypeError: NetworkError when attempting to fetch resource. es-module-shims.js:766:26 Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource.
- 移除全部模拟器相关代码,仅保留index.html、样式文件与three.js加载逻辑,仍出现模块解析相关报错
解决思路
旧版three.js光照不生效排查
- 先确认当前three.js版本:打开浏览器开发者工具控制台,输入
THREE.REVISION即可输出版本号,确认版本对MeshLambertMaterial、阴影API的支持情况 - 材质替换后粒子不可见的核心原因:
ParticleCanvasMaterial属于不受光照影响的基础材质,无需光源即可直接显示;MeshLambertMaterial为受光材质,若场景光源配置错误(强度为0、位置未覆盖粒子区域、方向错误)、材质颜色设为纯黑,都会导致物体不可见- 确认粒子渲染载体:如果使用的是
Points(早期版本叫ParticleSystem)渲染粒子,部分旧版three.js中Points对光照材质的支持存在缺陷,无法响应光照,需要改用Mesh搭配小尺寸几何体(如球体)作为粒子载体才能正常受光
- 阴影生效必须满足全部以下配置,缺项则无法渲染阴影:
- 渲染器开启阴影映射:
renderer.shadowMap.enabled = true - 光源开启投射阴影:
light.castShadow = true,同时正确配置光源阴影相机的视锥体范围,确保所有粒子都在阴影相机的覆盖区域内 - 投射阴影的星体粒子设置
castShadow = true - 接收阴影的对象(如背景平面、其他星体)设置
receiveShadow = true - 避免错误修改材质的
shadowSide属性,默认使用正面渲染即可
- 渲染器开启阴影映射:
新版three.js模块加载报错修复
所有模块相关报错均为加载路径配置错误导致,按以下步骤处理:
- ES模块不支持
file://协议访问,必须通过HTTP服务运行页面,Python启动的本地服务方向正确,仅需修正路径配置 - 浏览器原生不支持
import 'three'这类裸模块标识符,两种方案二选一即可:- 方案一(适配旧项目,零改造成本):使用three.js的UMD构建版本,不使用ES模块,在HTML中通过普通script标签引入:将three.min.js放到项目js目录下,添加标签
<script src="./js/three.min.js"></script>,再引入自身业务的main.js,即可全局挂载THREE对象,完全兼容旧版写法,不会出现THREE is not defined错误 - 方案二(使用ES模块):导入three.js时必须写完整相对路径,例如将three.module.js放在js目录下时,导入语句写为
import * as THREE from './js/three.module.js',不能直接使用from 'three'的写法
- 方案一(适配旧项目,零改造成本):使用three.js的UMD构建版本,不使用ES模块,在HTML中通过普通script标签引入:将three.min.js放到项目js目录下,添加标签
- es-module-shims相关报错是因为shim未正确获取three.js资源,采用上述任意一种方案后,可直接删除es-module-shims的相关引入,无需依赖该库
- asm.js相关警告为浏览器未开启WebAssembly优化的提示,不影响核心功能运行,无需额外处理
内容的提问来源于stack exchange,提问作者m4r35n357
相关产品推荐
相关产品推荐

