










仓库地址:https://github.com/playcanvas/engine
版本:2.22.0-beta.17(package.json)
许可:MIT
语言:TypeScript / JavaScript(ESM 源码,按.js文件组织 + JSDoc 类型)
系列序号:源码解读系列第 17 篇
PlayCanvas Engine 是一个构建在 WebGL2 与 WebGPU 之上的开源网页端 3D 游戏引擎运行时(runtime)。官方定义:
"PlayCanvas is an open-source game engine built on WebGL2 and WebGPU. Use it to create interactive 3D apps, games and visualizations that run in any browser on any device."
它是一个纯运行时(runtime),不绑定任何 IDE——这与 PlayCanvas 自家的可视化编辑器(PlayCanvas Editor,独立仓库 playcanvas/editor)分离。引擎以 npm 包 playcanvas 形式分发,开发者既可只用引擎裸写代码,也可配合 @playcanvas/react、@playcanvas/web-components、create-playcanvas 脚手架或浏览器编辑器使用。
playcanvas(GitHub 组织)。PlayCanvas 公司 2014 年被 Snap( Snapchat 母公司) 收购,因此核心贡献者隶属于 Snap 的 PlayCanvas 团队。"license": "MIT"),对企业与商业用途友好。传统 3D 网页开发需要手写大量底层 WebGL 样板(着色器、缓冲区、渲染循环、资源管理)。PlayCanvas Engine 把这些都封装好,提供一套声明式 + 组件化的高层 API:
Entity + Component(相机、光照、模型、碰撞体、脚本等)描述场景;Application 管理主循环、资源加载、输入、声音、XR;其背景是:随着 WebGPU 普及、移动端图形能力增强、3D 内容(数字孪生、电商 3D、元宇宙/AR)需求爆发,业界需要一套专业级、可流式加载 glTF、支持 XR 与物理的通用网页 3D 引擎。PlayCanvas 凭借"开源 + 商业托管 + 编辑器"三位一体模式,成为与 Three.js、Babylon.js 并列的主流选择之一。
| 类别 | 能力 |
|---|---|
| 🧊 图形 Graphics | 基于 WebGL2 & WebGPU 的高级 2D + 3D 图形引擎 |
| 💠 高斯泼溅 Gaussian Splatting | 一流支持加载/渲染 3D Gaussian Splats |
| 🥽 XR | 通过 WebXR 内置 AR/VR 沉浸体验 |
| ⚛️ 物理 Physics | 与 ammo.js 3D 刚体物理引擎完整集成 |
| 🏃 动画 Animation | 基于状态的角色与任意场景属性动画 |
| 🎮 输入 Input | 鼠标、键盘、触摸、手柄 API |
| 🔊 声音 Sound | 基于 Web Audio API 的 3D 空间音效 |
| 📦 资源 Assets | 基于 glTF 2.0、Draco、Basis 压缩的异步流式系统 |
| 📜 脚本 Scripts | 可用 TypeScript 或 JavaScript 编写游戏行为 |
| 依赖项 | 要求 | 说明 |
|---|---|---|
| Node.js | >=18.3.0(engines.node,README 建议 18+) |
仅用于开发与构建引擎本身;普通使用通过 npm 安装已构建产物,无需 Node |
| npm | >=11.10.0,packageManager 锁 npm@11.18.0 |
安装依赖、运行构建脚本 |
| 支持 WebGL2/WebGPU 的浏览器 | Chrome/Edge/Firefox/Safari(新版) | 运行时目标环境;WebGPU 需较新版本浏览器 |
| 安全上下文 | https:// 或 localhost |
WebGPU/WebXR/麦克风等特性要求;file:// 直接打开受限 |
| 构建工具链(仅贡献者) | esbuild 0.28、turbo 2.10、rollup 4.62、typescript 5.9、typedoc 0.28 | 见 devDependencies |
| 运行时第三方库 | 物理依赖 ammo.js(WASM 版 Bullet);压缩依赖 Draco/Basis(KTX2)解码器(通常以资源形式提供) | 引擎核心 dependencies 仅含 @types/webxr、@webgpu/types 两个类型包,运行时不强制外部 npm 依赖 |
方式 A:作为库使用(最常见)
npm install playcanvas
随后在代码中 ESM 导入:
import { Application, Color, Entity, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO } from 'playcanvas';
方式 B:脚手架快速建项目
npm create playcanvas@latest
方式 C:从源码构建(贡献者/定制)
git clone https://github.com/playcanvas/engine.git
cd engine
npm install # 或 npm ci
npm run build # turbo run build:all → build/ 输出
import { Application, Color, Entity, FILLMODE_FILL_WINDOW, RESOLUTION_AUTO } from 'playcanvas';
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
const app = new Application(canvas);
app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
app.setCanvasResolution(RESOLUTION_AUTO);
window.addEventListener('resize', () => app.resizeCanvas());
const box = new Entity('cube');
box.addComponent('render', { type: 'box' });
app.root.addChild(box);
const camera = new Entity('camera');
camera.addComponent('camera', { clearColor: new Color(0.1, 0.2, 0.3) });
app.root.addChild(camera);
camera.setPosition(0, 0, 3);
const light = new Entity('light');
light.addComponent('light');
app.root.addChild(light);
light.setEulerAngles(45, 0, 0);
app.on('update', dt => box.rotate(10 * dt, 20 * dt, 30 * dt));
app.start();
| 命令 | 作用 |
|---|---|
npm run build |
turbo run build:all,构建全部 flavor(rel/dbg/prf/min)×(umd/esm)+ 类型声明到 build/ |
npm run docs |
typedoc 生成 API 文档到 docs/ |
npm run dev(无,但可) |
用 npm run watch 进入持久监听构建 |
npm test |
mocha 运行单元测试(需 --require test/fixtures.mjs) |
npm run lint / lint:fix |
eslint 9(flat config)代码检查 |
npm run serve |
在 51000 端口起静态服务预览 build/ |
npm run build:dbg:esm -- --watch |
单 flavor 监听构建(开发调试) |
exports)引擎提供多种构建产物,按"调试/性能分析/生产/压缩"与"UMD/ESM"正交组合:
.(默认):build/playcanvas.js(UMD)或 build/playcanvas/src/index.js(ESM)./debug(playcanvas.dbg)——含断言与 Debug 检查的调试版./profiler(playcanvas.prf)——含内建性能分析器(mini-stats 通道)./build/*、./scripts/*——直接引用内部构建/脚本sideEffects 仅标注 deprecated/deprecated.js,其余模块全部可 tree-shaking。
PlayCanvas 的运行时由一条清晰的分层数据流驱动。下面以"加载一个 glTF 模型并渲染到屏幕"为例,串起核心工作流。
core/ 基础工具与数学(无外部依赖):事件、GUID、对象池、Vec3/Mat4/Quat/Color、包围盒/视锥
platform/ 浏览器能力封装:GraphicsDevice(WebGL/WebGPU/NULL)、Input、Net、Sound
scene/ 纯场景图与渲染描述:Camera/Light/Mesh/MeshInstance/Model、材质、动画、Renderer、Shader-Lib、Frame-Graph
framework/ 应用层封装:Application、Entity、Component 系统、Asset 资源系统、Handlers、Anim、XR、GSplat、Physics
extras/ 可选高级工具:导出器、Gizmo(编辑器辅助)、mini-stats、render-passes、renderers
deprecated/ 向后兼容的旧 API
步骤 1:创建 GraphicsDevice
Application 构造函数(见 src/framework/application.js)调用 createDevice():
createDevice(canvas, options) {
if (platform.browser && !!navigator.xr) options.graphicsDeviceOptions.xrCompatible = true;
return new WebglGraphicsDevice(canvas, options.graphicsDeviceOptions);
}
默认构建 WebGL2 设备;若以 options.graphicsDevice 传入 WebGPU 设备,则可切换。设备创建时会探测能力、建立 shader-chunks、初始化内置纹理。
步骤 2:注册 Component 系统(23 个)
addComponentSystems() 向 AppOptions 注入 23 个系统类,例如:
RigidBodyComponentSystem, CollisionComponentSystem, AnimationComponentSystem, ModelComponentSystem, RenderComponentSystem, CameraComponentSystem, LightComponentSystem, ScriptComponentSystem, SoundComponentSystem, ElementComponentSystem, … GSplatComponentSystem。
步骤 3:注册 Resource Handler(25 个)
addResourceHandles() 注入资源加载器:RenderHandler, ModelHandler, MaterialHandler, TextureHandler, AnimClipHandler, CubemapHandler, ShaderHandler, ContainerHandler(glTF 容器), GSplatHandler, …。
步骤 4:init() 与 start()
init(appOptions) 完成装配后,调用 app.start() 启动主循环,逐帧触发 update/prerender/postrender 事件。
渲染核心在 src/scene/renderer/,由 FrameGraph(src/scene/frame-graph.js)统一编排。一帧内:
frameGraph.addRenderPass(pass) 注册 RenderPass,支持 beforePasses / afterPasses 依赖与 FramePassMultiView 多视包装(VR 双眼)。_compilePasses):
store=true,避免数据丢失;_skipEnd/_skipStart),减少 GPU barrier;RenderPass.render(),内部走 ForwardRenderer(forward-renderer.js)做可见性裁剪(culler.js)、分层渲染(layer-render-step.js)、阴影(shadow-renderer*.js)、集群光照(world-clusters-allocator.js)。platform/graphics 抽象层落到具体设备。这是引擎最难也最精妙的部分,位于 src/scene/shader-lib/:
glsl/ 版本、对 WebGPU 提供 wgsl/ 版本;program-library.js + shader-chunk-map.js 按材质需求(光照模型、雾、骨骼、蒙皮…)拼装程序;platform/graphics/shader-processor-glsl.js 做宏替换/版本适配;AssetRegistry → 对应 Handler → 解析(glTF 经 ContainerHandler 拆解出 Mesh/Texture/Anim/Material)→ 缓存入 Asset → 组件 model/render/anim 引用。glTF 支持 Draco(几何压缩)与 Basis/KTX2(纹理压缩)解码器插件。
build.mjs 是构建编排脚本,借 utils/esbuild-build-target.mjs 调用 esbuild:
src/index.js(24KB 聚合导出);--type:rel(发布)/ dbg(调试)/ prf(性能剖分)/ min(压缩);--format:esm / umd;turbo.json 把 build:all 拆成 build:umd/build:esm/build:types 并行;--treemap/--treenet/--treesun 调用 esbuild-visualizer 生成包体积可视化 HTML。| 文件 | 作用 | 模块 |
|---|---|---|
package.json |
包元数据、MIT 许可、exports 多产物映射、npm 脚本、devDependencies(esbuild/turbo/rollup/typedoc/mocha) | 工程 |
turbo.json |
构建任务 DAG:build:all → build:umd/esm/types,每个子任务定义 inputs(src/**/*.js) 与 outputs(build/*),with/persistent 编排 watch |
构建编排 |
build.mjs |
CLI 构建入口:解析 --type/--format/--watch/--sourcemaps/--treemap,调用 esbuild target 与 tree visualizer |
构建脚本 |
utils/esbuild-build-target.mjs |
esbuild 具体构建目标(入口、插件链、产物命名 OUT_PREFIX) |
构建脚本 |
utils/types-build-target.mjs |
类型声明构建(rollup-plugin-dts + tsc) | 构建脚本 |
eslint.config.mjs |
ESLint 9 flat config(基于 @playcanvas/eslint-config) |
质量 |
typedoc*.mjs |
API 文档生成配置(含 merge-modules / mdn-links / missing-exports 插件) | 文档 |
tsconfig*.json |
TypeScript 配置(JSDoc 类型检查与 .d.ts 生成) |
类型 |
README*.md(en/zh/ja/kr) |
多语言项目说明 | 文档 |
LICENSE |
MIT 全文 | 许可 |
CHANGELOG.md / CONTRIBUTING(如有) |
版本与贡献指南 | 文档 |
src/index.js(入口聚合)24KB 的再导出枢纽,按 // CORE、// PLATFORM/GRAPHICS、// SCENE、// FRAMEWORK、// EXTRAS、// BACKWARDS COMPATIBILITY 注释分区,将全部公共类(如 Application、Entity、Vec3、GraphicsDevice、WebglGraphicsDevice、WebgpuGraphicsDevice、Scene、Camera、Light、Asset、SoundManager、XrManager 等)具名导出,便于 tree-shaking。
src/core/ —— 引擎基石(无外部依赖)30 个直接子项(28 文件 + math/、shape/ 两目录):
event-handler.js(事件系统,引擎大量模块继承)、event-handle.js、guid.js、hash.js、object-pool.js(对象池,减少 GC)、ref-counted-*.js(引用计数缓存/对象)、indexed-list.js、sorted-loop-array.js、block-allocator.js、read-stream.js、path.js、uri.js、string.js、time.js、tracing.js、debug.js、platform.js(运行环境探测)、preprocessor.js、secure-context-warning.js、wasm-module.js(WASM 加载封装)、constants.js、core.js、tags.js/tags-cache.js、array-utils.js/map-utils.js/set-utils.js/sort.js/numeric-ids.js/string-ids.js。core/math/:vec2/3/4.js、mat3/4.js、quat.js、color.js、curve.js/curve-set.js、bounding-box.js(AABB)、bounding-sphere.js、plane.js、ray.js、frustum.js、sphere.js 等——全部手写高性能数学库,零依赖。core/shape/:box.js、sphere.js、plane.js、ray.js、capsule.js 等基础几何/碰撞形状。src/platform/ —— 浏览器能力封装| 子模块 | 内容 |
|---|---|
platform/graphics/ |
图形设备抽象核心(46 直接子项):graphics-device.js(基类,定义统一接口)、graphics-device-create.js(按环境选择 WebGL/WebGPU/NULL);webgl/(WebGL2 实现:webgl-graphics-device.js 等)、webgpu/(WebGPU 实现)、null/(无头测试设备)。还包括 texture.js、vertex-buffer.js、index-buffer.js、shader.js、render-target.js、render-pass.js/frame-pass.js、bind-group.js/bind-group-format.js、uniform-buffer*.js、storage-buffer.js、scope-id.js/scope-space.js(uniform 作用域映射)、shader-processor-glsl.js(GLSL 后处理)、shader-chunks/(平台级着色器分块)、gpu-profiler.js、dynamic-buffer*.js、multi-sampled-texture-cache.js、xr-bridge.js 等。 |
platform/input/ |
输入设备:keyboard.js、mouse.js、touch-device.js、game-pads.js(手柄)、element-input.js |
platform/net/ |
HTTP 网络请求封装(http.js 等) |
platform/sound/ |
基于 Web Audio 的声音管理:manager.js(SoundManager)、sound.js、sound-instance.js、空间音效定位 |
src/scene/ —— 场景图与渲染描述(40 直接子项)文件(场景对象):scene.js(Scene 根)、graph-node.js(层级节点基类,Entity 的祖先)、camera.js、light.js、mesh.js/mesh-instance.js、model.js、sprite.js、skin.js/skin-instance.js/skin-instance-cache.js、morph*.js、texture-atlas.js、layer.js(渲染分层)、render.js、render-view.js、fog-params.js、camera-shader-params.js、shader-pass.js、picker-id.js、area-light-luts.js、constants.js。
子目录(渲染子系统):
renderer/(19 个文件,渲染心脏):renderer.js、forward-renderer.js、culler.js(视锥/遮挡裁剪)、layer-render-step.js、shadow-renderer.js/-directional.js/-local.js、shadow-map*.js、render-pass-*.js(forward / shadow / cookie / postprocessing / multi-view)、frame-pass-*.js、world-clusters-allocator.js(集群光照分配)、light-camera.js。shader-lib/:跨平台着色器系统,glsl/ 与 wgsl/ 双目录 + program-library.js/shader-chunks.js/shader-chunk-map.js/shader-utils.js/get-program-library.js。materials/:StandardMaterial 等材质模型与参数。graphics/:场景级图形辅助(如 post-effect 设置、相机渲染辅助)。lighting/:光照评估、集群光照、区域光 LUT。animation/:骨骼动画、蒙皮、混合。batching/:batch-manager.js 静态/动态合批。composition/:多相机/多视口合成。compress/:Draco/Basis/KTX2 解码集成。geometry/:程序化几何(盒/球/平面/胶囊等)与 GPU 几何工具。gsplat/ 与 gsplat-unified/:3D Gaussian Splatting 渲染(引擎 headline 特性)。immediate/:即时模式调试绘制(线/点)。particle-system/:粒子系统实现。skybox/:天空盒/IBL 处理。src/framework/ —— 应用层封装(26 直接子项)核心文件:application.js(Application 类,见上文注册 23 系统 + 25 handler)、app-base.js(AppBase 基类,定义主循环/事件/子系统注册)、app-options.js、entity.js(Entity = GraphNode + Component 容器)、component.js/registry.js/system.js(组件系统基类),scene-registry*.js、template.js、script.js、stats.js、globals.js、constants.js。
子目录(按能力分域):
components/(23 个组件系统目录 + component.js/system.js/registry.js):render、model、camera、light、animation、anim、script、sound、audio-listener、collision、rigid-body、joint、element、button、screen、scroll-view、scrollbar、sprite、layout-group、layout-child、particle-system、zone、gsplat。每个目录含 component.js + system.js。asset/:Asset、AssetRegistry、AssetReference、ResourceLoader。handlers/:25 个资源处理器(render/model/material/texture/animation/anim-clip/anim-state-graph/cubemap/shader/script/scene/container/gsplat/html/css/font/json/binary/folder/hierarchy/template/text/texture-atlas/sprite)。anim/:动画状态机、求值、混合树、动画控制器。physics/:与 ammo.js 的绑定(RigidBody/Collision/Joint 后端)。xr/:WebXR 管理(XrManager、XrInput、HitTest、DOM Overlay 等)。gsplat/:GSplat 资源/组件桥接。lightmapper/:光照贴图烘焙(lightmapper.js)。parsers/:材质 JSON 等解析。input/:ElementComponent 元素输入事件。font/、i18n/(国际化)、bundle/(资源包)、graphics/(拾取器 Picker)、script/(脚本注册/创建)。| 子模块 | 内容 |
|---|---|
exporters/ |
场景/模型导出器(如导出 glTF)。 |
gizmo/ |
编辑器用的变换 Gizmo(平移/旋转/缩放手柄)。 |
mini-stats/ |
轻量性能 HUD(FPS、绘制调用、内存)。 |
render-passes/ |
预置后处理 RenderPass(Bloom、SSAO、TAA、Color Grading 等)。 |
renderers/ |
辅助渲染器(如 2D/UI 渲染帮手)。 |
input/ |
额外输入辅助。 |
index.js |
extras 聚合导出(仅在显式 import extras 时进入产物)。 |
src/deprecated/ —— 向后兼容保留旧 API(如 deprecated.js 被标为 sideEffects),确保老项目升级不破。新代码不应再依赖。
Entity + Component + System 清晰解耦,23 种内置组件覆盖渲染/物理/UI/动画/音频/XR,扩展性强。store-on-no-clear、Pass 合并、Cube mipmap 延迟等自动优化,减少 GPU 同步开销,体现专业引擎的工程深度。playcanvas.js 可观),对极致轻量的 2D/小场景可能"杀鸡用牛刀";相较 Three.js 更重。shader-lib 的 chunk 化 + shader-processor-glsl.js 后处理,是同时支持 WebGL/WebGPU 又不分裂代码库的优雅方案——业界稀缺能力。frame-graph.js 中 store-on-no-clear、相邻 Pass 合并、cubemap mipmap 延迟生成,是引擎级"零成本抽象"的典范,提升真实帧率。scene/gsplat/ 与 gsplat-unified/ 原生支持 3D Gaussian Splats 渲染与 GSplatComponent,把 NeRF/辐射场资产当成一等公民——抓住 2023+ 三维重建浪潮。FramePassMultiView 把 VR 双眼 Pass 自动包裹为子图,享受与主 Pass 相同的合并/优化。platform/graphics/render-pass.js 与 extras/render-passes/ 让开发者以声明式 Pass 组合自定义渲染管线(类似 Unity Render Graph)。world-clusters-allocator.js 实现屏幕空间分簇光照,支持大量动态光源而不过载。platform/graphics/null/ 提供无头设备,使单元测试可脱离 GPU 运行图遍历逻辑——体现测试工程素养。sideEffects 精准标注保障 tree-shaking。| 项 | 值 |
|---|---|
| 仓库 | playcanvas/engine(组织 playcanvas,现属 Snap) |
| 版本 | 2.22.0-beta.17 |
| 许可 | MIT |
| 语言 | TypeScript/JavaScript(ESM,JSDoc 类型) |
| 构建 | turbo + esbuild(前端)、rollup-plugin-dts + tsc(类型)、typedoc(文档) |
| 核心模块 | core / platform(graphics,input,net,sound) / scene / framework / extras / deprecated |
| 组件系统 | 23 种 |
| 资源 Handler | 25 种 |
| 图形后端 | WebGL2 / WebGPU / NULL(无头测试) |
| 渲染编排 | FrameGraph(Pass 合并 + store-on-no-clear + mipmap 延迟) |
| 着色器 | shader-lib:glsl/ + wgsl/ 双实现,chunk 化拼装 |
| 亮点特性 | GSplat、WebXR、集群光照、Frame Graph 优化、双目标着色器 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。