@woosh/meep-engine 3.60.9 → 3.61.1
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/CHANGELOG.md +90 -0
- package/package.json +1 -1
- package/src/engine/ecs/EntityManager.d.ts +3 -3
- package/src/engine/ecs/EntityManager.js +3 -3
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
- package/src/engine/graphics/ecs/decal/v2/Decal.d.ts +46 -2
- package/src/engine/graphics/ecs/decal/v2/Decal.d.ts.map +1 -1
- package/src/engine/graphics/ecs/decal/v2/Decal.js +74 -5
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +13 -1
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts +9 -0
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts.map +1 -0
- package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.js +37 -0
- package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
- package/src/engine/graphics3/DecalSystem.js +462 -447
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts +14 -0
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts.map +1 -1
- package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +53 -13
- package/src/engine/graphics3/decal/chunk_decal_record.d.ts +6 -1
- package/src/engine/graphics3/decal/chunk_decal_record.d.ts.map +1 -1
- package/src/engine/graphics3/decal/chunk_decal_record.js +28 -9
- package/src/engine/graphics3/decal/decal_gpu_records.d.ts +2 -1
- package/src/engine/graphics3/decal/decal_gpu_records.d.ts.map +1 -1
- package/src/engine/graphics3/decal/decal_gpu_records.js +26 -5
- package/src/engine/graphics3/decal/decal_material_samplers.d.ts +6 -0
- package/src/engine/graphics3/decal/decal_material_samplers.d.ts.map +1 -1
- package/src/engine/graphics3/decal/decal_material_samplers.js +13 -0
- package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
- package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts +5 -0
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +69 -28
- package/src/engine/network/NetworkSession.d.ts +3 -0
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +68 -10
- package/src/engine/network/README.md +6 -3
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +51 -5
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +308 -34
- package/src/engine/network/replication/Replicator.d.ts +8 -2
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +13 -4
- package/src/engine/network/sim/ActionLog.d.ts +16 -2
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +33 -2
- package/src/engine/network/sim/RewindEngine.d.ts +9 -0
- package/src/engine/network/sim/RewindEngine.d.ts.map +1 -1
- package/src/engine/network/sim/RewindEngine.js +15 -1
- package/src/engine/network/state/FrameBufferRing.d.ts +12 -5
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
- package/src/engine/network/state/FrameBufferRing.js +32 -6
- package/src/engine/network/time/TimeDilation.d.ts +30 -14
- package/src/engine/network/time/TimeDilation.d.ts.map +1 -1
- package/src/engine/network/time/TimeDilation.js +47 -17
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +3 -2
- package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
- package/src/generation/foliage/skeleton/ShootWoodHash.js +25 -2
- package/src/shade/renderer/buffer/graph_read_buffer.d.ts +3 -1
- package/src/shade/renderer/buffer/graph_read_buffer.d.ts.map +1 -1
- package/src/shade/renderer/buffer/graph_read_buffer.js +9 -6
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts +5 -0
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
- package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +48 -43
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +117 -35
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +2 -2
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +10 -3
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts +15 -3
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +25 -4
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts +23 -5
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +294 -20
- package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.d.ts +21 -0
- package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.d.ts.map +1 -0
- package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.js +83 -0
- package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.d.ts +21 -0
- package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.d.ts.map +1 -0
- package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.js +64 -0
- package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/chunk_restir_resolve.js +91 -94
- package/src/shade/renderer/restir/reservoir/chunk_rtxdi_stream_sample.js +1 -1
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts +14 -0
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.js +36 -21
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts +22 -0
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.js +64 -0
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.js +13 -18
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.js +28 -30
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.js +15 -16
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts +0 -1
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.js +15 -18
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.d.ts +32 -0
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.js +73 -0
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +7 -3
- package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts +0 -2
- package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts.map +0 -1
- package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.js +0 -6
|
@@ -1,447 +1,462 @@
|
|
|
1
|
-
import { assert } from "../../core/assert.js";
|
|
2
|
-
import { FramePhase } from "../../shade/renderer/extension/FramePhase.js";
|
|
3
|
-
import { RenderExtension } from "../../shade/renderer/extension/RenderExtension.js";
|
|
4
|
-
import { GameAssetType } from "../asset/GameAssetType.js";
|
|
5
|
-
import { ImageRGBADataLoader } from "../asset/loaders/image/ImageRGBADataLoader.js";
|
|
6
|
-
import { System } from "../ecs/System.js";
|
|
7
|
-
import { Transform64 } from "../ecs/transform/Transform64.js";
|
|
8
|
-
import { Decal } from "../graphics/ecs/decal/v2/Decal.js";
|
|
9
|
-
import { ManagedAtlas } from "../graphics/texture/atlas/ManagedTextureAtlas.js";
|
|
10
|
-
import { SpriteAtlas } from "../graphics/texture/atlas/SpriteAtlas.js";
|
|
11
|
-
import { SpriteAtlasFill } from "../graphics/texture/atlas/SpriteAtlasFill.js";
|
|
12
|
-
import { sprite_atlas_max_lod } from "../graphics/texture/atlas/sprite_atlas_border.js";
|
|
13
|
-
import { sampler2d_ensure_uint8_RGBA } from "../graphics/texture/sampler/sampler2d_ensure_uint8_RGBA.js";
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.#
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
this.#
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
this.#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
this.#by_entity.
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
1
|
+
import { assert } from "../../core/assert.js";
|
|
2
|
+
import { FramePhase } from "../../shade/renderer/extension/FramePhase.js";
|
|
3
|
+
import { RenderExtension } from "../../shade/renderer/extension/RenderExtension.js";
|
|
4
|
+
import { GameAssetType } from "../asset/GameAssetType.js";
|
|
5
|
+
import { ImageRGBADataLoader } from "../asset/loaders/image/ImageRGBADataLoader.js";
|
|
6
|
+
import { System } from "../ecs/System.js";
|
|
7
|
+
import { Transform64 } from "../ecs/transform/Transform64.js";
|
|
8
|
+
import { Decal } from "../graphics/ecs/decal/v2/Decal.js";
|
|
9
|
+
import { ManagedAtlas } from "../graphics/texture/atlas/ManagedTextureAtlas.js";
|
|
10
|
+
import { SpriteAtlas } from "../graphics/texture/atlas/SpriteAtlas.js";
|
|
11
|
+
import { SpriteAtlasFill } from "../graphics/texture/atlas/SpriteAtlasFill.js";
|
|
12
|
+
import { sprite_atlas_max_lod } from "../graphics/texture/atlas/sprite_atlas_border.js";
|
|
13
|
+
import { sampler2d_ensure_uint8_RGBA } from "../graphics/texture/sampler/sampler2d_ensure_uint8_RGBA.js";
|
|
14
|
+
import {
|
|
15
|
+
decal_identity_albedo,
|
|
16
|
+
decal_identity_normal,
|
|
17
|
+
decal_identity_orm,
|
|
18
|
+
decal_pack_orm
|
|
19
|
+
} from "./decal/decal_material_samplers.js";
|
|
20
|
+
import { DECAL_RECORD_WORD_COUNT } from "./decal/DECAL_GPU_RECORD.js";
|
|
21
|
+
import { sort_decals_by_priority, write_decal_record } from "./decal/decal_gpu_records.js";
|
|
22
|
+
import { GPUDecalRenderer } from "./decal/GPUDecalRenderer.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Paints the game's decals into the G-buffer under Shade.
|
|
26
|
+
*
|
|
27
|
+
* **A decal is a surface override, not a tint** (D22): it carries albedo, a tangent-space normal,
|
|
28
|
+
* roughness, metalness and emission, and it writes them into the G-buffer before anything is lit —
|
|
29
|
+
* so ambient occlusion, screen-space reflection and shading all see a decal exactly as they see the
|
|
30
|
+
* surface it is painted on. The renderer this replaces could only lerp diffuse colour inside a
|
|
31
|
+
* forward shader.
|
|
32
|
+
*
|
|
33
|
+
* **Decals reach opaque surfaces only, by construction.** The G-buffer is all they touch and
|
|
34
|
+
* transparency composites later, so a decal will never appear on water.
|
|
35
|
+
*
|
|
36
|
+
* The records are rebuilt every frame. That sounds wasteful and is the cheaper arrangement: the
|
|
37
|
+
* froxel binning depends on the camera and so has to run every frame regardless, and rebuilding the
|
|
38
|
+
* records alongside it means nothing has to watch a decal's colour for changes — which matters,
|
|
39
|
+
* because the signal that would be watched does not fire for alpha-only edits.
|
|
40
|
+
*/
|
|
41
|
+
export class DecalSystem extends System {
|
|
42
|
+
dependencies = [Decal, Transform64];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @type {GraphicsEngine}
|
|
46
|
+
*/
|
|
47
|
+
#graphics;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @type {AssetManager}
|
|
51
|
+
*/
|
|
52
|
+
#assets;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @type {GPUDecalRenderer}
|
|
56
|
+
*/
|
|
57
|
+
#renderer = new GPUDecalRenderer();
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Three atlases, because their contents want different mip filters and different border fills —
|
|
61
|
+
* and because albedo is sRGB while the other two are not.
|
|
62
|
+
*
|
|
63
|
+
* @type {SpriteAtlas}
|
|
64
|
+
*/
|
|
65
|
+
#atlas_albedo = new SpriteAtlas(SpriteAtlasFill.PremultipliedCoverage);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @type {SpriteAtlas}
|
|
69
|
+
*/
|
|
70
|
+
#atlas_normal = new SpriteAtlas(SpriteAtlasFill.EdgeExtend);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @type {SpriteAtlas}
|
|
74
|
+
*/
|
|
75
|
+
#atlas_orm = new SpriteAtlas(SpriteAtlasFill.EdgeExtend);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @type {ManagedAtlas}
|
|
79
|
+
*/
|
|
80
|
+
#managed_albedo;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @type {ManagedAtlas}
|
|
84
|
+
*/
|
|
85
|
+
#managed_normal;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @type {ManagedAtlas}
|
|
89
|
+
*/
|
|
90
|
+
#managed_orm;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* What every decal authoring no maps of its own shares. One patch each, packed once.
|
|
94
|
+
*
|
|
95
|
+
* @type {Sampler2D}
|
|
96
|
+
*/
|
|
97
|
+
#identity_albedo = decal_identity_albedo();
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @type {Sampler2D}
|
|
101
|
+
*/
|
|
102
|
+
#identity_normal = decal_identity_normal();
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @type {Sampler2D}
|
|
106
|
+
*/
|
|
107
|
+
#identity_orm = decal_identity_orm();
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The decals to draw, in link order until {@link update} sorts them into draw order.
|
|
111
|
+
*
|
|
112
|
+
* @type {Array<{entity: number, decal: Decal, transform: Transform, patches: object, listener: Function}>}
|
|
113
|
+
*/
|
|
114
|
+
#entries = [];
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @type {Map<number, object>}
|
|
118
|
+
*/
|
|
119
|
+
#by_entity = new Map();
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @type {Float32Array}
|
|
123
|
+
*/
|
|
124
|
+
#records = new Float32Array(0);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* {@link #records} as words, for the fields that are bit patterns rather than floats.
|
|
128
|
+
*
|
|
129
|
+
* @type {Uint32Array}
|
|
130
|
+
*/
|
|
131
|
+
#record_words = new Uint32Array(this.#records.buffer);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @type {number}
|
|
135
|
+
*/
|
|
136
|
+
#record_count = 0;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @type {RenderExtension|null}
|
|
140
|
+
*/
|
|
141
|
+
#extension = null;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* What the pass draws. Read-only — the decals follow the entities.
|
|
145
|
+
*
|
|
146
|
+
* @returns {Array}
|
|
147
|
+
*/
|
|
148
|
+
get decals() {
|
|
149
|
+
return this.#entries;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @returns {number} decals packed for the GPU by the last update
|
|
154
|
+
*/
|
|
155
|
+
get record_count() {
|
|
156
|
+
return this.#record_count;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* What was packed, for a gate that wants to see it. Read-only.
|
|
161
|
+
*
|
|
162
|
+
* @returns {Float32Array}
|
|
163
|
+
*/
|
|
164
|
+
get records() {
|
|
165
|
+
return this.#records;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @param {GraphicsEngine} graphics
|
|
170
|
+
* @param {AssetManager} assets
|
|
171
|
+
*/
|
|
172
|
+
constructor(graphics, assets) {
|
|
173
|
+
super();
|
|
174
|
+
|
|
175
|
+
assert.defined(graphics, 'graphics');
|
|
176
|
+
assert.defined(assets, 'assets');
|
|
177
|
+
|
|
178
|
+
this.#graphics = graphics;
|
|
179
|
+
this.#assets = assets;
|
|
180
|
+
|
|
181
|
+
this.#managed_albedo = new ManagedAtlas({
|
|
182
|
+
assetManager: this.#assets,
|
|
183
|
+
atlas: this.#atlas_albedo
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
this.#managed_normal = new ManagedAtlas({
|
|
187
|
+
assetManager: this.#assets,
|
|
188
|
+
atlas: this.#atlas_normal
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
this.#managed_orm = new ManagedAtlas({
|
|
192
|
+
atlas: this.#atlas_orm,
|
|
193
|
+
load: async (key) => {
|
|
194
|
+
const separator = key.indexOf("\0");
|
|
195
|
+
const uri_orm = key.slice(0, separator);
|
|
196
|
+
const uri_emissive = key.slice(separator + 1);
|
|
197
|
+
|
|
198
|
+
const [orm, emissive] = await Promise.all([
|
|
199
|
+
uri_orm === "" ? null : this.#load_sampler(uri_orm),
|
|
200
|
+
uri_emissive === "" ? null : this.#load_sampler(uri_emissive)
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
return decal_pack_orm(orm, emissive);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param {string} uri
|
|
210
|
+
* @returns {Promise<import("../graphics/texture/sampler/Sampler2D.js").Sampler2D>}
|
|
211
|
+
*/
|
|
212
|
+
async #load_sampler(uri) {
|
|
213
|
+
const asset = await this.#assets.promise(uri, GameAssetType.Image);
|
|
214
|
+
|
|
215
|
+
return sampler2d_ensure_uint8_RGBA(asset.create());
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async startup(entityManager) {
|
|
219
|
+
this.entityManager = entityManager;
|
|
220
|
+
|
|
221
|
+
const assets = this.#assets;
|
|
222
|
+
|
|
223
|
+
if (!assets.hasLoaderForType(GameAssetType.Image)) {
|
|
224
|
+
await assets.registerLoader(GameAssetType.Image, new ImageRGBADataLoader());
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.#extension = this.#graphics.add_extension(new DecalExtension(this));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async shutdown(entityManager) {
|
|
231
|
+
if (this.#extension !== null) {
|
|
232
|
+
this.#graphics.remove_extension(this.#extension);
|
|
233
|
+
|
|
234
|
+
this.#extension = null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
for (let i = 0; i < this.#entries.length; i++) {
|
|
238
|
+
this.#release(this.#entries[i]);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
this.#renderer.destroy();
|
|
242
|
+
|
|
243
|
+
this.#entries.length = 0;
|
|
244
|
+
this.#by_entity.clear();
|
|
245
|
+
this.#record_count = 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The `transform` IS the projection volume, and it projects along its local **+Z** — so the
|
|
250
|
+
* surface being painted faces the other way. Get the sign backwards and every pixel of the
|
|
251
|
+
* decal is rejected by the coverage fade, silently, with every CPU-side observable here
|
|
252
|
+
* reporting success.
|
|
253
|
+
*
|
|
254
|
+
* @see Decal
|
|
255
|
+
* @see chunk_decal_surface_frame
|
|
256
|
+
*
|
|
257
|
+
* @param {Decal} decal
|
|
258
|
+
* @param {Transform64} transform
|
|
259
|
+
* @param {number} entity
|
|
260
|
+
*/
|
|
261
|
+
link(decal, transform, entity) {
|
|
262
|
+
const entry = {
|
|
263
|
+
entity,
|
|
264
|
+
decal,
|
|
265
|
+
transform,
|
|
266
|
+
/**
|
|
267
|
+
* Atlas patches, acquired as the textures arrive. A decal whose albedo has not loaded
|
|
268
|
+
* yet is not packed at all — its alpha is the decal's shape, and drawing it with the
|
|
269
|
+
* identity patch would put a white square on the ground until the image landed. Only a
|
|
270
|
+
* decal that names no albedo map at all draws with the identity patch.
|
|
271
|
+
*/
|
|
272
|
+
patches: { albedo: null, normal: null, orm: null }
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
this.#entries.push(entry);
|
|
276
|
+
this.#by_entity.set(entity, entry);
|
|
277
|
+
|
|
278
|
+
this.#acquire(entry);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @param {Decal} decal
|
|
283
|
+
* @param {Transform64} transform
|
|
284
|
+
* @param {number} entity
|
|
285
|
+
*/
|
|
286
|
+
unlink(decal, transform, entity) {
|
|
287
|
+
const entry = this.#by_entity.get(entity);
|
|
288
|
+
|
|
289
|
+
if (entry === undefined) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this.#release(entry);
|
|
294
|
+
|
|
295
|
+
const index = this.#entries.indexOf(entry);
|
|
296
|
+
|
|
297
|
+
if (index !== -1) {
|
|
298
|
+
this.#entries.splice(index, 1);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
this.#by_entity.delete(entity);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @param {object} entry
|
|
306
|
+
*/
|
|
307
|
+
#release(entry) {
|
|
308
|
+
const patches = entry.patches;
|
|
309
|
+
|
|
310
|
+
if (patches.albedo !== null) {
|
|
311
|
+
patches.albedo.release();
|
|
312
|
+
patches.albedo = null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (patches.normal !== null) {
|
|
316
|
+
patches.normal.release();
|
|
317
|
+
patches.normal = null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (patches.orm !== null) {
|
|
321
|
+
patches.orm.release();
|
|
322
|
+
patches.orm = null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Fetch this decal's textures and take a reference on the atlas patch each lands in.
|
|
328
|
+
*
|
|
329
|
+
* Reference counted and graveyard cached through {@link ManagedAtlas}, because combat spawns a
|
|
330
|
+
* footprint decal per step and every one of them names the same file: packing or erasing a patch
|
|
331
|
+
* per footprint would repack three atlases and regenerate their mip chains several times a second.
|
|
332
|
+
*
|
|
333
|
+
* @param {object} entry
|
|
334
|
+
*/
|
|
335
|
+
#acquire(entry) {
|
|
336
|
+
const decal = entry.decal;
|
|
337
|
+
|
|
338
|
+
const albedo_uri = decal.albedo_uri;
|
|
339
|
+
|
|
340
|
+
// no albedo map is a mask of one over the whole volume, coloured by the tint alone
|
|
341
|
+
entry.patches.albedo = albedo_uri === ""
|
|
342
|
+
? this.#managed_albedo.acquire_sampler(this.#identity_albedo)
|
|
343
|
+
: this.#managed_albedo.acquire(albedo_uri);
|
|
344
|
+
|
|
345
|
+
entry.patches.normal = decal.uri_normal === ""
|
|
346
|
+
? this.#managed_normal.acquire_sampler(this.#identity_normal)
|
|
347
|
+
: this.#managed_normal.acquire(decal.uri_normal);
|
|
348
|
+
|
|
349
|
+
entry.patches.orm = (decal.uri_orm === "" && decal.uri_emissive === "")
|
|
350
|
+
? this.#managed_orm.acquire_sampler(this.#identity_orm)
|
|
351
|
+
: this.#managed_orm.acquire(`${decal.uri_orm}\0${decal.uri_emissive}`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
update(timeDelta) {
|
|
355
|
+
const entries = this.#entries;
|
|
356
|
+
|
|
357
|
+
sort_decals_by_priority(entries);
|
|
358
|
+
|
|
359
|
+
this.#managed_albedo.update();
|
|
360
|
+
this.#managed_normal.update();
|
|
361
|
+
this.#managed_orm.update();
|
|
362
|
+
|
|
363
|
+
const required = entries.length * DECAL_RECORD_WORD_COUNT;
|
|
364
|
+
|
|
365
|
+
if (this.#records.length < required) {
|
|
366
|
+
this.#records = new Float32Array(required);
|
|
367
|
+
this.#record_words = new Uint32Array(this.#records.buffer);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const records = this.#records;
|
|
371
|
+
|
|
372
|
+
let count = 0;
|
|
373
|
+
|
|
374
|
+
for (let i = 0; i < entries.length; i++) {
|
|
375
|
+
const entry = entries[i];
|
|
376
|
+
const patches = entry.patches;
|
|
377
|
+
|
|
378
|
+
const albedo = patches.albedo?.getValue() ?? null;
|
|
379
|
+
const normal = patches.normal?.getValue() ?? null;
|
|
380
|
+
const orm = patches.orm?.getValue() ?? null;
|
|
381
|
+
|
|
382
|
+
if (albedo === null || normal === null || orm === null) {
|
|
383
|
+
// still waiting on an image; a decal is packed once it can be drawn properly
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
write_decal_record(
|
|
388
|
+
records,
|
|
389
|
+
this.#record_words,
|
|
390
|
+
count * DECAL_RECORD_WORD_COUNT,
|
|
391
|
+
entry.decal,
|
|
392
|
+
entry.transform.matrix,
|
|
393
|
+
{ albedo: albedo.uv, normal: normal.uv, orm: orm.uv },
|
|
394
|
+
{
|
|
395
|
+
albedo: sprite_atlas_max_lod(albedo.padding),
|
|
396
|
+
normal: sprite_atlas_max_lod(normal.padding),
|
|
397
|
+
orm: sprite_atlas_max_lod(orm.padding)
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
count++;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
this.#record_count = count;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @param {FrameContext} frame
|
|
409
|
+
*/
|
|
410
|
+
record(frame) {
|
|
411
|
+
if (this.#record_count === 0) {
|
|
412
|
+
/*
|
|
413
|
+
Nothing to paint, so the frame keeps the G-buffer it already had. Skipping is what makes
|
|
414
|
+
the replacement design free when no decal is on screen — the pass reads and rewrites
|
|
415
|
+
every pixel when it runs.
|
|
416
|
+
*/
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
this.#renderer.graph_draw({
|
|
421
|
+
frame,
|
|
422
|
+
records: this.#records,
|
|
423
|
+
record_count: this.#record_count,
|
|
424
|
+
atlas_albedo: this.#atlas_albedo.sampler,
|
|
425
|
+
atlas_normal: this.#atlas_normal.sampler,
|
|
426
|
+
atlas_orm: this.#atlas_orm.sampler
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* **Late on the phase**, because a decal composites over surfaces that are already written rather
|
|
433
|
+
* than preceding them — anything another extension writes into the G-buffer at this phase. That
|
|
434
|
+
* requirement used to be met by putting a registration call above an `await` and writing a comment
|
|
435
|
+
* about it; here it is the declaration below. The textured ground no longer depends on it: terrain is
|
|
436
|
+
* shaded in the G-buffer pass itself, before any extension runs.
|
|
437
|
+
*/
|
|
438
|
+
export class DecalExtension extends RenderExtension {
|
|
439
|
+
name = "decals";
|
|
440
|
+
|
|
441
|
+
phase = FramePhase.AfterGBuffer;
|
|
442
|
+
|
|
443
|
+
relative_order = 1;
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* @type {DecalSystem}
|
|
447
|
+
*/
|
|
448
|
+
#system;
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @param {DecalSystem} system
|
|
452
|
+
*/
|
|
453
|
+
constructor(system) {
|
|
454
|
+
super();
|
|
455
|
+
|
|
456
|
+
this.#system = system;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
record(frame) {
|
|
460
|
+
this.#system.record(frame);
|
|
461
|
+
}
|
|
462
|
+
}
|