@woosh/meep-engine 3.14.3 → 3.14.4

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.
Files changed (75) hide show
  1. package/package.json +1 -1
  2. package/src/engine/Engine.d.ts.map +1 -1
  3. package/src/engine/Engine.js +733 -726
  4. package/src/engine/network/NetworkSession.d.ts +24 -4
  5. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  6. package/src/engine/network/NetworkSession.js +28 -4
  7. package/src/engine/network/orchestrator/NetworkPeer.d.ts +47 -6
  8. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  9. package/src/engine/network/orchestrator/NetworkPeer.js +184 -56
  10. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +97 -11
  11. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  12. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +304 -22
  13. package/src/engine/network/replication/Replicator.d.ts +14 -1
  14. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  15. package/src/engine/network/replication/Replicator.js +44 -3
  16. package/src/engine/network/sim/ActionLog.d.ts +21 -3
  17. package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
  18. package/src/engine/network/sim/ActionLog.js +24 -3
  19. package/src/engine/network/sim/SimAction.d.ts +15 -0
  20. package/src/engine/network/sim/SimAction.d.ts.map +1 -1
  21. package/src/engine/network/sim/SimAction.js +15 -0
  22. package/src/engine/network/sim/SimActionExecutor.d.ts +51 -1
  23. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  24. package/src/engine/network/sim/SimActionExecutor.js +73 -5
  25. package/src/engine/network/transport/Channel.d.ts +1 -1
  26. package/src/engine/network/transport/Channel.js +1 -1
  27. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  28. package/src/engine/simulation/Ticker.js +4 -1
  29. package/src/engine/ui/GUIEngine.d.ts.map +1 -1
  30. package/src/engine/ui/GUIEngine.js +6 -0
  31. package/src/shade/playground/particle_system/README.md +98 -0
  32. package/src/shade/playground/particle_system/index.html +124 -0
  33. package/src/shade/playground/particle_system/main.d.ts +2 -0
  34. package/src/shade/playground/particle_system/main.d.ts.map +1 -0
  35. package/src/shade/playground/particle_system/main.js +180 -0
  36. package/src/shade/playground/particle_system/particle_scene.d.ts +52 -0
  37. package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -0
  38. package/src/shade/playground/particle_system/particle_scene.js +552 -0
  39. package/src/shade/playground/skinned_mesh_soup/README.md +122 -0
  40. package/src/shade/playground/skinned_mesh_soup/index.html +199 -0
  41. package/src/shade/playground/skinned_mesh_soup/main.d.ts +7 -0
  42. package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -0
  43. package/src/shade/playground/skinned_mesh_soup/main.js +564 -0
  44. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts +23 -0
  45. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -0
  46. package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +409 -0
  47. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +1 -1
  48. package/src/shade/renderer/particles/cull/chunk_particle_cull.js +3 -1
  49. package/src/shade/renderer/particles/data/chunk_particle_emitter.js +1 -1
  50. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts +1 -1
  51. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  52. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +89 -0
  53. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -0
  54. package/src/shade/renderer/particles/isa/InstructionStream.js +162 -0
  55. package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts +1 -48
  56. package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts.map +1 -1
  57. package/src/shade/renderer/particles/isa/ParticleAssembler.js +25 -114
  58. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +1 -1
  59. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +4 -2
  60. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +4 -4
  61. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
  62. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +7 -5
  63. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
  64. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +3 -1
  65. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  66. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +3 -1
  67. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  68. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +5 -2
  69. package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
  70. package/src/shade/renderer/particles/shaders/shader_particle_render.js +9 -2
  71. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  72. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -1
  73. package/src/shade/renderer/particles/prototypeParticleSystem.d.ts +0 -2
  74. package/src/shade/renderer/particles/prototypeParticleSystem.d.ts.map +0 -1
  75. package/src/shade/renderer/particles/prototypeParticleSystem.js +0 -448
@@ -0,0 +1,162 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { PARTICLE_VM_INSTRUCTION_WORDS, PARTICLE_VM_REGISTER_COUNT } from "../ParticleConstants.js";
3
+ import { VM_ISA, VM_OP } from "./ParticleVMISA.js";
4
+
5
+ /**
6
+ * A single VM instruction stream (a SPAWN or UPDATE section). Instructions are appended in order;
7
+ * {@link toWords} flattens them to the packed `Uint32Array` the program consumes.
8
+ *
9
+ * Register usage is tracked as instructions are emitted so the assembler can report how many
10
+ * registers the program touches without a separate pass.
11
+ */
12
+ export class InstructionStream {
13
+ /** @type {number[][]} */
14
+ instructions = [];
15
+ /** @type {number} highest register index referenced, plus one */
16
+ register_count = 0;
17
+
18
+ #use_register(index) {
19
+ assert.isNonNegativeInteger(index, "register index");
20
+ assert.lessThan(index, PARTICLE_VM_REGISTER_COUNT, "register index exceeds the VM register file");
21
+ if (index + 1 > this.register_count) {
22
+ this.register_count = index + 1;
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Emit a raw instruction. Validates the opcode and tracks register usage. Prefer the typed
28
+ * helpers below where they exist — they document the non-obvious operand packing.
29
+ *
30
+ * @param {number} op
31
+ * @param {number} [dst]
32
+ * @param {number} [s0]
33
+ * @param {number} [s1]
34
+ * @param {number} [s2]
35
+ * @returns {InstructionStream} this, for chaining
36
+ */
37
+ emit(op, dst = 0, s0 = 0, s1 = 0, s2 = 0) {
38
+ const meta = VM_ISA.get(op);
39
+ assert.defined(meta, `unknown opcode ${op}`);
40
+
41
+ if (meta.dst) {
42
+ // For value-producing ops this is the destination; for STORE_ATTR/KILL it is a source
43
+ // register living in the dst slot. Either way it must be a valid register.
44
+ this.#use_register(dst);
45
+ }
46
+
47
+ const operands = meta.operands;
48
+ const slots = [s0, s1, s2];
49
+ for (let i = 0; i < 3; i++) {
50
+ if (operands[i] === "reg") {
51
+ this.#use_register(slots[i]);
52
+ }
53
+ }
54
+
55
+ this.instructions.push([op, dst >>> 0, s0 >>> 0, s1 >>> 0, s2 >>> 0]);
56
+ return this;
57
+ }
58
+
59
+ // --- typed helpers (packing that isn't obvious from `emit`) ---
60
+
61
+ /**
62
+ * @param {number} dst
63
+ * @param {number} src
64
+ * @returns {InstructionStream}
65
+ */
66
+ mov(dst, src) {
67
+ return this.emit(VM_OP.MOV, dst, src);
68
+ }
69
+
70
+ /**
71
+ * @param {number} dst
72
+ * @param {number} constant_index
73
+ * @returns {InstructionStream}
74
+ */
75
+ loadConst(dst, constant_index) {
76
+ return this.emit(VM_OP.LOAD_CONST, dst, constant_index);
77
+ }
78
+
79
+ /**
80
+ * @param {number} dst
81
+ * @param {number} word_offset
82
+ * @param {number} component_count
83
+ * @returns {InstructionStream}
84
+ */
85
+ loadAttr(dst, word_offset, component_count) {
86
+ return this.emit(VM_OP.LOAD_ATTR, dst, word_offset, component_count);
87
+ }
88
+
89
+ /**
90
+ * @param {number} src_register
91
+ * @param {number} word_offset
92
+ * @param {number} component_count
93
+ * @returns {InstructionStream}
94
+ */
95
+ storeAttr(src_register, word_offset, component_count) {
96
+ return this.emit(VM_OP.STORE_ATTR, src_register, word_offset, component_count);
97
+ }
98
+
99
+ /**
100
+ * @param {number} dst
101
+ * @param {number} builtin_id
102
+ * @returns {InstructionStream}
103
+ */
104
+ loadBuiltin(dst, builtin_id) {
105
+ return this.emit(VM_OP.LOAD_BUILTIN, dst, builtin_id);
106
+ }
107
+
108
+ /**
109
+ * @param {number} condition_register
110
+ * @returns {InstructionStream}
111
+ */
112
+ kill(condition_register) {
113
+ return this.emit(VM_OP.KILL, condition_register);
114
+ }
115
+
116
+ /**
117
+ * @param {number} dst
118
+ * @param {number} mode
119
+ * @returns {InstructionStream}
120
+ */
121
+ random(dst, mode) {
122
+ return this.emit(VM_OP.RANDOM, dst, mode);
123
+ }
124
+
125
+ /**
126
+ * @param {number} dst
127
+ * @param {number} curve_handle
128
+ * @param {number} t_register
129
+ * @returns {InstructionStream}
130
+ */
131
+ curve(dst, curve_handle, t_register) {
132
+ return this.emit(VM_OP.CURVE, dst, curve_handle, t_register);
133
+ }
134
+
135
+ /**
136
+ * @returns {InstructionStream}
137
+ */
138
+ halt() {
139
+ return this.emit(VM_OP.HALT);
140
+ }
141
+
142
+ /**
143
+ * @returns {number}
144
+ */
145
+ get instruction_count() {
146
+ return this.instructions.length;
147
+ }
148
+
149
+ /**
150
+ * @returns {Uint32Array}
151
+ */
152
+ toWords() {
153
+ const instructions = this.instructions;
154
+ const words = new Uint32Array(instructions.length * PARTICLE_VM_INSTRUCTION_WORDS);
155
+
156
+ for (let i = 0; i < instructions.length; i++) {
157
+ words.set(instructions[i], i * PARTICLE_VM_INSTRUCTION_WORDS);
158
+ }
159
+
160
+ return words;
161
+ }
162
+ }
@@ -1,51 +1,3 @@
1
- /**
2
- * A single VM instruction stream (a SPAWN or UPDATE section). Instructions are appended in order;
3
- * {@link toWords} flattens them to the packed `Uint32Array` the program consumes.
4
- *
5
- * Register usage is tracked as instructions are emitted so the assembler can report how many
6
- * registers the program touches without a separate pass.
7
- */
8
- export class InstructionStream {
9
- /** @type {number[][]} */
10
- instructions: number[][];
11
- /** @type {number} highest register index referenced, plus one */
12
- register_count: number;
13
- /**
14
- * Emit a raw instruction. Validates the opcode and tracks register usage. Prefer the typed
15
- * helpers below where they exist — they document the non-obvious operand packing.
16
- *
17
- * @param {number} op
18
- * @param {number} [dst]
19
- * @param {number} [s0]
20
- * @param {number} [s1]
21
- * @param {number} [s2]
22
- * @returns {InstructionStream} this, for chaining
23
- */
24
- emit(op: number, dst?: number, s0?: number, s1?: number, s2?: number): InstructionStream;
25
- /** @param {number} dst @param {number} src @returns {InstructionStream} */
26
- mov(dst: number, src: number): InstructionStream;
27
- /** @param {number} dst @param {number} constant_index @returns {InstructionStream} */
28
- loadConst(dst: number, constant_index: number): InstructionStream;
29
- /** @param {number} dst @param {number} word_offset @param {number} component_count @returns {InstructionStream} */
30
- loadAttr(dst: number, word_offset: number, component_count: number): InstructionStream;
31
- /** @param {number} src_register @param {number} word_offset @param {number} component_count @returns {InstructionStream} */
32
- storeAttr(src_register: number, word_offset: number, component_count: number): InstructionStream;
33
- /** @param {number} dst @param {number} builtin_id @returns {InstructionStream} */
34
- loadBuiltin(dst: number, builtin_id: number): InstructionStream;
35
- /** @param {number} condition_register @returns {InstructionStream} */
36
- kill(condition_register: number): InstructionStream;
37
- /** @param {number} dst @param {number} mode @returns {InstructionStream} */
38
- random(dst: number, mode: number): InstructionStream;
39
- /** @param {number} dst @param {number} curve_handle @param {number} t_register @returns {InstructionStream} */
40
- curve(dst: number, curve_handle: number, t_register: number): InstructionStream;
41
- /** @returns {InstructionStream} */
42
- halt(): InstructionStream;
43
- /** @returns {number} */
44
- get instruction_count(): number;
45
- /** @returns {Uint32Array} */
46
- toWords(): Uint32Array;
47
- #private;
48
- }
49
1
  /**
50
2
  * Convenience builder for a {@link ParticleProgram}: two instruction streams sharing one constant
51
3
  * pool. Used directly by tests and internally by the node-graph compiler.
@@ -72,5 +24,6 @@ export class ParticleAssembler {
72
24
  */
73
25
  build(): ParticleProgram;
74
26
  }
27
+ import { InstructionStream } from "./InstructionStream.js";
75
28
  import { ParticleProgram } from "./ParticleProgram.js";
76
29
  //# sourceMappingURL=ParticleAssembler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleAssembler.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/isa/ParticleAssembler.js"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH;IAEQ,yBAAyB;IACzB,cADW,MAAM,EAAE,EAAE,CACC;IACtB,iEAAiE;IACjE,gBADW,MAAM,CACM;IAW3B;;;;;;;;;;OAUG;IACH,SAPW,MAAM,QACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,GACJ,iBAAiB,CAsB7B;IAID,2EAA2E;IAC3E,SADY,MAAM,OAAc,MAAM,GAAgB,iBAAiB,CACf;IAExD,sFAAsF;IACtF,eADY,MAAM,kBAAc,MAAM,GAA2B,iBAAiB,CACS;IAE3F,mHAAmH;IACnH,cADY,MAAM,eAAc,MAAM,mBAAsB,MAAM,GAA4B,iBAAiB,CACM;IAErH,4HAA4H;IAC5H,wBADY,MAAM,eAAuB,MAAM,mBAAsB,MAAM,GAA4B,iBAAiB,CACiB;IAEzI,kFAAkF;IAClF,iBADY,MAAM,cAAc,MAAM,GAAuB,iBAAiB,CACS;IAEvF,sEAAsE;IACtE,yBADY,MAAM,GAA+B,iBAAiB,CACY;IAE9E,4EAA4E;IAC5E,YADY,MAAM,QAAc,MAAM,GAAiB,iBAAiB,CACR;IAEhE,+GAA+G;IAC/G,WADY,MAAM,gBAAc,MAAM,cAAuB,MAAM,GAAuB,iBAAiB,CACL;IAEtG,mCAAmC;IACnC,QADc,iBAAiB,CACS;IAExC,wBAAwB;IACxB,gCAEC;IAED,6BAA6B;IAC7B,WADc,WAAW,CAOxB;;CACJ;AAED;;;GAGG;AACH;IAEQ,gCAAgC;IAChC,OADW,iBAAiB,CACQ;IACpC,gCAAgC;IAChC,QADW,iBAAiB,CACS;IACrC,8DAA8D;IAC9D,WADW,MAAM,EAAE,CACA;IAGvB;;;;;;;;OAQG;IACH,YANW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAYlB;IAED;;OAEG;IACH,SAFa,eAAe,CAS3B;CACJ;gCArJ+B,sBAAsB"}
1
+ {"version":3,"file":"ParticleAssembler.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/isa/ParticleAssembler.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH;IACI,gCAAgC;IAChC,OADW,iBAAiB,CACI;IAEhC,gCAAgC;IAChC,QADW,iBAAiB,CACK;IAEjC,8DAA8D;IAC9D,WADW,MAAM,EAAE,CACJ;IAEf;;;;;;;;OAQG;IACH,YANW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAyBlB;IAED;;OAEG;IACH,SAFa,eAAe,CAS3B;CACJ;kCA9DiC,wBAAwB;gCAC1B,sBAAsB"}
@@ -1,121 +1,19 @@
1
- import { assert } from "../../../../core/assert.js";
2
- import { PARTICLE_VM_INSTRUCTION_WORDS, PARTICLE_VM_REGISTER_COUNT } from "../ParticleConstants.js";
1
+ import { InstructionStream } from "./InstructionStream.js";
3
2
  import { ParticleProgram } from "./ParticleProgram.js";
4
- import { VM_ISA, VM_OP } from "./ParticleVMISA.js";
5
-
6
- /**
7
- * A single VM instruction stream (a SPAWN or UPDATE section). Instructions are appended in order;
8
- * {@link toWords} flattens them to the packed `Uint32Array` the program consumes.
9
- *
10
- * Register usage is tracked as instructions are emitted so the assembler can report how many
11
- * registers the program touches without a separate pass.
12
- */
13
- export class InstructionStream {
14
- constructor() {
15
- /** @type {number[][]} */
16
- this.instructions = [];
17
- /** @type {number} highest register index referenced, plus one */
18
- this.register_count = 0;
19
- }
20
-
21
- #use_register(index) {
22
- assert.isNonNegativeInteger(index, "register index");
23
- assert.lessThan(index, PARTICLE_VM_REGISTER_COUNT, "register index exceeds the VM register file");
24
- if (index + 1 > this.register_count) {
25
- this.register_count = index + 1;
26
- }
27
- }
28
-
29
- /**
30
- * Emit a raw instruction. Validates the opcode and tracks register usage. Prefer the typed
31
- * helpers below where they exist — they document the non-obvious operand packing.
32
- *
33
- * @param {number} op
34
- * @param {number} [dst]
35
- * @param {number} [s0]
36
- * @param {number} [s1]
37
- * @param {number} [s2]
38
- * @returns {InstructionStream} this, for chaining
39
- */
40
- emit(op, dst = 0, s0 = 0, s1 = 0, s2 = 0) {
41
- const meta = VM_ISA.get(op);
42
- assert.defined(meta, `unknown opcode ${op}`);
43
-
44
- if (meta.dst) {
45
- // For value-producing ops this is the destination; for STORE_ATTR/KILL it is a source
46
- // register living in the dst slot. Either way it must be a valid register.
47
- this.#use_register(dst);
48
- }
49
-
50
- const operands = meta.operands;
51
- const slots = [s0, s1, s2];
52
- for (let i = 0; i < 3; i++) {
53
- if (operands[i] === "reg") {
54
- this.#use_register(slots[i]);
55
- }
56
- }
57
-
58
- this.instructions.push([op, dst >>> 0, s0 >>> 0, s1 >>> 0, s2 >>> 0]);
59
- return this;
60
- }
61
-
62
- // --- typed helpers (packing that isn't obvious from `emit`) ---
63
-
64
- /** @param {number} dst @param {number} src @returns {InstructionStream} */
65
- mov(dst, src) { return this.emit(VM_OP.MOV, dst, src); }
66
-
67
- /** @param {number} dst @param {number} constant_index @returns {InstructionStream} */
68
- loadConst(dst, constant_index) { return this.emit(VM_OP.LOAD_CONST, dst, constant_index); }
69
-
70
- /** @param {number} dst @param {number} word_offset @param {number} component_count @returns {InstructionStream} */
71
- loadAttr(dst, word_offset, component_count) { return this.emit(VM_OP.LOAD_ATTR, dst, word_offset, component_count); }
72
-
73
- /** @param {number} src_register @param {number} word_offset @param {number} component_count @returns {InstructionStream} */
74
- storeAttr(src_register, word_offset, component_count) { return this.emit(VM_OP.STORE_ATTR, src_register, word_offset, component_count); }
75
-
76
- /** @param {number} dst @param {number} builtin_id @returns {InstructionStream} */
77
- loadBuiltin(dst, builtin_id) { return this.emit(VM_OP.LOAD_BUILTIN, dst, builtin_id); }
78
-
79
- /** @param {number} condition_register @returns {InstructionStream} */
80
- kill(condition_register) { return this.emit(VM_OP.KILL, condition_register); }
81
-
82
- /** @param {number} dst @param {number} mode @returns {InstructionStream} */
83
- random(dst, mode) { return this.emit(VM_OP.RANDOM, dst, mode); }
84
-
85
- /** @param {number} dst @param {number} curve_handle @param {number} t_register @returns {InstructionStream} */
86
- curve(dst, curve_handle, t_register) { return this.emit(VM_OP.CURVE, dst, curve_handle, t_register); }
87
-
88
- /** @returns {InstructionStream} */
89
- halt() { return this.emit(VM_OP.HALT); }
90
-
91
- /** @returns {number} */
92
- get instruction_count() {
93
- return this.instructions.length;
94
- }
95
-
96
- /** @returns {Uint32Array} */
97
- toWords() {
98
- const words = new Uint32Array(this.instructions.length * PARTICLE_VM_INSTRUCTION_WORDS);
99
- for (let i = 0; i < this.instructions.length; i++) {
100
- words.set(this.instructions[i], i * PARTICLE_VM_INSTRUCTION_WORDS);
101
- }
102
- return words;
103
- }
104
- }
105
3
 
106
4
  /**
107
5
  * Convenience builder for a {@link ParticleProgram}: two instruction streams sharing one constant
108
6
  * pool. Used directly by tests and internally by the node-graph compiler.
109
7
  */
110
8
  export class ParticleAssembler {
111
- constructor() {
112
- /** @type {InstructionStream} */
113
- this.spawn = new InstructionStream();
114
- /** @type {InstructionStream} */
115
- this.update = new InstructionStream();
116
- /** @type {number[]} flat constant pool, 4 floats per entry */
117
- this.constants = [];
118
- }
9
+ /** @type {InstructionStream} */
10
+ spawn = new InstructionStream();
11
+
12
+ /** @type {InstructionStream} */
13
+ update = new InstructionStream();
14
+
15
+ /** @type {number[]} flat constant pool, 4 floats per entry */
16
+ constants = [];
119
17
 
120
18
  /**
121
19
  * Intern a `vec4f` constant into the shared pool, deduplicating exact matches so identical
@@ -127,14 +25,27 @@ export class ParticleAssembler {
127
25
  * @returns {number} constant-pool index
128
26
  */
129
27
  constant(x, y = 0, z = 0, w = 0) {
130
- const count = this.constants.length / 4;
28
+ const data = this.constants;
29
+ const count = data.length / 4;
30
+
131
31
  for (let i = 0; i < count; i++) {
132
32
  const base = i * 4;
133
- if (this.constants[base] === x && this.constants[base + 1] === y && this.constants[base + 2] === z && this.constants[base + 3] === w) {
33
+
34
+ if (
35
+ data[base] === x
36
+ && data[base + 1] === y
37
+ && data[base + 2] === z
38
+ && data[base + 3] === w
39
+ ) {
40
+
134
41
  return i;
42
+
135
43
  }
44
+
136
45
  }
137
- this.constants.push(x, y, z, w);
46
+
47
+ data.push(x, y, z, w);
48
+
138
49
  return count;
139
50
  }
140
51
 
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_particle_curve_animation.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,6CAFU,SAAS,CAO0C;0BA1BnC,oCAAoC"}
1
+ {"version":3,"file":"chunk_particle_curve_animation.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,6CAFU,SAAS,CAS0C;0BA5BnC,oCAAoC"}
@@ -21,9 +21,11 @@ const CURVE_TABLE = ANIMATION_DATABASE_SPEC.get("animation_curves");
21
21
  *
22
22
  * @type {CodeChunk}
23
23
  */
24
- export const chunk_particle_curve_animation = CodeChunk.from(/* wgsl */ `
24
+ export const chunk_particle_curve_animation = CodeChunk.from(
25
+ /* language=wgsl */
26
+ `
25
27
  fn particle_vm_sample_curve(handle : u32, t : f32) -> f32 {
26
28
  let header = ${CURVE_TABLE.marshalling_method_read}(&particle_curve_database, handle);
27
29
  return animation_curve_evaluate(t, &particle_curve_database, header);
28
30
  }
29
- `, [CURVE_TABLE.chunk_read, chunk_animation_curve_evaluate]);
31
+ `, [CURVE_TABLE.chunk_read, chunk_animation_curve_evaluate]);
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Pluggable lighting hook for the billboard fragment shader. `particle_apply_lighting(color, world,
3
- * normal)` returns the lit colour; the default is a pass-through (unlit / emissive).
2
+ * Pluggable lighting hook for the billboard fragment shader. `particle_apply_lighting(color, world, normal)`
3
+ * returns the lit colour; the default is a pass-through (unlit / emissive).
4
4
  *
5
- * The production feature swaps this for a chunk that binds {@link
6
- * ../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js} and calls `shade_standard_material_direct` + IBL —
5
+ * The production feature swaps this for a chunk that binds
6
+ * {@link ../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js} and calls `shade_standard_material_direct` + IBL —
7
7
  * i.e. billboards reuse the exact same lighting path as opaque surfaces when an emitter opts in via
8
8
  * its `lighting` flag. Keeping it a hook means unlit emitters compile without pulling in the whole
9
9
  * clustered-lighting resource group.
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_particle_lighting.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_lighting.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,4CAFU,SAAS,CAMhB;0BAlBuB,oCAAoC"}
1
+ {"version":3,"file":"chunk_particle_lighting.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_lighting.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,4CAFU,SAAS,CAQhB;0BApBuB,oCAAoC"}
@@ -1,18 +1,20 @@
1
1
  import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
2
2
 
3
3
  /**
4
- * Pluggable lighting hook for the billboard fragment shader. `particle_apply_lighting(color, world,
5
- * normal)` returns the lit colour; the default is a pass-through (unlit / emissive).
4
+ * Pluggable lighting hook for the billboard fragment shader. `particle_apply_lighting(color, world, normal)`
5
+ * returns the lit colour; the default is a pass-through (unlit / emissive).
6
6
  *
7
- * The production feature swaps this for a chunk that binds {@link
8
- * ../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js} and calls `shade_standard_material_direct` + IBL —
7
+ * The production feature swaps this for a chunk that binds
8
+ * {@link ../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js} and calls `shade_standard_material_direct` + IBL —
9
9
  * i.e. billboards reuse the exact same lighting path as opaque surfaces when an emitter opts in via
10
10
  * its `lighting` flag. Keeping it a hook means unlit emitters compile without pulling in the whole
11
11
  * clustered-lighting resource group.
12
12
  *
13
13
  * @type {CodeChunk}
14
14
  */
15
- export const chunk_particle_lighting_unlit = CodeChunk.from(/* wgsl */ `
15
+ export const chunk_particle_lighting_unlit = CodeChunk.from(
16
+ /* language=wgsl */
17
+ `
16
18
  fn particle_apply_lighting(color : vec4<f32>, world_position : vec3<f32>, normal : vec3<f32>) -> vec4<f32> {
17
19
  return color;
18
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_particle_render_math.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_render_math.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,yCAFU,SAAS,CAyFhB;0BAzGuB,oCAAoC"}
1
+ {"version":3,"file":"chunk_particle_render_math.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_render_math.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,yCAFU,SAAS,CA2FhB;0BA3GuB,oCAAoC"}
@@ -16,7 +16,9 @@ import { EMITTER_BLEND, EMITTER_PROJECTION } from "../data/PARTICLE_EMITTER_LAYO
16
16
  *
17
17
  * @type {CodeChunk}
18
18
  */
19
- export const chunk_particle_render_math = CodeChunk.from(/* wgsl */ `
19
+ export const chunk_particle_render_math = CodeChunk.from(
20
+ /* language=wgsl */
21
+ `
20
22
  const PARTICLE_PROJ_BILLBOARD : u32 = ${EMITTER_PROJECTION.BILLBOARD}u;
21
23
  const PARTICLE_PROJ_STRETCHED : u32 = ${EMITTER_PROJECTION.STRETCHED}u;
22
24
  const PARTICLE_PROJ_HORIZONTAL : u32 = ${EMITTER_PROJECTION.HORIZONTAL}u;
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_emit.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit.js"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;GAYG;AAEH,2CAHU,aAAa,CAGwB;AA6F/C,iDAIG;8BAhI2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_emit.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit.js"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;GAYG;AAEH,2CAHU,aAAa,CAGwB;AA+F/C,iDAIG;8BAlI2B,+BAA+B"}
@@ -64,7 +64,9 @@ resources.createGroup()
64
64
  .addStorageBuffer("alive_out", WebGPUArray.u32, true)
65
65
  .addStorageBuffer("dead", WebGPUArray.u32, true)
66
66
  .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
67
- const body = CodeChunk.from(/* wgsl */ `
67
+ const body = CodeChunk.from(
68
+ /* language=wgsl */
69
+ `
68
70
  const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
69
71
  const PARTICLE_USER_WORD_START : u32 = ${PARTICLE_RECORD_USER_WORD_START}u;
70
72
  const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_finalize.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_finalize.js"],"names":[],"mappings":"AA4BA,2DAWG;AAaH,2DAwBG;;8BA1E2B,+BAA+B;iDAIZ,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_finalize.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_finalize.js"],"names":[],"mappings":"AA4BA,2DAYG;AAaH,2DA0BG;;8BA7E2B,+BAA+B;iDAIZ,+BAA+B"}
@@ -29,7 +29,8 @@ reset_resources.createGroup().addStorageBuffer("counters", WebGPUArray.from(atom
29
29
  export const shader_particle_reset_counters = ComputeShader.from({
30
30
  label: "Particle Reset Counters",
31
31
  resources: reset_resources,
32
- body: CodeChunk.from(/* wgsl */ `
32
+ body: CodeChunk.from(
33
+ /* language=wgsl */ `
33
34
  @compute @workgroup_size(1, 1, 1)
34
35
  fn main() {
35
36
  atomicStore(&counters[${PARTICLE_COUNTER.ALIVE}u], 0u);
@@ -53,7 +54,9 @@ indirect_resources.createGroup()
53
54
  export const shader_particle_build_indirect = ComputeShader.from({
54
55
  label: "Particle Build Indirect",
55
56
  resources: indirect_resources,
56
- body: CodeChunk.from(/* wgsl */ `
57
+ body: CodeChunk.from(
58
+ /* language=wgsl */
59
+ `
57
60
  @compute @workgroup_size(1, 1, 1)
58
61
  fn main() {
59
62
  let alive = atomicLoad(&counters[${PARTICLE_COUNTER.ALIVE}u]);
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_render.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_render.js"],"names":[],"mappings":"AA6JA;;;;;;;;;GASG;AACH;IAP4B,YAAY,GAA7B,MAAM;IACgB,YAAY,GAAlC,MAAM,GAAC,IAAI;IAEkB,aAAa;IAExC,wBAAwB,CAqBpC;;;;;;;;;;;;;;;;AAED,yFAAyF;AACzF,uEAAsD;yCA7Lb,iEAAiE;4CAO9D,sDAAsD"}
1
+ {"version":3,"file":"shader_particle_render.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_render.js"],"names":[],"mappings":"AA8JA;;;;;;;;;GASG;AACH;IAP4B,YAAY,GAA7B,MAAM;IACgB,YAAY,GAAlC,MAAM,GAAC,IAAI;IAEkB,aAAa;IAExC,wBAAwB,CA2BpC;;;;;;;;;;;;;;;;AAED,yFAAyF;AACzF,uEAAsD;yCApMb,iEAAiE;4CAO9D,sDAAsD"}
@@ -52,7 +52,8 @@ resources.createGroup()
52
52
  // Only textureLoad-ed (soft depth), so it can be unfilterable — matches an r32float scene depth.
53
53
  .addTexture("scene_depth", "unfilterable-float");
54
54
 
55
- const body = CodeChunk.from(/* wgsl */ `
55
+ const body = CodeChunk.from(
56
+ /* language=wgsl */ `
56
57
  const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
57
58
  const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
58
59
  const PARTICLE_ATTRIBUTE_ABSENT : u32 = ${EMITTER_ATTRIBUTE_ABSENT}u;
@@ -165,7 +166,12 @@ const descriptor = ShaderDescriptor.from({ label: "Particle Billboard", body, re
165
166
  * reverse-Z scenes (the engine convention), "less"/"less-equal" for a standard-Z scene
166
167
  * @returns {RenderPipelineDescriptor}
167
168
  */
168
- export function create_particle_billboard_pipeline({ color_format = "rgba16float", depth_format = "depth32float", depth_compare = "greater" } = {}) {
169
+ export function create_particle_billboard_pipeline({
170
+ color_format = "rgba16float",
171
+ depth_format = "depth32float",
172
+ depth_compare = "greater"
173
+ } = {}) {
174
+
169
175
  const code = descriptor.source;
170
176
 
171
177
  return RenderPipelineDescriptor.from({
@@ -184,6 +190,7 @@ export function create_particle_billboard_pipeline({ color_format = "rgba16float
184
190
  : DepthStencilState.from({ format: depth_format, depthWriteEnabled: false, depthCompare: depth_compare }),
185
191
  primitive: { topology: "triangle-list", cullMode: "none" },
186
192
  });
193
+
187
194
  }
188
195
 
189
196
  /** The billboard shader's resource set (for building bind groups + the draw command). */
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,+CAHU,aAAa,CAG4B;AAqEnD,qDAIG;8BA3G2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,+CAHU,aAAa,CAG4B;AAuEnD,qDAIG;8BA7G2B,+BAA+B"}
@@ -62,7 +62,9 @@ resources.createGroup()
62
62
  .addStorageBuffer("alive_out", WebGPUArray.u32, true)
63
63
  .addStorageBuffer("dead", WebGPUArray.u32, true)
64
64
  .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
65
- const body = CodeChunk.from(/* wgsl */ `
65
+
66
+
67
+ const body = CodeChunk.from(/* language=wgsl */ `
66
68
  const PARTICLE_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
67
69
  const PARTICLE_HEADER_EMITTER : u32 = ${PARTICLE_RECORD_HEADER_EMITTER}u;
68
70
  const PARTICLE_INSTRUCTION_WORDS : u32 = ${PARTICLE_VM_INSTRUCTION_WORDS}u;
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=prototypeParticleSystem.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prototypeParticleSystem.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/prototypeParticleSystem.js"],"names":[],"mappings":""}