@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.
- package/package.json +1 -1
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +733 -726
- package/src/engine/network/NetworkSession.d.ts +24 -4
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +28 -4
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +47 -6
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +184 -56
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +97 -11
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +304 -22
- package/src/engine/network/replication/Replicator.d.ts +14 -1
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +44 -3
- package/src/engine/network/sim/ActionLog.d.ts +21 -3
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +24 -3
- package/src/engine/network/sim/SimAction.d.ts +15 -0
- package/src/engine/network/sim/SimAction.d.ts.map +1 -1
- package/src/engine/network/sim/SimAction.js +15 -0
- package/src/engine/network/sim/SimActionExecutor.d.ts +51 -1
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +73 -5
- package/src/engine/network/transport/Channel.d.ts +1 -1
- package/src/engine/network/transport/Channel.js +1 -1
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +4 -1
- package/src/engine/ui/GUIEngine.d.ts.map +1 -1
- package/src/engine/ui/GUIEngine.js +6 -0
- package/src/shade/playground/particle_system/README.md +98 -0
- package/src/shade/playground/particle_system/index.html +124 -0
- package/src/shade/playground/particle_system/main.d.ts +2 -0
- package/src/shade/playground/particle_system/main.d.ts.map +1 -0
- package/src/shade/playground/particle_system/main.js +180 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts +52 -0
- package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -0
- package/src/shade/playground/particle_system/particle_scene.js +552 -0
- package/src/shade/playground/skinned_mesh_soup/README.md +122 -0
- package/src/shade/playground/skinned_mesh_soup/index.html +199 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts +7 -0
- package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/main.js +564 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts +23 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -0
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +409 -0
- package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +1 -1
- package/src/shade/renderer/particles/cull/chunk_particle_cull.js +3 -1
- package/src/shade/renderer/particles/data/chunk_particle_emitter.js +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts +1 -1
- package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts +89 -0
- package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -0
- package/src/shade/renderer/particles/isa/InstructionStream.js +162 -0
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts +1 -48
- package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts.map +1 -1
- package/src/shade/renderer/particles/isa/ParticleAssembler.js +25 -114
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +4 -2
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +4 -4
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +7 -5
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_emit.js +3 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +5 -2
- package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_render.js +9 -2
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +3 -1
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts +0 -2
- package/src/shade/renderer/particles/prototypeParticleSystem.d.ts.map +0 -1
- 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":"
|
|
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 {
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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(
|
|
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
|
-
*
|
|
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
|
|
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,
|
|
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
|
-
*
|
|
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
|
|
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(
|
|
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,
|
|
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(
|
|
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;
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
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":"
|
|
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(
|
|
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({
|
|
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;
|
|
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
|
-
|
|
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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prototypeParticleSystem.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/prototypeParticleSystem.js"],"names":[],"mappings":""}
|