这次我们来看一个 3D Neural Decode 类型的交互网站项目。这类项目的核心目标非常直接:用可旋转、可缩放、可点击的 3D 场景,把神经网络结构、权重、激活值和推理路径直观呈现出来,让不习惯读论文和源码的人也能理解 AI 模型内部到底发生了什么。它不是一个训练框架,也不是推理引擎,而是一个面向“看懂模型”的交互式可视化网站。
项目最值得关注的特点可以归纳为四块:一是 3D 场景渲染,模型层与神经元以空间结构展示,比传统 2D 示意图更有层次感;二是交互式解码,点击某个神经元或连接边,可以查看对应的权重、激活值、名称等参数;三是数据与渲染分离,模型结构用 JSON 描述,前端负责解析和绘制,方便替换为不同模型;四是轻量运行,整体以浏览器 WebGL 渲染为主,普通电脑就能演示,不强制依赖独立显卡。
这篇文章会从技术架构、本地部署、功能验证、接口扩展、性能优化和问题排查几个方面展开。适合三类读者:给 AI 小白做科普演示的产品同学,想做前端可视化的开发者,以及需要给模型写配套解释文档的研究人员。整体阅读时间大约 15 分钟,建议收藏后在电脑端对照操作。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 3D 交互式神经网络可视化网站 |
| 主要功能 | 神经网络结构 3D 展示、神经元拾取与参数查看、推理过程可视化、注意力/激活值展示 |
| 前端渲染方案 | WebGL 场景,常见实现为 Three.js / React Three Fiber,具体以项目源码为准 |
| 数据格式 | 模型结构通过 JSON 描述,前端解析渲染 |
| 运行方式 | 本地静态服务或 Node 开发服务 |
| 是否需要 GPU | 通常不需要,浏览器软渲染也能打开,复杂场景建议开启硬件加速 |
| 是否支持 API | 取决于项目是否提供数据接口服务,可自行封装模型配置读取接口 |
| 是否支持批量任务 | 以单模型/多模型切换为主,若要做批量演示需自行增加队列逻辑 |
| 适合场景 | AI 教学演示、模型论文配图、技术直播、前端可视化方案验证 |
这里需要明确一个边界:由于不同版本的 3D Neural Decode 项目在实现上差异较大,上表属于“这类项目通常具备的能力”,具体到某个仓库时,要以实际 README 和代码为准。不要假设所有 3D 神经网络可视化项目都自带完整的后端接口,很多项目其实是一个纯静态前端页面。
2. 适用场景与使用边界
2.1 这个网站能解决什么问题
传统上我们理解神经网络,靠的是纸面结构图或者 TensorBoard 这类 2D 工具。2D 图适合表达层与层之间的纵向连接,但表达高维特征、通道关系、注意力权重时就显得局促。3D Neural Decode 网站解决的核心问题是“空间感缺失”:它把神经网络的层、神经元、连接边放进一个三维空间,观察者可以环绕查看,也能放大到单个节点看细节。
另外一个很实际的价值是教学演示。给完全没有深度学习基础的人讲卷积、池化、全连接,静态图很难讲清楚数据的流动过程。但 3D 场景里如果加入推理动画,比如输入一张图片后,激活值逐层向前传播,观察者就能直观看到“哪一层对最终结果影响最大”。这种演示方式在技术分享、公开课、项目答辩中很加分。
2.2 不适合什么场景
这类网站不适合做精确的模型调试。它展示的是结构、激活值、权重分布,而不是完整的梯度信息、训练曲线、参数量统计。真要定位模型为什么收敛慢、为什么梯度消失,还是得回到训练框架里看日志和曲线。
它也不适合做超大型模型的全量可视化。像 BERT-Large、GPT 级别模型的参数达到数亿甚至千亿,如果试图把每个神经元和每条连接都画成 3D 节点,浏览器会有明显的渲染压力。因此实际项目通常做简化处理,只展示层结构、头部注意力等抽象信息。
2.3 版权、隐私与合规边界
如果这个网站要发布到公网,或者把真实模型的权重、网络结构、训练数据可视化出来,需要注意几点:模型权重如果来自开源社区,要保留原许可证信息;如果来自公司的内部模型,发布前需要确认脱敏和授权;如果网站允许用户上传自己的图片或模型文件,涉及人脸、声音等敏感数据时必须明确提示用途并限制访问范围。
可视化本身没有安全风险,但它把模型内部结构暴露得更清晰,等于进行了某种程度的“模型逆向展示”。如果你的模型涉及商业机密,或者使用了非公开的训练数据,建议只做本地演示,不要直接挂到公网。
3. 整体架构与可视化思路
3.1 前端 3D 渲染层
3D Neural Decode 网站的前端通常包含几个核心模块:场景初始化、模型结构解析、节点与连线生成、交互拾取、动画控制。场景初始化指创建 WebGL 渲染器、相机、轨道控制器;模型结构解析负责读入 JSON 并映射为三维坐标;节点与连线生成决定每个神经元在空间中的位置;交互拾取负责判断用户点击了哪个节点;动画控制用于展示激活值传播。
以 Three.js 为例,初始化一个可交互的 3D 场景的代码大致是这样的:
import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.set(60, 40, 60); const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); document.getElementById('app').appendChild(renderer.domElement); const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.08; function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } animate();这段代码不依赖具体项目,属于通用场景模板。实际开发时,你需要在animate循环里加入节点动画、选中效果、数值更新逻辑。
3.2 模型结构数据格式
为了让前端能够渲染任意神经网络,模型结构最好独立成数据文件。一个典型的简化结构 JSON 可以这样设计:
{ "model": "mnist_cnn", "layers": [ { "id": "input", "type": "input", "shape": [28, 28, 1], "position": {"x": 0, "y": 0, "z": 0} }, { "id": "conv1", "type": "conv2d", "kernel_size": 3, "filters": 8, "activation": "relu", "position": {"x": 10, "y": 0, "z": 0} }, { "id": "pool1", "type": "maxpool", "pool_size": 2, "position": {"x": 20, "y": 0, "z": 0} }, { "id": "fc", "type": "dense", "units": 10, "activation": "softmax", "position": {"x": 30, "y": 0, "z": 0} } ] }这里的关键设计点是给每一层都显式指定position。3D 布局不是必须由代码自动计算,手工指定反而更容易控制位置关系。层的坐标决定了场景中的排列方向,比如从左到右表示数据前向传播。如果你的项目里没有position字段,前端也可以根据层序号自动排列。
3.3 节点拾取与信息面板
3D 场景里最常用的交互是点击节点查看详情。Raycaster 拾取是通用做法:
const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); renderer.domElement.addEventListener('click', (event) => { const rect = renderer.domElement.getBoundingClientRect(); mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; raycaster.setFromCamera(mouse, camera); const hits = raycaster.intersectObjects(nodes); if (hits.length > 0) { const nodeData = hits[0].object.userData; updateInfoPanel(nodeData); } }); function updateInfoPanel(data) { document.getElementById('node-name').textContent = data.name; document.getElementById('node-type').textContent = data.type; document.getElementById('node-value').textContent = data.activation || '--'; }交互是否流畅很依赖两个细节:第一,点击检测的对象和实际渲染的对象要保持一致,不要在渲染时克隆了一份网格,却用另一组对象做拾取;第二,节点数量大时,不要每帧都对全部节点做intersectObjects,可以先用八叉树或网格剪裁减少检测范围,或者只在 click 事件里做一次全量检测。
4. 环境准备与前置条件
4.1 基础运行环境
由于这是一个 Web 项目,环境准备比本地模型部署简单得多。通常需要准备以下几项:
- Node.js 16 或更高版本,用于安装依赖和启动开发服务;
- 现代浏览器,推荐 Chrome、Edge、Firefox 的最新版本;
- 查看本机是否开启 WebGL 硬件加速;
- 如果项目带 Python 后端,需要 Python 3.8 或更高版本;
- 磁盘空间 1GB 以上即可,主要存放 npm 依赖和模型配置文件;
- 不需要独立 GPU,但复杂 3D 场景下,集成显卡也能跑,只是帧率可能偏低。
4.2 检查 WebGL 是否可用
打开 Chrome 或 Edge,在地址栏输入chrome://gpu,查看 WebGL 选项是否为 “Hardware accelerated”。如果显示 “Software only”,说明硬件加速被禁用或驱动有问题。这种情况 3D 场景仍然能渲染,但性能会明显下降。可以在浏览器设置里打开“使用硬件加速”,然后重启浏览器。
4.3 端口检查
如果项目默认监听本地端口,比如常见的前端开发端口 5173、3000、8080,启动前先确认端口没有被占用:
# Windows 环境查看端口占用 netstat -ano | findstr "5173" # Linux / macOS 环境 lsof -i :5173如果端口被占用,最简单的办法是换一个端口,或者关掉占用端口的进程。启动参数一般写在package.json的scripts里,修改方式看后面的启动章节。
5. 本地启动与服务访问
5.1 npm 方式启动
如果你的项目是基于 Node 的前端工程,通常会提供package.json。命令一般是这样:
# 进入项目目录 cd 3d-neural-decode # 安装依赖 npm install # 开发模式启动 npm run dev启动成功后,终端会输出一个本地地址,通常是http://localhost:5173或http://localhost:3000。用浏览器打开这个地址,就能看到 3D 场景。
如果项目没有提供package.json,可以检查是不是纯静态页面。纯静态页面不需要安装依赖,直接用任意静态服务器启动即可:
# Python 3 自带的静态服务器 cd 3d-neural-decode python -m http.server 8080然后访问http://localhost:8080。
5.2 构建生产版本
开发模式启动适合调试,发布到服务器前建议执行构建命令:
npm run build构建完成后,生成的文件通常在dist或build目录。把这个目录上传到 Nginx、GitHub Pages、Vercel 等任意静态托管平台,就能公网访问。如果项目里还有后端接口服务,需要确保前端请求的接口地址和实际部署地址一致,否则会出现页面能打开、数据加载不出来的问题。
5.3 验证服务是否正常
启动后不要急着看 3D 场景,先做三步检查:
- 打开浏览器开发者工具的 Console,确认没有 JS 报错;
- 打开 Network 面板,确认模型结构 JSON 请求状态是 200,而不是 404;
- 观察页面中是否出现神经网络结构,结构是否完整显示所有层。
如果 JSON 请求 404,多半是模型配置文件路径不对。检查项目目录下是否存在模型文件,以及文件名大小写是否一致。很多 Linux 服务器对路径大小写敏感,但 Windows 下不敏感,这会导致本地能跑、上线后加载失败的坑。
6. 核心功能测试与效果验证
6.1 模型结构加载测试
测试目的:确认 3D 场景能正确解析模型 JSON 并渲染完整结构。
操作步骤:
- 打开网站首页,等待模型加载;
- 观察场景中是否出现多个层节点,每层之间的连接线是否正常;
- 查看页面信息面板,是否显示模型名称、层数量、参数量等基础信息;
- 切换一个模型文件,刷新页面,确认结构随之变化。
判断成功的标准:所有层都出现在 3D 场景中,且层之间的相对位置合理。失败时,优先检查 Network 面板里模型文件请求是否失败,以及 JSON 格式是否和前端解析逻辑匹配。
常见失败原因:
- 模型文件缺失或路径错误;
- JSON 格式与前端字段不匹配,比如前端期望
layers,实际上传的是layer_list; - JSON 中存在中文注释或尾逗号,导致解析失败。
6.2 3D 交互操作测试
测试目的:验证环绕、缩放、平移、点击拾取等交互是否正常。
操作步骤:
- 按住鼠标左键拖拽,场景应绕目标点旋转;
- 滚动滚轮,场景应缩放;
- 按住鼠标右键拖拽,场景应平移;
- 单击某个神经元或层节点,右侧信息面板应显示对应参数;
- 点击空白处,信息面板应关闭或清空。
预期结果:操作流畅,没有明显卡顿;点击节点时,高亮效果即时反馈;信息面板显示的数值和模型配置文件一致。
如果点击节点没有反应,先确认是否点击到了实际渲染的网格体。有些项目为了视觉效果,节点是精灵图或者粒子,而不是标准 Mesh,它们的拾取逻辑需要单独处理。另外检查userData是否在创建节点对象时挂载,很多拾取失效问题都是因为userData没有写入数据。
6.3 前向传播动画测试
测试目的:验证推理过程动画是否按层顺序传播。
操作步骤:
- 点击“运行推理”或“播放”按钮;
- 观察高亮或流光效果是否从输入层依次传到输出层;
- 观看结束后,检查输出层展示的预测标签或概率分布是否合理;
- 重复运行,确认动画步调稳定。
这个功能是这个项目最吸引人的部分。如果动画没有执行,通常是因为前端没有设置定时器,或者推理结果数据没准备好。建议在代码里对每层传播增加一个间隔时间参数,比如每层 300ms,这样调试时能看清每一层的输出。
6.4 注意力/激活值可视化测试
测试目的:确认激活值能映射到节点颜色或大小。
操作步骤:
- 输入一条测试样本,或者选择预设样例;
- 观察各节点颜色或球体大小是否随激活值变化;
- 点击高亮的节点,查看具体激活数值是否和预期一致。
激活值展示通常使用颜色映射,比如蓝色表示低激活,红色表示高激活。如果所有节点颜色完全没有变化,需要检查激活值数据是否正确传递到了前端,以及颜色映射函数是否在 0 到 1 的范围内工作正常。注意检查数据里是否有极大异常值,异常值会把整个映射范围拉大,让大多数节点看起来都是同一个颜色。
6.5 多模型切换测试
测试目的:验证网站是否支持在多个模型结构间切换。
操作步骤:
- 在页面找到模型下拉框或切换按钮;
- 切换到第二个模型;
- 确认 3D 场景中旧模型节点被清空,新模型结构正常加载;
- 切换回第一个模型,确认状态恢复。
多模型切换最容易出现的坑是“内存泄漏”。每次切换时,旧场景中的几何体、材质、纹理如果没有被 dispose,会一直占用 GPU 内存,多次切换后页面越来越卡。如果你准备长期维护这个项目,建议在切换模型时主动释放资源:
function clearModelGroup(group) { if (!group) return; group.traverse((obj) => { if (obj.isMesh) { obj.geometry?.dispose(); if (Array.isArray(obj.material)) { obj.material.forEach((m) => m.dispose()); } else { obj.material?.dispose(); } } }); scene.remove(group); }7. 数据接口与扩展能力
7.1 前后端分离的接口设计
3D 可视化网站不一定只有纯前端。如果模型数据存放在后端,或者可视化结果需要动态生成,建议设计一套简单的 JSON 接口。一个通用接口设计是:
GET /api/model:返回默认模型结构;GET /api/models:返回可用模型列表;GET /api/model/:id:按 ID 返回指定模型结构;POST /api/upload:接收用户上传的模型配置或权重摘要。
以 Python Flask 为例,一个最小化接口长这样:
from flask import Flask, jsonify import json import os app = Flask(__name__) MODEL_DIR = "./models" @app.route("/api/model/<model_id>") def get_model(model_id): file_path = os.path.join(MODEL_DIR, f"{model_id}.json") if not os.path.exists(file_path): return jsonify({"error": "model not found"}), 404 with open(file_path, "r", encoding="utf-8") as f: data = json.load(f) return jsonify(data) if __name__ == "__main__": app.run(host="127.0.0.1", port=8000)前端加载接口数据后,再走 3D 渲染流程。这里要注意跨域问题。如果前端启动在 5173 端口,接口在 8000 端口,直接 fetch 会被浏览器拦截。Flask 侧可以用flask-cors解决:
pip install flask-cors然后在代码中启用:
from flask_cors import CORS CORS(app)7.2 批量可视化多个模型
如果需要批量生成多个模型的可视化页面,可以写一个自动化脚本。思路是:
- 准备一批模型配置文件,放在
models目录; - 启动后端接口服务;
- 前端通过路由参数或查询参数切换模型,例如
http://localhost:5173/?model=resnet50; - 配置一个监听脚本,当
models目录新增文件时,自动刷新页面或提示用户。
批量可视化不能把所有模型一次性全部加载到场景里,否则浏览器会卡死。更稳妥的做法是按需加载,一次只渲染一个模型,切换时再读取文件。
7.3 前端调用接口示例
async function loadModel(modelId) { const response = await fetch(`/api/model/${modelId}`); const data = await response.json(); buildSceneFromModel(data); } const urlParams = new URLSearchParams(window.location.search); const modelId = urlParams.get('model') || 'default'; loadModel(modelId);用 URL 参数控制模型选择,好处是分享链接时能带上具体模型,别人打开链接就能看到对应的可视化结构。
8. 性能观察与渲染优化
8.1 观察哪些指标
3D 可视化网站的性能瓶颈不在 CPU,而在 GPU 和内存。需要观察四个指标:
- 帧率 FPS,理想情况稳定在 50 到 60;
- GPU 内存占用,节点越多占用越高;
- 主线程 JS 执行时间,动画逻辑是否有每帧大量计算;
- 网络请求时间,模型 JSON 是否过大导致加载缓慢。
打开 Chrome 开发者工具的 Performance 面板,录制一段交互操作,可以看到脚本执行、渲染、绘制的时间占比。如果渲染时间占比明显偏高,问题出在绘制节点数量太多;如果脚本时间偏高,问题出在每帧做了过多计算。
8.2 节点数量对性能的影响
一个简单全连接网络可能只有几百个神经元,3D 场景完全没压力。但卷积层的神经元数量通常非常多,如果把每个通道、每个空间位置都画成一个球体,几万个节点会让浏览器明显卡顿。
优化策略有几种:
- 用 InstancedMesh 批量渲染相同形状的球体,大幅减少 draw call;
- 减少材质种类,全场景尽量共用材质;
- 对节点数量过大的层做抽样,只展示部分代表性神经元;
- 用 LOD 策略,相机距离远时显示简化结构,靠近时再显示细节;
- 使用 BufferGeometry 直接管理顶点位置,避免每帧修改对象的 transform。
写节点更新逻辑时,要避免每帧创建新对象。比如更新节点颜色,正确的做法是直接修改material.color或instanceColor,而不是scene.remove(oldNode); scene.add(newNode)。
8.3 如何降低资源占用
如果页面启动后风扇狂转,多半是渲染器一直在做高精度渲染。可以开启渲染器降级:
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));当节点数量超过阈值时,关闭抗锯齿:
if (nodeCount > 50000) { renderer = new THREE.WebGLRenderer({ antialias: false, alpha: false }); }限定动画帧率也是一个通用做法。很多 3D 工程用requestAnimationFrame无脑刷新,即使场景静止也保持 60 帧。可以用一个计数器控制动画更新频率,比如每秒最多更新 30 次:
let lastUpdate = 0; const FRAME_INTERVAL = 1000 / 30; function animate(time) { requestAnimationFrame(animate); if (time - lastUpdate < FRAME_INTERVAL) return; lastUpdate = time; controls.update(); renderer.render(scene, camera); }9. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 首页白屏 | JS 报错或路由不对 | 打开控制台查看报错 | 修复脚本错误,检查访问路径 |
| 3D 场景不显示 | WebGL 硬件加速关闭 | 访问chrome://gpu查看 WebGL 状态 | 开启硬件加速或更换浏览器 |
| 模型加载后结构错乱 | JSON 中的层坐标不合适 | 在控制台打印解析后的坐标 | 调整 position 或自动布局算法 |
| 点击节点无反应 | 拾取对象和渲染对象不一致 | 检查 raycaster 检测列表 | 统一渲染与拾取对象 |
| 页面随着切换模型越来越卡 | 旧场景资源未释放 | 观察 GPU 内存变化 | dispose 几何体、材质、纹理 |
| 动画不播放 | 推理数据未获取或定时器未执行 | 查看网络请求和 console | 检查推理结果数据接口 |
| 接口请求跨域失败 | 前端端口和后端端口不一致 | 查看 Network 面板 CORS 错误 | 后端启用 CORS 或配置反向代理 |
| 高分辨率下画面模糊 | 渲染器没有处理 retina | 查看 pixelRatio | 设置setPixelRatio |
| 本地能跑线上不行 | 资源路径大小写或 base path 错误 | 对比本地和线上请求地址 | 使用相对路径或设置 base path |
这里补充一个定位技巧:遇到白屏,不要先看代码逻辑,先打开 Network 面板,看静态资源是否加载成功。很多线上部署问题都是静态资源路径配错,导致 JS 没加载出来。其次看 Console 面板,如果出现TypeError: Cannot read properties of undefined,通常是某个 JSON 字段为空,前端没有做空值判断。
10. 最佳实践与使用建议
10.1 先跑通最小示例再扩展
第一次接触这个项目,不要着急改 UI、加模型。先把默认模型跑起来,确认 3D 场景正常、交互正常、动画正常,再逐步替换成自己的模型结构。这样可以避免把“项目配置问题”和“模型数据问题”混在一起。
10.2 模型配置要建立统一约定
无论是自己定义模型 JSON,还是从训练框架导出模型结构,都建议建立一个统一 schema。每个 layer 至少要包含:id、type、name、shape、position。连接关系可以用connections字段显式描述。不要依赖前端自动推断连接,显式声明更可靠,也能支持复杂网络结构。
一个推荐的最小 schema 片段:
{ "model_id": "simple_mlp", "model_name": "Simple MLP Example", "layers": [ { "id": "input", "type": "input", "name": "Input Layer", "shape": [784], "position": {"x": 0, "y": 0, "z": 0} }, { "id": "hidden_1", "type": "dense", "name": "Hidden Layer 1", "units": 128, "activation": "relu", "position": {"x": 10, "y": 0, "z": 0} } ], "connections": [ {"from": "input", "to": "hidden_1"} ] }10.3 目录管理建议
项目文件建议按以下方式组织:
3d-neural-decode/ ├── public/ │ └── models/ # 模型结构配置 ├── src/ │ ├── scene/ # 3D 场景相关代码 │ ├── ui/ # 信息面板和控件 │ ├── utils/ # JSON 解析等工具 │ └── main.js # 入口文件 ├── scripts/ # 模型导出等脚本 └── package.json模型配置、输入素材、输出截图不要混到一个目录。特别是做批量可视化时,模型配置目录必须是独立的,否则脚本遍历文件时容易出错。
10.4 涉及敏感模型数据时注意安全
如果可视化的是公司内部模型,或者模型包含敏感业务信息,发布到公网前要评估风险。至少做到:本地服务绑定127.0.0.1,不绑定0.0.0.0;生产环境加上访问认证;模型配置里如果包含真实路径、内部名称、未公开结构,要提前脱敏;上传功能如果没有必要,直接去掉。
10.5 发布或商用前做效果复核
3D 可视化很容易出现“演示时效果好,截图后信息混乱”的问题。发布到博客或做报告前,至少复核四个方面:节点颜色是否有区分度,色盲用户能不能看清;连接线是否遮挡关键节点,要不要降低透明度;信息面板文字是否在小屏幕下溢出;动画播放速度是否适合讲解,过快会看不清传播细节,过慢会拖节奏。
11. 总结与下一步
3D Neural Decode 这类网站项目,最值得尝试的点在于它把复杂的神经网络内部机制变成了一个可交互的空间对象。它不是替代 TensorBoard 的调试工具,而是面向理解、教学、演示的表达工具。值得先验证的功能有三个:模型结构是否正确加载、节点点击是否能看到参数信息、前向传播动画是否流畅。最容易踩的坑则是两个:一个是 GPU 资源没有释放,切换模型后页面越来越卡;另一个是 JSON 字段与前端解析逻辑不匹配,本地正常线上白屏。
如果你准备继续深入,可以从三个方向扩展:一是接入更多模型格式,比如把 ONNX、PyTorch 的结构自动导出为可视化 JSON;二是增加对比视图,让两个模型并排展示;三是把推理响应时间、层耗时等性能数据叠加到 3D 场景中,做成一个带运行时指标的模型分析面板。先从最小版本跑通,后续的扩展迭代会顺畅得多。
建议收藏备用。接下来你真正要做的,是打开终端,进入项目目录,输入启动命令,亲手把第一个 3D 模型场景跑起来。