@codexo/exojs-particles 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/esm/ParticleSystem.d.ts +212 -0
- package/dist/esm/ParticleSystem.js +570 -0
- package/dist/esm/ParticleSystem.js.map +1 -0
- package/dist/esm/distributions/BoxArea.d.ts +17 -0
- package/dist/esm/distributions/BoxArea.js +48 -0
- package/dist/esm/distributions/BoxArea.js.map +1 -0
- package/dist/esm/distributions/CircleArea.d.ts +19 -0
- package/dist/esm/distributions/CircleArea.js +33 -0
- package/dist/esm/distributions/CircleArea.js.map +1 -0
- package/dist/esm/distributions/ColorGradient.d.ts +40 -0
- package/dist/esm/distributions/ColorGradient.js +72 -0
- package/dist/esm/distributions/ColorGradient.js.map +1 -0
- package/dist/esm/distributions/ConeDirection.d.ts +28 -0
- package/dist/esm/distributions/ConeDirection.js +44 -0
- package/dist/esm/distributions/ConeDirection.js.map +1 -0
- package/dist/esm/distributions/Constant.d.ts +17 -0
- package/dist/esm/distributions/Constant.js +35 -0
- package/dist/esm/distributions/Constant.js.map +1 -0
- package/dist/esm/distributions/Curve.d.ts +30 -0
- package/dist/esm/distributions/Curve.js +53 -0
- package/dist/esm/distributions/Curve.js.map +1 -0
- package/dist/esm/distributions/Distribution.d.ts +45 -0
- package/dist/esm/distributions/LineSegment.d.ts +15 -0
- package/dist/esm/distributions/LineSegment.js +27 -0
- package/dist/esm/distributions/LineSegment.js.map +1 -0
- package/dist/esm/distributions/Range.d.ts +12 -0
- package/dist/esm/distributions/Range.js +19 -0
- package/dist/esm/distributions/Range.js.map +1 -0
- package/dist/esm/distributions/VectorRange.d.ts +20 -0
- package/dist/esm/distributions/VectorRange.js +31 -0
- package/dist/esm/distributions/VectorRange.js.map +1 -0
- package/dist/esm/distributions/index.d.ts +12 -0
- package/dist/esm/gpu/ParticleGpuState.d.ts +57 -0
- package/dist/esm/gpu/ParticleGpuState.js +535 -0
- package/dist/esm/gpu/ParticleGpuState.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +32 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/modules/AlphaFadeOverLifetime.d.ts +24 -0
- package/dist/esm/modules/AlphaFadeOverLifetime.js +64 -0
- package/dist/esm/modules/AlphaFadeOverLifetime.js.map +1 -0
- package/dist/esm/modules/ApplyForce.d.ts +20 -0
- package/dist/esm/modules/ApplyForce.js +48 -0
- package/dist/esm/modules/ApplyForce.js.map +1 -0
- package/dist/esm/modules/AttractToPoint.d.ts +27 -0
- package/dist/esm/modules/AttractToPoint.js +73 -0
- package/dist/esm/modules/AttractToPoint.js.map +1 -0
- package/dist/esm/modules/BurstSpawn.d.ts +53 -0
- package/dist/esm/modules/BurstSpawn.js +93 -0
- package/dist/esm/modules/BurstSpawn.js.map +1 -0
- package/dist/esm/modules/ColorOverLifetime.d.ts +22 -0
- package/dist/esm/modules/ColorOverLifetime.js +65 -0
- package/dist/esm/modules/ColorOverLifetime.js.map +1 -0
- package/dist/esm/modules/ColorOverSpeed.d.ts +27 -0
- package/dist/esm/modules/ColorOverSpeed.js +86 -0
- package/dist/esm/modules/ColorOverSpeed.js.map +1 -0
- package/dist/esm/modules/DeathModule.d.ts +24 -0
- package/dist/esm/modules/DeathModule.js +25 -0
- package/dist/esm/modules/DeathModule.js.map +1 -0
- package/dist/esm/modules/Drag.d.ts +20 -0
- package/dist/esm/modules/Drag.js +43 -0
- package/dist/esm/modules/Drag.js.map +1 -0
- package/dist/esm/modules/OrbitalForce.d.ts +28 -0
- package/dist/esm/modules/OrbitalForce.js +65 -0
- package/dist/esm/modules/OrbitalForce.js.map +1 -0
- package/dist/esm/modules/RateSpawn.d.ts +41 -0
- package/dist/esm/modules/RateSpawn.js +75 -0
- package/dist/esm/modules/RateSpawn.js.map +1 -0
- package/dist/esm/modules/RepelFromPoint.d.ts +24 -0
- package/dist/esm/modules/RepelFromPoint.js +76 -0
- package/dist/esm/modules/RepelFromPoint.js.map +1 -0
- package/dist/esm/modules/RotateOverLifetime.d.ts +20 -0
- package/dist/esm/modules/RotateOverLifetime.js +41 -0
- package/dist/esm/modules/RotateOverLifetime.js.map +1 -0
- package/dist/esm/modules/ScaleOverLifetime.d.ts +26 -0
- package/dist/esm/modules/ScaleOverLifetime.js +59 -0
- package/dist/esm/modules/ScaleOverLifetime.js.map +1 -0
- package/dist/esm/modules/SpawnModule.d.ts +30 -0
- package/dist/esm/modules/SpawnModule.js +31 -0
- package/dist/esm/modules/SpawnModule.js.map +1 -0
- package/dist/esm/modules/SpawnOnDeath.d.ts +24 -0
- package/dist/esm/modules/SpawnOnDeath.js +47 -0
- package/dist/esm/modules/SpawnOnDeath.js.map +1 -0
- package/dist/esm/modules/Turbulence.d.ts +30 -0
- package/dist/esm/modules/Turbulence.js +122 -0
- package/dist/esm/modules/Turbulence.js.map +1 -0
- package/dist/esm/modules/UpdateModule.d.ts +95 -0
- package/dist/esm/modules/UpdateModule.js +66 -0
- package/dist/esm/modules/UpdateModule.js.map +1 -0
- package/dist/esm/modules/VelocityOverLifetime.d.ts +30 -0
- package/dist/esm/modules/VelocityOverLifetime.js +84 -0
- package/dist/esm/modules/VelocityOverLifetime.js.map +1 -0
- package/dist/esm/modules/WgslContribution.d.ts +81 -0
- package/dist/esm/modules/WgslContribution.js +34 -0
- package/dist/esm/modules/WgslContribution.js.map +1 -0
- package/dist/esm/modules/index.d.ts +22 -0
- package/dist/esm/particlesBuildInfo.d.ts +15 -0
- package/dist/esm/particlesBuildInfo.js +8 -0
- package/dist/esm/particlesBuildInfo.js.map +1 -0
- package/dist/esm/particlesExtension.d.ts +24 -0
- package/dist/esm/particlesExtension.js +49 -0
- package/dist/esm/particlesExtension.js.map +1 -0
- package/dist/esm/public.d.ts +9 -0
- package/dist/esm/register.d.ts +1 -0
- package/dist/esm/register.js +43 -0
- package/dist/esm/register.js.map +1 -0
- package/dist/esm/renderers/WebGl2ParticleRenderer.d.ts +45 -0
- package/dist/esm/renderers/WebGl2ParticleRenderer.js +325 -0
- package/dist/esm/renderers/WebGl2ParticleRenderer.js.map +1 -0
- package/dist/esm/renderers/WebGpuParticleRenderer.d.ts +48 -0
- package/dist/esm/renderers/WebGpuParticleRenderer.js +553 -0
- package/dist/esm/renderers/WebGpuParticleRenderer.js.map +1 -0
- package/dist/esm/renderers/glsl/particle.frag.js +4 -0
- package/dist/esm/renderers/glsl/particle.frag.js.map +1 -0
- package/dist/esm/renderers/glsl/particle.vert.js +4 -0
- package/dist/esm/renderers/glsl/particle.vert.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ParticleSystem } from '#ParticleSystem';
|
|
2
|
+
import { AbstractWebGpuRenderer } from '@codexo/exojs/rendering';
|
|
3
|
+
import type { WebGpuBackend } from '@codexo/exojs/rendering';
|
|
4
|
+
export declare class WebGpuParticleRenderer extends AbstractWebGpuRenderer<ParticleSystem> {
|
|
5
|
+
/**
|
|
6
|
+
* The particle system's transform is bound as a uniform and each particle is
|
|
7
|
+
* positioned system-locally, so this renderer never reads the shared transform
|
|
8
|
+
* storage; the plan player skips writing transform records for particle draws.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
readonly _consumesSharedTransform = false;
|
|
12
|
+
private readonly _drawCalls;
|
|
13
|
+
private _drawCallCount;
|
|
14
|
+
private readonly _uniformData;
|
|
15
|
+
private _device;
|
|
16
|
+
private _shaderModule;
|
|
17
|
+
private _uniformBindGroupLayout;
|
|
18
|
+
private _textureBindGroupLayout;
|
|
19
|
+
private _pipelineLayout;
|
|
20
|
+
private _uniformBuffer;
|
|
21
|
+
private _uniformBindGroup;
|
|
22
|
+
private _staticVertexBuffer;
|
|
23
|
+
private _instanceBuffer;
|
|
24
|
+
private _indexBuffer;
|
|
25
|
+
private _instanceBufferByteLength;
|
|
26
|
+
private _instanceData;
|
|
27
|
+
private _float32View;
|
|
28
|
+
private _uint32View;
|
|
29
|
+
private readonly _pipelines;
|
|
30
|
+
render(system: ParticleSystem): void;
|
|
31
|
+
flush(): void;
|
|
32
|
+
destroy(): void;
|
|
33
|
+
protected onConnect(backend: WebGpuBackend): void;
|
|
34
|
+
protected onDisconnect(): void;
|
|
35
|
+
private _ensureCapacity;
|
|
36
|
+
private _writeUniformData;
|
|
37
|
+
private _writeInstanceData;
|
|
38
|
+
/**
|
|
39
|
+
* Same atlas/UV-resolution as the WebGL2 path. Returns the per-frame
|
|
40
|
+
* (uvMin, uvMax) pairs derived from `system.frames` (or fallback to
|
|
41
|
+
* `system.textureFrame` when no atlas is declared), already flipY-
|
|
42
|
+
* adjusted for the current texture.
|
|
43
|
+
*/
|
|
44
|
+
private _uvMinsScratch;
|
|
45
|
+
private _uvMaxsScratch;
|
|
46
|
+
private _computeFrameUvs;
|
|
47
|
+
private _getPipeline;
|
|
48
|
+
}
|
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import { AbstractWebGpuRenderer, Texture, getWebGpuBlendState, stencilContentDepthStencilState } from '@codexo/exojs/rendering';
|
|
2
|
+
|
|
3
|
+
/// <reference types="@webgpu/types" />
|
|
4
|
+
const particleShaderSource = `
|
|
5
|
+
struct ProjectionUniforms {
|
|
6
|
+
projection: mat4x4<f32>,
|
|
7
|
+
translation: mat4x4<f32>,
|
|
8
|
+
flags: vec4<f32>,
|
|
9
|
+
localBounds: vec4<f32>, // quadMin.xy, quadSize.xy
|
|
10
|
+
uvBounds: vec4<f32>, // uvMin.xy, uvMax.xy
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
@group(0) @binding(0)
|
|
14
|
+
var<uniform> uniforms: ProjectionUniforms;
|
|
15
|
+
|
|
16
|
+
@group(1) @binding(0)
|
|
17
|
+
var particleTexture: texture_2d<f32>;
|
|
18
|
+
|
|
19
|
+
@group(1) @binding(1)
|
|
20
|
+
var particleSampler: sampler;
|
|
21
|
+
|
|
22
|
+
// Per-instance attributes (one entry per particle, 40 bytes total).
|
|
23
|
+
struct VertexInput {
|
|
24
|
+
@location(0) unitPosition: vec2<f32>, // per-vertex (static unit quad)
|
|
25
|
+
@location(1) translation: vec2<f32>,
|
|
26
|
+
@location(2) scale: vec2<f32>,
|
|
27
|
+
@location(3) rotation: f32,
|
|
28
|
+
@location(4) color: vec4<f32>,
|
|
29
|
+
@location(5) uvMin: vec2<f32>, // pre-resolved frame UV (top-left)
|
|
30
|
+
@location(6) uvMax: vec2<f32>, // pre-resolved frame UV (bottom-right)
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
struct VertexOutput {
|
|
34
|
+
@builtin(position) position: vec4<f32>,
|
|
35
|
+
@location(0) texcoord: vec2<f32>,
|
|
36
|
+
@location(1) color: vec4<f32>,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
@vertex
|
|
40
|
+
fn vertexMain(input: VertexInput) -> VertexOutput {
|
|
41
|
+
let quadMin = uniforms.localBounds.xy;
|
|
42
|
+
let quadSize = uniforms.localBounds.zw;
|
|
43
|
+
|
|
44
|
+
let localPosition = quadMin + (input.unitPosition * quadSize);
|
|
45
|
+
let radians = radians(input.rotation);
|
|
46
|
+
let sinValue = sin(radians);
|
|
47
|
+
let cosValue = cos(radians);
|
|
48
|
+
let rotated = vec2<f32>(
|
|
49
|
+
(localPosition.x * (input.scale.x * cosValue)) + (localPosition.y * (input.scale.y * sinValue)) + input.translation.x,
|
|
50
|
+
(localPosition.x * (input.scale.x * -sinValue)) + (localPosition.y * (input.scale.y * cosValue)) + input.translation.y
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
var output: VertexOutput;
|
|
54
|
+
|
|
55
|
+
output.position = uniforms.projection * uniforms.translation * vec4<f32>(rotated, 0.0, 1.0);
|
|
56
|
+
output.texcoord = input.uvMin + ((input.uvMax - input.uvMin) * input.unitPosition);
|
|
57
|
+
output.color = vec4(input.color.rgb * input.color.a, input.color.a);
|
|
58
|
+
|
|
59
|
+
return output;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@fragment
|
|
63
|
+
fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
64
|
+
let sample = textureSample(particleTexture, particleSampler, input.texcoord);
|
|
65
|
+
let premultipliedSample = select(sample, vec4(sample.rgb * sample.a, sample.a), uniforms.flags.x > 0.5);
|
|
66
|
+
|
|
67
|
+
return premultipliedSample * input.color;
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const staticVertexStrideBytes = 8;
|
|
71
|
+
const instanceWords = 10;
|
|
72
|
+
const instanceStrideBytes = 40;
|
|
73
|
+
const indicesPerParticle = 6;
|
|
74
|
+
const uniformByteLength = 176;
|
|
75
|
+
const initialParticleCapacity = 1;
|
|
76
|
+
const staticVertexData = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
|
|
77
|
+
const staticIndexData = new Uint16Array([0, 1, 2, 0, 2, 3]);
|
|
78
|
+
class WebGpuParticleRenderer extends AbstractWebGpuRenderer {
|
|
79
|
+
/**
|
|
80
|
+
* The particle system's transform is bound as a uniform and each particle is
|
|
81
|
+
* positioned system-locally, so this renderer never reads the shared transform
|
|
82
|
+
* storage; the plan player skips writing transform records for particle draws.
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
_consumesSharedTransform = false;
|
|
86
|
+
_drawCalls = [];
|
|
87
|
+
_drawCallCount = 0;
|
|
88
|
+
_uniformData = new Float32Array(uniformByteLength / Float32Array.BYTES_PER_ELEMENT);
|
|
89
|
+
_device = null;
|
|
90
|
+
_shaderModule = null;
|
|
91
|
+
_uniformBindGroupLayout = null;
|
|
92
|
+
_textureBindGroupLayout = null;
|
|
93
|
+
_pipelineLayout = null;
|
|
94
|
+
_uniformBuffer = null;
|
|
95
|
+
_uniformBindGroup = null;
|
|
96
|
+
_staticVertexBuffer = null;
|
|
97
|
+
_instanceBuffer = null;
|
|
98
|
+
_indexBuffer = null;
|
|
99
|
+
_instanceBufferByteLength = 0;
|
|
100
|
+
_instanceData = new ArrayBuffer(instanceStrideBytes * initialParticleCapacity);
|
|
101
|
+
_float32View = new Float32Array(this._instanceData);
|
|
102
|
+
_uint32View = new Uint32Array(this._instanceData);
|
|
103
|
+
_pipelines = new Map();
|
|
104
|
+
render(system) {
|
|
105
|
+
const backend = this._backend;
|
|
106
|
+
const texture = system.texture;
|
|
107
|
+
if (backend === null || !(texture instanceof Texture) || texture.source === null || texture.width === 0 || texture.height === 0 || system.liveCount === 0) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
backend.setBlendMode(system.blendMode);
|
|
111
|
+
const drawCallIndex = this._drawCallCount++;
|
|
112
|
+
const drawCall = this._drawCalls[drawCallIndex];
|
|
113
|
+
if (drawCall) {
|
|
114
|
+
drawCall.system = system;
|
|
115
|
+
drawCall.texture = texture;
|
|
116
|
+
drawCall.blendMode = system.blendMode;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this._drawCalls.push({
|
|
120
|
+
system,
|
|
121
|
+
texture,
|
|
122
|
+
blendMode: system.blendMode,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
flush() {
|
|
127
|
+
const backend = this._backend;
|
|
128
|
+
const device = this._device;
|
|
129
|
+
const uniformBuffer = this._uniformBuffer;
|
|
130
|
+
const uniformBindGroup = this._uniformBindGroup;
|
|
131
|
+
const staticVertexBuffer = this._staticVertexBuffer;
|
|
132
|
+
const indexBuffer = this._indexBuffer;
|
|
133
|
+
if (!backend || !device || !uniformBuffer || !uniformBindGroup || !staticVertexBuffer || !this._instanceBuffer || !indexBuffer) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (this._drawCallCount === 0 && !backend.clearRequested) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const scissor = backend.getScissorRect();
|
|
140
|
+
const maskClipsAll = scissor !== null && (scissor.width <= 0 || scissor.height <= 0);
|
|
141
|
+
// If no drawcalls will actually render (none queued, or the scissor
|
|
142
|
+
// clips everything), but a clear is pending, open a single empty
|
|
143
|
+
// pass so createColorAttachment consumes the clear state.
|
|
144
|
+
if (this._drawCallCount === 0 || maskClipsAll) {
|
|
145
|
+
if (backend.clearRequested) {
|
|
146
|
+
backend._passCoordinator.acquirePass();
|
|
147
|
+
backend._passCoordinator.endPass();
|
|
148
|
+
}
|
|
149
|
+
this._drawCallCount = 0;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// One command encoder / pass per drawcall. Each particle system's
|
|
153
|
+
// queue.writeBuffer calls target offset 0 of the instance and uniform
|
|
154
|
+
// buffers — a single pass with multiple systems would see all
|
|
155
|
+
// writeBuffers serialize before submit, leaving only the last
|
|
156
|
+
// system's data in those buffers and making every earlier draw read
|
|
157
|
+
// the wrong data. Also: _ensureCapacity may destroy and recreate the
|
|
158
|
+
// instance buffer on growth; keeping one drawcall per pass means
|
|
159
|
+
// that destroy happens strictly between submits, so no pass holds a
|
|
160
|
+
// reference to a buffer that has since been destroyed.
|
|
161
|
+
for (let drawCallIndex = 0; drawCallIndex < this._drawCallCount; drawCallIndex++) {
|
|
162
|
+
const drawCall = this._drawCalls[drawCallIndex];
|
|
163
|
+
const system = drawCall.system;
|
|
164
|
+
const particleCount = system.liveCount;
|
|
165
|
+
if (particleCount === 0) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const pipeline = this._getPipeline(drawCall.blendMode, backend.renderTargetFormat, backend._passCoordinator.stencilActive);
|
|
169
|
+
const textureBinding = backend.getTextureBinding(drawCall.texture);
|
|
170
|
+
const textureBindGroup = device.createBindGroup({
|
|
171
|
+
layout: this._textureBindGroupLayout,
|
|
172
|
+
entries: [
|
|
173
|
+
{
|
|
174
|
+
binding: 0,
|
|
175
|
+
resource: textureBinding.view,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
binding: 1,
|
|
179
|
+
resource: textureBinding.sampler,
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
});
|
|
183
|
+
this._writeUniformData(backend, system, drawCall.texture);
|
|
184
|
+
// GPU mode: the system's compute pipeline already wrote the
|
|
185
|
+
// interleaved instance data into its own buffer. Bind it
|
|
186
|
+
// directly — no CPU pack, no writeBuffer for instance data.
|
|
187
|
+
// CPU mode: pack from CPU SoA into our owned instance buffer.
|
|
188
|
+
let drawInstanceCount = particleCount;
|
|
189
|
+
const instanceBuffer = (() => {
|
|
190
|
+
if (system.gpuMode && system.gpuState !== null) {
|
|
191
|
+
return system.gpuState.instanceBuffer;
|
|
192
|
+
}
|
|
193
|
+
this._ensureCapacity(particleCount);
|
|
194
|
+
drawInstanceCount = this._writeInstanceData(system);
|
|
195
|
+
device.queue.writeBuffer(this._instanceBuffer, 0, this._instanceData, 0, drawInstanceCount * instanceStrideBytes);
|
|
196
|
+
return this._instanceBuffer;
|
|
197
|
+
})();
|
|
198
|
+
device.queue.writeBuffer(uniformBuffer, 0, this._uniformData.buffer, this._uniformData.byteOffset, this._uniformData.byteLength);
|
|
199
|
+
// One coordinator-owned pass per drawcall: each system's writeBuffers
|
|
200
|
+
// target offset 0, so the pass must be submitted before the next system
|
|
201
|
+
// overwrites those buffers. acquirePass/endPass preserve that 1:1 ratio.
|
|
202
|
+
const pass = backend._passCoordinator.acquirePass().pass;
|
|
203
|
+
pass.setBindGroup(0, uniformBindGroup);
|
|
204
|
+
pass.setPipeline(pipeline);
|
|
205
|
+
pass.setBindGroup(1, textureBindGroup);
|
|
206
|
+
pass.setVertexBuffer(0, staticVertexBuffer);
|
|
207
|
+
pass.setVertexBuffer(1, instanceBuffer);
|
|
208
|
+
pass.setIndexBuffer(indexBuffer, 'uint16');
|
|
209
|
+
pass.drawIndexed(indicesPerParticle, drawInstanceCount, 0, 0, 0);
|
|
210
|
+
backend.stats.batches++;
|
|
211
|
+
backend.stats.drawCalls++;
|
|
212
|
+
backend._passCoordinator.endPass();
|
|
213
|
+
}
|
|
214
|
+
this._drawCallCount = 0;
|
|
215
|
+
}
|
|
216
|
+
destroy() {
|
|
217
|
+
this.disconnect();
|
|
218
|
+
}
|
|
219
|
+
onConnect(backend) {
|
|
220
|
+
this._backend = backend;
|
|
221
|
+
this._device = this._backend.device;
|
|
222
|
+
this._shaderModule = this._device.createShaderModule({ code: particleShaderSource });
|
|
223
|
+
this._uniformBindGroupLayout = this._device.createBindGroupLayout({
|
|
224
|
+
entries: [
|
|
225
|
+
{
|
|
226
|
+
binding: 0,
|
|
227
|
+
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
228
|
+
buffer: {
|
|
229
|
+
type: 'uniform',
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
});
|
|
234
|
+
this._textureBindGroupLayout = this._device.createBindGroupLayout({
|
|
235
|
+
entries: [
|
|
236
|
+
{
|
|
237
|
+
binding: 0,
|
|
238
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
239
|
+
texture: {
|
|
240
|
+
sampleType: 'float',
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
binding: 1,
|
|
245
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
246
|
+
sampler: {
|
|
247
|
+
type: 'filtering',
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
});
|
|
252
|
+
this._pipelineLayout = this._device.createPipelineLayout({
|
|
253
|
+
bindGroupLayouts: [this._uniformBindGroupLayout, this._textureBindGroupLayout],
|
|
254
|
+
});
|
|
255
|
+
this._uniformBuffer = this._device.createBuffer({
|
|
256
|
+
size: uniformByteLength,
|
|
257
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
258
|
+
});
|
|
259
|
+
this._uniformBindGroup = this._device.createBindGroup({
|
|
260
|
+
layout: this._uniformBindGroupLayout,
|
|
261
|
+
entries: [
|
|
262
|
+
{
|
|
263
|
+
binding: 0,
|
|
264
|
+
resource: {
|
|
265
|
+
buffer: this._uniformBuffer,
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
});
|
|
270
|
+
this._staticVertexBuffer = this._device.createBuffer({
|
|
271
|
+
size: staticVertexData.byteLength,
|
|
272
|
+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
273
|
+
});
|
|
274
|
+
this._device.queue.writeBuffer(this._staticVertexBuffer, 0, staticVertexData.buffer, staticVertexData.byteOffset, staticVertexData.byteLength);
|
|
275
|
+
this._indexBuffer = this._device.createBuffer({
|
|
276
|
+
size: staticIndexData.byteLength,
|
|
277
|
+
usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
|
|
278
|
+
});
|
|
279
|
+
this._device.queue.writeBuffer(this._indexBuffer, 0, staticIndexData.buffer, staticIndexData.byteOffset, staticIndexData.byteLength);
|
|
280
|
+
this._ensureCapacity(initialParticleCapacity);
|
|
281
|
+
}
|
|
282
|
+
onDisconnect() {
|
|
283
|
+
this.flush();
|
|
284
|
+
this._staticVertexBuffer?.destroy();
|
|
285
|
+
this._instanceBuffer?.destroy();
|
|
286
|
+
this._indexBuffer?.destroy();
|
|
287
|
+
this._uniformBuffer?.destroy();
|
|
288
|
+
this._pipelines.clear();
|
|
289
|
+
this._indexBuffer = null;
|
|
290
|
+
this._staticVertexBuffer = null;
|
|
291
|
+
this._instanceBuffer = null;
|
|
292
|
+
this._uniformBindGroup = null;
|
|
293
|
+
this._uniformBuffer = null;
|
|
294
|
+
this._pipelineLayout = null;
|
|
295
|
+
this._textureBindGroupLayout = null;
|
|
296
|
+
this._uniformBindGroupLayout = null;
|
|
297
|
+
this._shaderModule = null;
|
|
298
|
+
this._device = null;
|
|
299
|
+
this._backend = null;
|
|
300
|
+
this._instanceBufferByteLength = 0;
|
|
301
|
+
this._instanceData = new ArrayBuffer(instanceStrideBytes * initialParticleCapacity);
|
|
302
|
+
this._float32View = new Float32Array(this._instanceData);
|
|
303
|
+
this._uint32View = new Uint32Array(this._instanceData);
|
|
304
|
+
this._drawCallCount = 0;
|
|
305
|
+
}
|
|
306
|
+
_ensureCapacity(particleCount) {
|
|
307
|
+
const requiredInstanceBytes = particleCount * instanceStrideBytes;
|
|
308
|
+
if (requiredInstanceBytes > this._instanceData.byteLength) {
|
|
309
|
+
let byteLength = this._instanceData.byteLength;
|
|
310
|
+
while (byteLength < requiredInstanceBytes) {
|
|
311
|
+
byteLength *= 2;
|
|
312
|
+
}
|
|
313
|
+
this._instanceData = new ArrayBuffer(byteLength);
|
|
314
|
+
this._float32View = new Float32Array(this._instanceData);
|
|
315
|
+
this._uint32View = new Uint32Array(this._instanceData);
|
|
316
|
+
}
|
|
317
|
+
if (requiredInstanceBytes > this._instanceBufferByteLength) {
|
|
318
|
+
let byteLength = this._instanceBufferByteLength || instanceStrideBytes;
|
|
319
|
+
while (byteLength < requiredInstanceBytes) {
|
|
320
|
+
byteLength *= 2;
|
|
321
|
+
}
|
|
322
|
+
this._instanceBuffer?.destroy();
|
|
323
|
+
this._instanceBuffer = this._device.createBuffer({
|
|
324
|
+
size: byteLength,
|
|
325
|
+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
326
|
+
});
|
|
327
|
+
this._instanceBufferByteLength = byteLength;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
_writeUniformData(backend, system, texture) {
|
|
331
|
+
const projection = backend.view.getTransform().toArray(false);
|
|
332
|
+
const transform = system.getGlobalTransform().toArray(false);
|
|
333
|
+
const shouldPremultiplySample = backend.shouldPremultiplyTextureSample(texture);
|
|
334
|
+
const vertices = system.vertices;
|
|
335
|
+
const texCoords = system.texCoords;
|
|
336
|
+
const quadMinX = vertices[0];
|
|
337
|
+
const quadMinY = vertices[1];
|
|
338
|
+
const quadSizeX = vertices[2] - vertices[0];
|
|
339
|
+
const quadSizeY = vertices[3] - vertices[1];
|
|
340
|
+
const uvMinX = (texCoords[0] & 0xffff) / 0xffff;
|
|
341
|
+
const uvMinY = ((texCoords[0] >>> 16) & 0xffff) / 0xffff;
|
|
342
|
+
const uvMaxX = (texCoords[2] & 0xffff) / 0xffff;
|
|
343
|
+
const uvMaxY = ((texCoords[2] >>> 16) & 0xffff) / 0xffff;
|
|
344
|
+
this._uniformData.set([
|
|
345
|
+
projection[0],
|
|
346
|
+
projection[1],
|
|
347
|
+
0,
|
|
348
|
+
0,
|
|
349
|
+
projection[3],
|
|
350
|
+
projection[4],
|
|
351
|
+
0,
|
|
352
|
+
0,
|
|
353
|
+
0,
|
|
354
|
+
0,
|
|
355
|
+
1,
|
|
356
|
+
0,
|
|
357
|
+
projection[6],
|
|
358
|
+
projection[7],
|
|
359
|
+
0,
|
|
360
|
+
projection[8],
|
|
361
|
+
transform[0],
|
|
362
|
+
transform[1],
|
|
363
|
+
0,
|
|
364
|
+
0,
|
|
365
|
+
transform[3],
|
|
366
|
+
transform[4],
|
|
367
|
+
0,
|
|
368
|
+
0,
|
|
369
|
+
0,
|
|
370
|
+
0,
|
|
371
|
+
1,
|
|
372
|
+
0,
|
|
373
|
+
transform[6],
|
|
374
|
+
transform[7],
|
|
375
|
+
0,
|
|
376
|
+
transform[8],
|
|
377
|
+
shouldPremultiplySample ? 1 : 0,
|
|
378
|
+
0,
|
|
379
|
+
0,
|
|
380
|
+
0,
|
|
381
|
+
quadMinX,
|
|
382
|
+
quadMinY,
|
|
383
|
+
quadSizeX,
|
|
384
|
+
quadSizeY,
|
|
385
|
+
uvMinX,
|
|
386
|
+
uvMinY,
|
|
387
|
+
uvMaxX,
|
|
388
|
+
uvMaxY,
|
|
389
|
+
]);
|
|
390
|
+
}
|
|
391
|
+
_writeInstanceData(system) {
|
|
392
|
+
const { posX, posY, scaleX, scaleY, rotations, color, textureIndex, alive, liveCount } = system;
|
|
393
|
+
const f32 = this._float32View;
|
|
394
|
+
const u32 = this._uint32View;
|
|
395
|
+
const { uvMins, uvMaxs } = this._computeFrameUvs(system);
|
|
396
|
+
const frameCount = uvMins.length / 2;
|
|
397
|
+
let writeIndex = 0;
|
|
398
|
+
for (let particleIndex = 0; particleIndex < liveCount; particleIndex++) {
|
|
399
|
+
// Skip dead slots — present in GPU-mode systems where the live
|
|
400
|
+
// range can carry holes filled in on next spawn.
|
|
401
|
+
if (alive[particleIndex] === 0) {
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
const targetIndex = writeIndex * instanceWords;
|
|
405
|
+
const frame = textureIndex[particleIndex] < frameCount ? textureIndex[particleIndex] : 0;
|
|
406
|
+
const uvBase = frame * 2;
|
|
407
|
+
f32[targetIndex + 0] = posX[particleIndex];
|
|
408
|
+
f32[targetIndex + 1] = posY[particleIndex];
|
|
409
|
+
f32[targetIndex + 2] = scaleX[particleIndex];
|
|
410
|
+
f32[targetIndex + 3] = scaleY[particleIndex];
|
|
411
|
+
f32[targetIndex + 4] = rotations[particleIndex];
|
|
412
|
+
u32[targetIndex + 5] = color[particleIndex];
|
|
413
|
+
f32[targetIndex + 6] = uvMins[uvBase + 0];
|
|
414
|
+
f32[targetIndex + 7] = uvMins[uvBase + 1];
|
|
415
|
+
f32[targetIndex + 8] = uvMaxs[uvBase + 0];
|
|
416
|
+
f32[targetIndex + 9] = uvMaxs[uvBase + 1];
|
|
417
|
+
writeIndex++;
|
|
418
|
+
}
|
|
419
|
+
return writeIndex;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Same atlas/UV-resolution as the WebGL2 path. Returns the per-frame
|
|
423
|
+
* (uvMin, uvMax) pairs derived from `system.frames` (or fallback to
|
|
424
|
+
* `system.textureFrame` when no atlas is declared), already flipY-
|
|
425
|
+
* adjusted for the current texture.
|
|
426
|
+
*/
|
|
427
|
+
_uvMinsScratch = new Float32Array(2);
|
|
428
|
+
_uvMaxsScratch = new Float32Array(2);
|
|
429
|
+
_computeFrameUvs(system) {
|
|
430
|
+
const frames = system.frames;
|
|
431
|
+
const tex = system.texture;
|
|
432
|
+
const texW = tex.width;
|
|
433
|
+
const texH = tex.height;
|
|
434
|
+
const flipY = tex.flipY;
|
|
435
|
+
const count = frames.length === 0 ? 1 : frames.length;
|
|
436
|
+
if (this._uvMinsScratch.length < count * 2) {
|
|
437
|
+
this._uvMinsScratch = new Float32Array(count * 2);
|
|
438
|
+
this._uvMaxsScratch = new Float32Array(count * 2);
|
|
439
|
+
}
|
|
440
|
+
const mins = this._uvMinsScratch;
|
|
441
|
+
const maxs = this._uvMaxsScratch;
|
|
442
|
+
if (frames.length === 0) {
|
|
443
|
+
const f = system.textureFrame;
|
|
444
|
+
const minU = f.left / texW;
|
|
445
|
+
const maxU = f.right / texW;
|
|
446
|
+
const topV = f.top / texH;
|
|
447
|
+
const bottomV = f.bottom / texH;
|
|
448
|
+
mins[0] = minU;
|
|
449
|
+
mins[1] = flipY ? bottomV : topV;
|
|
450
|
+
maxs[0] = maxU;
|
|
451
|
+
maxs[1] = flipY ? topV : bottomV;
|
|
452
|
+
return { uvMins: mins, uvMaxs: maxs };
|
|
453
|
+
}
|
|
454
|
+
for (let i = 0; i < frames.length; i++) {
|
|
455
|
+
const f = frames[i];
|
|
456
|
+
const o = i * 2;
|
|
457
|
+
const minU = f.left / texW;
|
|
458
|
+
const maxU = f.right / texW;
|
|
459
|
+
const topV = f.top / texH;
|
|
460
|
+
const bottomV = f.bottom / texH;
|
|
461
|
+
mins[o + 0] = minU;
|
|
462
|
+
mins[o + 1] = flipY ? bottomV : topV;
|
|
463
|
+
maxs[o + 0] = maxU;
|
|
464
|
+
maxs[o + 1] = flipY ? topV : bottomV;
|
|
465
|
+
}
|
|
466
|
+
return { uvMins: mins, uvMaxs: maxs };
|
|
467
|
+
}
|
|
468
|
+
_getPipeline(blendMode, format, stencil) {
|
|
469
|
+
const pipelineKey = `${blendMode}:${format}:${stencil ? 's' : 'n'}`;
|
|
470
|
+
const existingPipeline = this._pipelines.get(pipelineKey);
|
|
471
|
+
if (existingPipeline) {
|
|
472
|
+
return existingPipeline;
|
|
473
|
+
}
|
|
474
|
+
const descriptor = {
|
|
475
|
+
layout: this._pipelineLayout,
|
|
476
|
+
vertex: {
|
|
477
|
+
module: this._shaderModule,
|
|
478
|
+
entryPoint: 'vertexMain',
|
|
479
|
+
buffers: [
|
|
480
|
+
{
|
|
481
|
+
arrayStride: staticVertexStrideBytes,
|
|
482
|
+
attributes: [
|
|
483
|
+
{
|
|
484
|
+
shaderLocation: 0,
|
|
485
|
+
offset: 0,
|
|
486
|
+
format: 'float32x2',
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
arrayStride: instanceStrideBytes,
|
|
492
|
+
stepMode: 'instance',
|
|
493
|
+
attributes: [
|
|
494
|
+
{
|
|
495
|
+
shaderLocation: 1,
|
|
496
|
+
offset: 0,
|
|
497
|
+
format: 'float32x2',
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
shaderLocation: 2,
|
|
501
|
+
offset: 8,
|
|
502
|
+
format: 'float32x2',
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
shaderLocation: 3,
|
|
506
|
+
offset: 16,
|
|
507
|
+
format: 'float32',
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
shaderLocation: 4,
|
|
511
|
+
offset: 20,
|
|
512
|
+
format: 'unorm8x4',
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
shaderLocation: 5,
|
|
516
|
+
offset: 24,
|
|
517
|
+
format: 'float32x2',
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
shaderLocation: 6,
|
|
521
|
+
offset: 32,
|
|
522
|
+
format: 'float32x2',
|
|
523
|
+
},
|
|
524
|
+
],
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
fragment: {
|
|
529
|
+
module: this._shaderModule,
|
|
530
|
+
entryPoint: 'fragmentMain',
|
|
531
|
+
targets: [
|
|
532
|
+
{
|
|
533
|
+
format,
|
|
534
|
+
blend: getWebGpuBlendState(blendMode),
|
|
535
|
+
writeMask: GPUColorWrite.ALL,
|
|
536
|
+
},
|
|
537
|
+
],
|
|
538
|
+
},
|
|
539
|
+
primitive: {
|
|
540
|
+
topology: 'triangle-list',
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
if (stencil) {
|
|
544
|
+
descriptor.depthStencil = stencilContentDepthStencilState();
|
|
545
|
+
}
|
|
546
|
+
const pipeline = this._device.createRenderPipeline(descriptor);
|
|
547
|
+
this._pipelines.set(pipelineKey, pipeline);
|
|
548
|
+
return pipeline;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export { WebGpuParticleRenderer };
|
|
553
|
+
//# sourceMappingURL=WebGpuParticleRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebGpuParticleRenderer.js","sources":["../../../../src/renderers/WebGpuParticleRenderer.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var fragmentSource = "#version 300 es\nprecision lowp float;\n\nuniform sampler2D u_texture;\n\nin vec2 v_texcoord;\nin vec4 v_color;\n\nlayout(location = 0) out vec4 fragColor;\n\nvoid main(void) {\n fragColor = texture(u_texture, v_texcoord) * v_color;\n}\n";
|
|
2
|
+
|
|
3
|
+
export { fragmentSource as default };
|
|
4
|
+
//# sourceMappingURL=particle.frag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"particle.frag.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var vertexSource = "#version 300 es\nprecision lowp float;\nprecision lowp int;\n\n// Per-instance attributes (one entry per particle, 40 bytes total).\nlayout(location = 0) in vec2 a_translation; // particle position in system-local space\nlayout(location = 1) in vec2 a_scale; // particle scale\nlayout(location = 2) in float a_rotation; // particle rotation in degrees\nlayout(location = 3) in vec4 a_color; // RGBA tint\nlayout(location = 4) in vec2 a_uvMin; // top-left UV (u, v) — pre-resolved per instance\nlayout(location = 5) in vec2 a_uvMax; // bottom-right UV (u, v) — pre-resolved per instance\n\nuniform mat3 u_projection;\nuniform mat3 u_systemTransform;\nuniform vec4 u_localBounds; // left, top, right, bottom (system.vertices)\n\nout vec2 v_texcoord;\nout vec4 v_color;\n\nvoid main(void) {\n // Static index buffer is [0,1,2,0,2,3] (triangle-list), so gl_VertexID 0..3\n // maps to TL, TR, BR, BL via the same bit math the sprite renderer uses.\n int vid = gl_VertexID;\n int cornerX = ((vid + 1) >> 1) & 1;\n int cornerY = vid >> 1;\n\n float localX = (cornerX == 0) ? u_localBounds.x : u_localBounds.z;\n float localY = (cornerY == 0) ? u_localBounds.y : u_localBounds.w;\n\n // Per-particle scale + rotation.\n vec2 rotation = vec2(sin(radians(a_rotation)), cos(radians(a_rotation)));\n vec2 transformed = vec2(\n (localX * (a_scale.x * rotation.y)) + (localY * (a_scale.y * rotation.x)),\n (localX * (a_scale.x * -rotation.x)) + (localY * (a_scale.y * rotation.y))\n );\n\n vec3 worldPos = vec3(transformed + a_translation, 1.0);\n\n gl_Position = vec4((u_projection * u_systemTransform * worldPos).xy, 0.0, 1.0);\n\n float u = (cornerX == 0) ? a_uvMin.x : a_uvMax.x;\n float v = (cornerY == 0) ? a_uvMin.y : a_uvMax.y;\n v_texcoord = vec2(u, v);\n\n v_color = vec4(a_color.rgb * a_color.a, a_color.a);\n}\n";
|
|
2
|
+
|
|
3
|
+
export { vertexSource as default };
|
|
4
|
+
//# sourceMappingURL=particle.vert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"particle.vert.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|