- 游戏开发
- 图形学
【免费下载链接】turbulenz_engine
Turbulenz is a modular 3D and 2D game framework for making HTML5 powered games for browsers, desktops and mobile devices.
本篇技术指南围绕 Turbulenz 引擎(开源 3D/2D HTML5 游戏框架)的高层 GPU 粒子系统展开,系统讲解ParticleManager与ParticleArchetype两大核心对象:从数据驱动的 Archetype 描述格式、Manager 的注册/初始化/实例管理/序列化,到资源加载、性能指标与完整实战流程。读完本文,你将能够基于 tslib/particlesystem.ts 中的实现,独立搭建、驱动并监控一套完全由 GPU 运算的粒子系统,并复现 samples/tsscripts/templates/gpu_particles.ts 中的烟火、余烬与烟雾效果。
一、高层 GPU 粒子系统概述
ParticleManager(自 SDK 0.28.0 引入)用于创建和管理基于 GPU 的粒子系统。与直接操作顶点缓冲的低层粒子 API 不同,高层系统是**数据驱动(data-driven)**的:一个粒子系统完全由一份易于序列化的ParticleArchetype描述表示,开发者只需书写 JSON 风格的对象描述,即可生成可复用的粒子系统原型。
官方 API 文档(docs/source/jslibrary_api/particlemanager_api.rst)对ParticleManager的定义与全部方法、ParticleInstance属性做了详细说明;docs/source/jslibrary_api/particlearchetype_api.rst 则完整给出了 Archetype 的数据格式。
1.1 能力检测:GPU 粒子系统的先决条件
GPU 粒子系统的运行依赖顶点纹理采样,官方文档明确指出其至少需要 4 个顶点纹理单元(vertex texture units),而这不是 WebGL 一致性(conformance)所要求的特性,因此必须在GraphicsDevice上主动检测:
if (graphicsDevice.maxSupported("VERTEX_TEXTURE_UNITS") < 4) { // GPU Particle System cannot be used! }在真实示例 samples/tsscripts/templates/gpu_particles.ts 中,检测逻辑更进一步——在TurbulenzEngine.createGraphicsDevice({})之后立即检查maxSupported("VERTEX_TEXTURE_UNITS") === 0,若设备不支持则直接弹出错误并中止初始化。此外,该示例还加载了particles-default-update.cgfx、particles-default-render.cgfx等着色器(对应 assets/shaders 目录),这些着色器正是粒子状态在 GPU 上更新与渲染的载体。
1.2 系统架构总览
下图为官方文档中的高层 GPU 粒子系统结构图,展示了ParticleManager与各组件之间的关系:
从源码结构(tslib/particlesystem.ts)看,一个高层粒子系统由以下可替换组件构成:
- Renderer(渲染器):负责把粒子状态绘制到屏幕上,决定混合模式(alpha/additive/opaque)。
- Updater(更新器):负责在 GPU 上推进粒子物理状态(速度、加速度、阻力等)。
- Synchronizer(同步器):负责管理发射器的启停与系统内部时钟的同步。
- Emitter(发射器):定义粒子发射的速率、爆发数量、位置、速度等参数。
- Animation System(动画系统):定义粒子可用的属性通道(颜色、缩放、旋转、帧),以及粒子动画注册表。
- Geometry(几何体):粒子使用的顶点/索引缓冲,可在多个系统间共享。
这些组件全部通过ParticleManager的注册机制挂载,以名字为键被 Archetype 引用,实现了"组件可插拔"的扩展架构。
二、ParticleArchetype:粒子系统的数据描述
ParticleArchetype用于完整描述一个粒子系统。官方文档给出了其 JSON 数据格式的骨架与全部字段默认值,下面逐一展开说明。
2.1 完整描述骨架
{ // Properties of the ParticleSystem system: { center : [0, 0, 0], halfExtents : [1, 1, 1], zSorted : false, maxSortSteps : 136, trackingEnabled: false }, // Properties of the ParticleRenderer renderer: { name: "default" .. renderer parameters }, // Properties of the ParticleUpdater updater: { name: "default" .. updater parameters }, // Properties of the ParticleSynchronizer synchronizer: { name: "default" .. synchronization parameters }, // Animation system definition. animationSystem: "default", // Pre-packed textures. packedTexture0: null, ... packedTextureN: null // Particle descriptions. particles: { "particle-name": { // Particle animation definition. animation: null, // Particle animation tweaks. tweaks: null, // Per particle textures when not using pre-packed textures. texture0: null, ... texture4: null, // Per particle uv-maps when using pre-packed textures. texture-uv0: null, ... texture-uvN: null } ... }, // ParticleEmitter descriptions. emitters: [ { name: "default", ... emitter parameters } ... ] }值得强调的是:该描述并非所有字段都必须填写。作为数据驱动 API,粒子系统的各个组件会自行校验输入结构,缺失字段自动用默认值补齐,并在输入错误时输出有用的错误/警告信息。上面的取值即为 Archetype 描述的基础默认值。
2.2 system 参数:粒子系统本体
system定义实例化该 Archetype 时创建的ParticleSystem参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
center | [0, 0, 0] | 粒子系统局部范围(extents)的中心。extents 限定粒子在系统内的位置范围,并为Scene提供剔除(culling)非可见系统的依据 |
halfExtents | [1, 1, 1] | 粒子系统的局部半范围 |
maxParticles | 由发射器自动推算 | 系统可容纳的最大粒子数,绝对上限为 65536;若未指定,将从 Archetype 的发射器推算 |
maxSpeed | 由发射器自动推算 | 粒子在局部坐标下能达到的最大速度,用于将粒子速度归一化存储进 GPU 纹理 |
maxLifeTime | 由发射器自动推算 | 系统中任何粒子能存活的最长时间,用于将粒子生命期归一化存储进 GPU 纹理 |
zSorted | false | 系统视图是否进行 z 排序以获得正确的 alpha 混合。开启后排序在 GPU 上通过一系列逐帧迭代改进排序的 draw call 完成,对较大系统代价可能很严重 |
maxSortSteps | 136 | 每帧用于排序粒子系统的最多 draw call 数。实际数量不会超过完全排序所需量(136恰是完整排序 65536 个粒子所需次数,即默认值对所有maxParticles都表示"完全排序") |
trackingEnabled | false | 为 true 时粒子可被要求进行 CPU 协同模拟,以支持更复杂的发射器。官方注明:没有任何预定义发射器需要此选项 |
2.3 renderer 参数:渲染器选择
renderer.name(默认"default")引用一个已注册的ParticleRenderer。官方文档明确列出了ParticleManager.create时默认注册的 4 个渲染器:
"default":使用alpha混合模式的默认粒子渲染器;"alpha":与"default"相同;"additive":使用additive(加法)混合模式的默认粒子渲染器;"opaque":使用opaque(不透明)混合模式的默认粒子渲染器。
从源码看,这 4 个渲染器确实在 tslib/particlesystem.ts 中被依次注册,其中additive与opaque通过DefaultParticleRenderer.create.bind(null, graphicsDevice, shaderManager, "additive"/"opaque")绑定不同混合模式。各渲染器支持的 Archetype 参数详见 docs/source/jslibrary_api/particlerenderer_api.rst 中的DefaultParticleRenderer一节,其createUserData函数常用于把发射器中的renderUserData对象转换为粒子的真实userData整数位域。
2.4 updater 与 synchronizer 参数
updater.name(默认"default"):引用已注册的ParticleUpdater。默认注册"default"(即DefaultParticleUpdater)。源码中还额外注册了"clamped"与"wrapped"两种更新模式(见 tslib/particlesystem.ts),它们通过DefaultParticleUpdater.create.bind(null, graphicsDevice, shaderManager, "clamped"/"wrapped")区分采样/寻址行为。更新器支持的 Archetype 参数见 docs/source/jslibrary_api/particleupdater_api.rst。synchronizer.name(默认"default"):引用已注册的ParticleSynchronizer,默认即DefaultParticleSynchronizer,参数见 docs/source/jslibrary_api/particlesynchronizer_api.rst。
2.5 animationSystem 与 packedTexture
animationSystem(默认"default"):Archetype 中粒子动画所使用的动画系统。默认动画系统与所有预定义更新器、渲染器兼容。packedTexture0..N:可指定预打包纹理(pre-packed texture),该纹理包含 Archetype 中所有粒子的完整翻页(flip-book)动画,将替代 Manager 运行时生成的打包纹理。packedTexture0也可简写为packedTexture。若定义了打包纹理,粒子可用texture-uv0..N字段指定归一化 UV 矩形,将粒子动画的 UV 矩形重新映射到打包纹理的子区域(对应ParticleBuilder.compile的uvMap参数);该字段缺省时隐含[0, 0, 1, 1]。若未指定打包纹理,则粒子应自行指定纹理,由 Manager 在运行时打包。
2.6 particles 与 emitters
particles是一份命名粒子动画字典,供发射器按名字引用,每个粒子的字段包括:
animation(默认"default"):已注册粒子动画的名字。默认粒子动画是单帧、无属性值的动画(系统默认值填充),报告生命期为0;tweaks:应用到该粒子动画上的微调字典(对应ParticleBuilder.compile的tweaks参数);texture-uv0..N:打包纹理下的归一化 UV 矩形映射;使用打包纹理且缺省时为[0, 0, 1, 1];不使用打包纹理时该字段禁止出现;texture0..N:单个粒子(含完整翻页动画)使用的纹理路径字符串;使用打包纹理时禁止出现;缺省时使用TextureManager的默认纹理。
emitters是粒子系统 Archetype 的发射器数组。每个发射器的name(默认"default")引用已注册的ParticleEmitter,默认即DefaultParticleEmitter,其支持的参数见 docs/source/jslibrary_api/particleemitter_api.rst。
三、ParticleManager 生命周期:创建、初始化与销毁
ParticleManager对象的方法在 docs/source/jslibrary_api/particlemanager_api.rst 中逐一说明,其源码实现位于 tslib/particlesystem.ts。生命周期如下:
3.1 create:创建 Manager
var particleManager = ParticleManager.create(graphicsDevice, textureManager, shaderManager);三个参数分别是GraphicsDevice、TextureManager、ShaderManager对象。从源码 tslib/particlesystem.ts 可见,create会初始化各组件注册表(renderers、updaters、systems、particles、synchronizers、emitters、geometries、archetypes)、创建系统/视图共享渲染上下文(SharedRenderContext)、TimeoutQueue(用于管理短时效果实例的过期回收),并注册全部默认组件(详见第五节)。
3.2 initialize:初始化并绑定场景
particleManager.initialize(scene, passIndex);必须在创建任何粒子系统之前调用。scene是 Manager 协作的Scene对象;passIndex是渲染器定义的transparent(透明)可渲染对象的通道索引。例如使用DefaultRendering时设为renderer.passIndex.transparent。该索引用于定义 draw call 的排序:粒子系统作为透明的介质,将在普通几何体之后渲染,并与其他透明几何体一起在Scene中做 z 排序。
实战示例 samples/tsscripts/templates/gpu_particles.ts 中即采用ForwardRendering:
renderer = ForwardRendering.create(graphicsDevice, mathDevice, shaderManager, effectManager, {}); // particleManager 使用要协作的 Scene 初始化, // 并传入渲染器的透明 pass 索引,使粒子系统与其他透明元素一起排序。 particleManager.initialize(scene, renderer.passIndex.transparent);若未初始化就调用依赖初始化状态的方法,源码会直接抛出"ParticleManager not initialized"(见 tslib/particlesystem.ts)。
3.3 update:推进内部时钟
particleManager.update(timeStep);timeStep是加到 Manager 内部计时器上的流逝时间(秒)。该调用会更新所有粒子系统用于追踪时间流逝的内部时钟,并自动剔除(cull)已过期的短时实例——即使它们处于屏幕外或从未可见。官方文档特别说明:无需将 update 绑定到固定时间步长,因为这不影响系统被渲染时的更新方式;任何固定时间步长的系统模拟都是各系统 Synchronizer 自己的职责。
在示例主循环中(samples/tsscripts/templates/gpu_particles.ts),deltaTime计算后立即调用particleManager.update(deltaTime),并注释说明它会同时"从 Manager 中移除任何过期的 ParticleInstance"。
3.4 destroy:彻底销毁
particleManager.destroy();销毁 Manager 及与其关联的所有状态:销毁每个已使用 Archetype 的所有状态(含全部现有粒子实例)、共享纹理与渲染目标状态,释放所有已分配的 GPU 内存,并确保 CPU 上分配的内存可被垃圾回收。调用后 Manager 及其创建的任何粒子实例均不得再使用。
源码实现 tslib/particlesystem.ts 依次:销毁所有已初始化的 Archetype 及其实例、销毁所有几何体与视图池、清空各组件注册表与 Archetype 列表、销毁系统/视图共享上下文与TimeoutQueue。示例卸载回调中也调用了particleManager.destroy()并置空引用(samples/tsscripts/templates/gpu_particles.ts)。
四、注册机制:让组件可替换、可扩展
高层粒子系统的核心设计是组件注册表 + 名称引用。所有注册方法都接受"名字 + 描述/构造器",Archetype 通过名字引用它们。源码中的注册表实现见 tslib/particlesystem.ts。
4.1 注册粒子动画与动画系统
particleManager.registerParticleAnimation(definition); // definition 的 name 用于粒子系统创建时的查找 particleManager.registerAnimationSystem(name, definition);源码 tslib/particlesystem.ts 显示,两者都会用ParticleBuildError收集解析错误/警告,失败时抛出"System parse failed!"或"Particle parse failed!"。ParticleManager.create默认注册的动画系统包含四个属性通道:color(float4)、scale(float2)、rotation(float)、frame(texture0,compress: "half"),并注册了名为"default"的单帧粒子动画{ animation: [{}] }。
在 samples/tsscripts/templates/gpu_particles.ts 中,示例注册了"fire"、"smoke"、"portal"三个粒子动画。以"fire"为例:通过"texture0-size": [4, 2]定义用于归一化 UV 坐标的纹理尺寸(实际纹理 512x512,但动画映射到上半部分,可"假装"为 4x2 简化坐标),然后给出 8 帧翻页序列texture0,以及带时间戳的动画关键帧(frame、color通道随时间变化,实现渐隐渐显)。
4.2 注册几何体
particleManager.registerGeometry(name, constructor);constructor负责构造共享几何实例,参数为GraphicsDevice与初始粒子容量。源码注册的默认几何体即DefaultParticleRenderer.prototype.createGeometry(gd, num, true)(shared=true,见 tslib/particlesystem.ts)。
4.3 注册渲染器、更新器、同步器、发射器
四者的注册签名高度一致,均采用(name, parser, compressor, loader, constructor)模式(同步器/发射器还各有补充参数):
particleManager.registerRenderer(name, parser, compressor, loader, constructor, geometry); particleManager.registerUpdater(name, parser, compressor, loader, constructor); particleManager.registerSynchronizer(name, parser, compressor, constructor); particleManager.registerEmitter(name, parser, compressor, getBurstCount, getTotalLifeTime, constructor);各部分职责:
parser:接收ParticleBuildError对象与压缩后的 JSON 对象(即 Archetype 中该组件可配置的值),校验输入正确性、报告警告/错误,返回应用于该组件实例的完整配置项集合(必要时含默认值);compressor:接收完整配置项集合,返回其最小化表示。官方明确要求parser 与 compressor 互为逆操作;loader(渲染器/更新器):接收完整配置项、加载着色器的函数(参数为着色器路径)、加载纹理的函数(参数为纹理路径),为渲染器/更新器所需的全部着色器和纹理调用加载函数,这些加载是异步处理的;constructor:无参数构造该组件的实例;geometry(渲染器):与该渲染器兼容的已注册ParticleGeometry名;getBurstCount/getTotalLifeTime(发射器):前者根据解析后的发射器 Archetype 与激活时间返回爆发次数(使发射器在给定时间后自动禁用);后者在给定爆发次数下返回发射器生命周期上界(最坏情况下最后一个粒子被杀死的时间),参数为系统 Archetype、发射器 Archetype 与爆发次数。
ParticleManager.create中这些默认组件的完整注册过程见 tslib/particlesystem.ts。值得注意的扩展点:除了"default",源码还注册了"clamped"/"wrapped"更新器,开发者可仿照该模式注册自己的渲染器、更新器、同步器与发射器,实现自定义粒子行为。
4.4 对象池机制
从源码 tslib/particlesystem.ts 可见,发射器与同步器维护各自的pool数组:getEmitter/getSynchronizer优先从池中弹出对象,池空时才调用构造器新建;实例销毁时通过releaseSynchronizer将发射器/同步器复位后压回池中(tslib/particlesystem.ts)。系统与视图同样有池(systemPool、viewPool)。这一机制显著降低了短时效果的分配开销。
五、实例管理:创建、变换、入场景与销毁
ParticleInstance封装了当前系统的运行时状态,由 Manager 创建。官方文档与源码共同确立了以下实例 API。
5.1 实例创建四件套
var instance = particleManager.createInstance(archetype, timeout, baseTechniqueParametersList); var instance = particleManager.createTimedInstance(archetype, activeTime, baseTechniqueParametersList); var instance = particleManager.createBurstInstance(archetype, burstCount, baseTechniqueParametersList); var instance = particleManager.createMultiBurstInstance(archetype, burstCounts, baseTechniqueParametersList); var instance = particleManager.createChildInstance(instance, timeout, baseTechniqueParametersList);createInstance:从已预加载资源的 Archetype 创建实例,发射器自动启用。若指定timeout,则发射器会调用其timeout函数,使效果在实例被移除时自然结束。baseTechniqueParametersList是可选的TechniqueParameters列表,在系统特定参数设置前应用到实例的ParticleRenderable上。createTimedInstance:辅助函数,通过合适的emitter.burst(N)调用使发射器在activeTime期间保持激活,并设置足够大的 timeout 使所有粒子在实例移除前自然淡出。源码 tslib/particlesystem.ts 显示其实现为:遍历发射器计算各发射器的爆发次数与最大生命周期,再调用createInstance并对每个发射器执行burst(burstCounts[i])。createBurstInstance:辅助函数,发射器恰好爆发burstCount次(缺省为1,即单次爆发),timeout 足够大以保证粒子自然淡出。实现见 tslib/particlesystem.ts。createMultiBurstInstance:与上者相同,但burstCounts为数组,每个发射器可指定不同的爆发次数(源码断言数组长度必须等于发射器数量,见 tslib/particlesystem.ts)。createChildInstance:创建一个不拥有自己粒子系统、而是引用另一实例的"子实例",提供父实例系统的额外一次渲染。这在场景中多处渲染同一粒子系统时能大幅节省开销。子实例的创建与销毁均被记录在父实例的children链上,父实例销毁时子实例自动销毁。子实例不适用粒子实例通常的淡入/淡出行为,它纯粹是既有实例的额外渲染;timeout 缺省时继承父实例的 timeout。
5.2 变换与入场景
particleManager.addInstanceToScene(instance, parent); // parent 省略时作为场景根节点 particleManager.removeInstanceFromScene(instance);ParticleInstance.renderable的局部变换(local transform)可用于移动/平移/缩放整个粒子系统。示例中(samples/tsscripts/templates/gpu_particles.ts)每帧以generationSpeed(默认 50 次/秒)的速度在世界范围随机位置生成实例,用instance.renderable.setLocalTransform(mathDevice.m43Build(...))设置随机缩放与位置,再addInstanceToScene(instance, particleNode)挂到共享的particleNode场景节点下,从而演示"同一个 Archetype 在场景各处复用"。
需要强调:不要手动把 renderable 加入/移出Scene,应始终使用addInstanceToScene/removeInstanceFromScene(官方文档的 Read Only 说明)。
5.3 实例与 Archetype 的销毁
particleManager.destroyInstance(instance); particleManager.clear(archetype); // archetype 可选 particleManager.destroyArchetype(archetype); particleManager.replaceArchetype(oldArchetype, newArchetype);destroyInstance:销毁实例,从场景移除并放回池中供同一 Archetype 的后续实例复用。源码 tslib/particlesystem.ts 显示它会递归销毁所有子实例、从TimeoutQueue移除(若已入队)、释放视图到viewPool、将系统放回systemPool、把实例压回instancePool。clear:销毁 Manager 关联的全部实例;若指定 Archetype 则只销毁该 Archetype 的实例。注意它不同于destroyArchetype——运行时打包纹理与对象池等生成状态会保留;若确定不再使用该 Archetype,应使用destroyArchetype。destroyArchetype:销毁某 Archetype 的所有实例及生成数据(运行时打包纹理、对象池等),完全重置该 Archetype 状态,之后可像从未使用过一样再次实例化。但它并不真正销毁 Archetype 对象本身,Archetype 仍可继续使用。replaceArchetype:用新 Archetype就地重建所有使用旧 Archetype 的粒子实例。该特性不追求性能,但对游戏内编辑器做粒子系统的实时更新极为有用。由于粒子系统范围(extents)、粒子容量(capacity)等属性不可变,这是影响当前在用系统这类属性的唯一简便途径。既有实例引用保持有效(实例对象被复用),新实例的发射器将全部启用——因此不适用于已创建的短时效果。
示例中的refreshArchetype函数(samples/tsscripts/templates/gpu_particles.ts)正是这一能力的典型应用:把描述中所有发射器的burstMin/burstMax乘以缩放因子,parseArchetype生成新 Archetype,replaceArchetype替换在用实例,最后destroyArchetype回收旧 Archetype,实现了运行时"增减粒子数量"的编辑器式体验。
六、资源加载、解析与序列化
6.1 loadArchetype:预加载全部依赖资源
particleManager.loadArchetype(archetype, onload);加载 Archetype 所需的全部资源(纹理、着色器)。必须在从 Archetype 创建系统之前执行,并假定所有资源加载完成后才能创建系统。onload可选,接收已完全加载的 Archetype 作为参数。
源码实现 tslib/particlesystem.ts 中有个巧妙细节:requestCount初始设为 1,保证所有 load 调用先于 onload 触发(即使资源已缓存、回调同步完成);同时用requested字典去重,避免对同一资源发起重复请求(规避 textureManager/shadermanager 对同一资源的回调重复调用问题);最终分别调用渲染器与更新器的load,再加载打包纹理与各粒子的纹理。
示例中(samples/tsscripts/templates/gpu_particles.ts)在加载循环前对两个 Archetype 调用loadArchetype,随后loadingLoop轮询textureManager.getNumPendingTextures() === 0 && shaderManager.getNumPendingShaders() === 0才进入主循环。
6.2 parseArchetype:解析为可用的完整对象
var archetype = particleManager.parseArchetype(description);把 Archetype 描述解析为 Manager 可用的完整对象,允许只指定与默认值不同的字段。解析失败时抛出包含各解析阶段全部警告与错误的异常;将 Manager 的failOnWarnings设为false可关闭"警告即失败"行为。原始描述不会被修改,可重复使用。
6.3 压缩与序列化
var description = particleManager.compressArchetype(archetype); var serializedString = particleManager.serializeArchetype(archetype); var archetype = particleManager.deserializeArchetype(jsonString);compressArchetype:压缩 Archetype,返回可恢复出原 Archetype 的最小化描述,用于节省保存/传输空间(序列化时也会使用),原 Archetype 保持不变;serializeArchetype:先压缩再序列化为 JSON 字符串,是"低成本保存 Archetype 到文件"的方法;deserializeArchetype:从压缩 JSON 表示反序列化,并解析为可直接用于 Manager 的完整 Archetype 对象。
官方文档还补充:Archetype 的序列化/反序列化应通过ParticleManager的这些方法完成,因为它们会同时压缩描述以减小文件体积。
七、性能监控:gatherMetrics 与 gatherInstanceMetrics
高层粒子系统的内存与实例行为高度透明,官方文档与示例均展示了指标采集用法。
7.1 gatherMetrics
var metrics = particleManager.gatherMetrics(archetype); // archetype 可选不提供 Archetype 时,返回对象含:
numInitializedArchetypes:已初始化的 Archetype 数;numPooledViews/numPooledSynchronizers/numPooledEmitters:池中视图/同步器/发射器数;numPooledSystems/numPooledInstances:池中系统/实例数;numActiveInstances:正在被更新与渲染的实例数(当前可见);numAllocatedInstances:已分配系统与视图、占用 CPU/GPU 空间的实例数(至少可见过一次);numInstances:作为 Scene 一部分存活的实例数。
提供 Archetype 时只统计该 Archetype 的实例(并额外含activeParticleCount)。官方文档给出了三条约束关系:创建的ParticleInstance总数为numInstances + numPooledInstances;numAllocatedInstances ≤ numInstances;numActiveInstances ≤ numAllocatedInstances。源码实现见 tslib/particlesystem.ts,其中"active"通过instance.system.lastTime === time(本帧是否被更新)判定。
7.2 gatherInstanceMetrics
var metrics = particleManager.gatherInstanceMetrics(archetype); // archetype 可选返回对象数组,每项包含:instance(关联的ParticleInstance)、allocated(是否已分配系统与视图并占用 CPU/GPU 空间)、active(是否正在被更新与渲染)。若实例active,则必然allocated。
示例主循环将两类指标都用于实时诊断(samples/tsscripts/templates/gpu_particles.ts):用gatherMetrics()输出文本指标到屏幕;用gatherInstanceMetrics()遍历全部实例,按 active(绿)、allocated(黄)、未分配(红)三色在小地图(minimap)上绘制实例位置,直观展示粒子系统的懒分配(lazy allocation)行为——系统与视图只在实例首次可见时才分配,离屏实例几乎零开销。
八、ParticleInstance 对象
ParticleInstance由ParticleManager创建,封装当前系统的状态,官方文档定义其只读属性如下:
renderable(只读,始终存在):该实例的ParticleRenderable。可用于通过局部变换移动/平移/缩放粒子系统。注意不要手动将其加入或移出Scene,应使用addInstanceToScene/removeInstanceFromScene;synchronizer(只读,始终存在):该实例的ParticleSynchronizer。可用于在运行时为特定实例添加/移除发射器;system(只读):该实例的ParticleSystem。采用懒分配——实例首次可见时才分配,也可能永远不会存在;timeout(只读):实例创建时使用的 timeout 值。
从源码 tslib/particlesystem.ts 看,实例还内部维护creationTime、queued、parent/children(父子实例链)与lazySystem等字段,createChildInstance与destroyInstance正是通过这些字段维护父子关系与级联回收。
九、端到端实战:从描述到渲染的完整工作流
综合 samples/tsscripts/templates/gpu_particles.ts 与官方文档,高层 GPU 粒子系统的标准使用流程可归纳为七步:
- 能力检测:创建
GraphicsDevice后检查maxSupported("VERTEX_TEXTURE_UNITS") >= 4; - 创建 Manager:
ParticleManager.create(graphicsDevice, textureManager, shaderManager); - 注册动画:
registerParticleAnimation注册带纹理翻页与关键帧动画的粒子动画; - 解析 Archetype:书写数据描述(
system/renderer/updater/particles/emitters),parseArchetype得到可用 Archetype; - 加载与初始化:
loadArchetype(archetype)预加载纹理/着色器,particleManager.initialize(scene, renderer.passIndex.transparent)绑定场景与透明通道; - 每帧驱动:主循环中
particleManager.update(deltaTime)推进时钟,按需createInstance/createBurstInstance生成短时效果,instance.renderable.setLocalTransform(...)设定位置缩放,addInstanceToScene(instance, parentNode)挂入场景; - 监控与回收:
gatherMetrics/gatherInstanceMetrics观察实例状态,destroyInstance/clear回收,编辑器场景下用replaceArchetype热更新;退出时particleManager.destroy()释放全部资源。
示例中的描述文件展示了丰富的发射器配置可供参考:emittance(rate发射速率、burstMin/burstMax每次爆发数量、delay延迟)、particle(lifeTimeScaleMin/Max、renderUserData中的facing: "billboard"/"velocity"、随机化开关)、position(radiusMax、radiusDistribution: "normal"、spherical球状分布)、velocity(conicalSpread锥形扩散、speedMin/Max)等(samples/tsscripts/templates/gpu_particles.ts),并演示了打包纹理(packedTexture)与运行时打包纹理(每个粒子自带texture)两种纹理方案。
十、总结
Turbulenz 引擎的高层粒子系统 API 是一套数据驱动、组件可插拔、资源可序列化、行为可观测的完整粒子解决方案:
- 数据驱动:一个
ParticleArchetype描述即可完整定义粒子系统,缺失字段自动补齐,组件级校验提供清晰错误/警告; - 组件可插拔:Renderer/Updater/Synchronizer/Emitter/Geometry 通过注册表按名引用,可自由扩展;
- 资源友好:Archetype 可压缩、序列化、反序列化,纹理支持预打包与运行时打包两种方案;
- 性能透明:系统/视图懒分配、对象池复用、
TimeoutQueue自动回收短时实例,配合gatherMetrics/gatherInstanceMetrics可精确掌控内存与活跃度。
对于需要大量特效(烟火、爆炸、弹幕、粒子尾迹)的 HTML5 游戏,这套 API 让开发者可以用纯数据的方式描述效果、以极低开销批量实例化,并实时监控其运行状态。进一步可阅读 docs/source/jslibrary_api/particlemanager_api.rst 与 docs/source/jslibrary_api/particlearchetype_api.rst 获取方法级细节,并结合 samples/templates/gpu_particles.html 与 samples/tsscripts/templates/gpu_particles.ts 直接运行体验。
- 游戏开发
- 图形学
【免费下载链接】turbulenz_engine
Turbulenz is a modular 3D and 2D game framework for making HTML5 powered games for browsers, desktops and mobile devices.
相关推荐
Cocos引擎粒子系统与GPU实例化:大规模粒子效果优化
Cocos引擎粒子系统与GPU实例化:大规模粒子效果优化 引言:粒子系统的性能挑战 在游戏开发中,粒子系统(Particle System)是创建火焰、烟雾、爆
游戏开发图形学3D渲染告别卡顿!Cocos引擎粒子系统GPU加速实战指南
告别卡顿!Cocos引擎粒子系统GPU加速实战指南 你是否还在为粒子特效导致的游戏帧率暴跌而烦恼?当同时渲染上千个粒子时,CPU计算往往成为性能瓶颈。本文将详解
游戏开发图形学3D渲染OpenToonz特效系统完全指南:从基础滤镜到高级粒子引擎
OpenToonz特效系统完全指南:从基础滤镜到高级粒子引擎 想要打造专业级2D动画效果吗?OpenToonz特效系统正是您需要的强大工具!作为一款开源的全功能
桌面应用图形学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考