@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.
Files changed (109) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/package.json +1 -1
  3. package/src/engine/ecs/EntityManager.d.ts +3 -3
  4. package/src/engine/ecs/EntityManager.js +3 -3
  5. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  6. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
  7. package/src/engine/graphics/ecs/decal/v2/Decal.d.ts +46 -2
  8. package/src/engine/graphics/ecs/decal/v2/Decal.d.ts.map +1 -1
  9. package/src/engine/graphics/ecs/decal/v2/Decal.js +74 -5
  10. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.d.ts.map +1 -1
  11. package/src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js +13 -1
  12. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts +9 -0
  13. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.d.ts.map +1 -0
  14. package/src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.js +37 -0
  15. package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
  16. package/src/engine/graphics3/DecalSystem.js +462 -447
  17. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts +14 -0
  18. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.d.ts.map +1 -1
  19. package/src/engine/graphics3/decal/DECAL_GPU_RECORD.js +53 -13
  20. package/src/engine/graphics3/decal/chunk_decal_record.d.ts +6 -1
  21. package/src/engine/graphics3/decal/chunk_decal_record.d.ts.map +1 -1
  22. package/src/engine/graphics3/decal/chunk_decal_record.js +28 -9
  23. package/src/engine/graphics3/decal/decal_gpu_records.d.ts +2 -1
  24. package/src/engine/graphics3/decal/decal_gpu_records.d.ts.map +1 -1
  25. package/src/engine/graphics3/decal/decal_gpu_records.js +26 -5
  26. package/src/engine/graphics3/decal/decal_material_samplers.d.ts +6 -0
  27. package/src/engine/graphics3/decal/decal_material_samplers.d.ts.map +1 -1
  28. package/src/engine/graphics3/decal/decal_material_samplers.js +13 -0
  29. package/src/engine/graphics3/decal/shader_cluster_assign_decals.js +1 -1
  30. package/src/engine/graphics3/decal/shader_cull_decals_frustum.js +1 -1
  31. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +5 -0
  32. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  33. package/src/engine/graphics3/decal/shader_decal_composite.js +69 -28
  34. package/src/engine/network/NetworkSession.d.ts +3 -0
  35. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  36. package/src/engine/network/NetworkSession.js +68 -10
  37. package/src/engine/network/README.md +6 -3
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +51 -5
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  40. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +308 -34
  41. package/src/engine/network/replication/Replicator.d.ts +8 -2
  42. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  43. package/src/engine/network/replication/Replicator.js +13 -4
  44. package/src/engine/network/sim/ActionLog.d.ts +16 -2
  45. package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
  46. package/src/engine/network/sim/ActionLog.js +33 -2
  47. package/src/engine/network/sim/RewindEngine.d.ts +9 -0
  48. package/src/engine/network/sim/RewindEngine.d.ts.map +1 -1
  49. package/src/engine/network/sim/RewindEngine.js +15 -1
  50. package/src/engine/network/state/FrameBufferRing.d.ts +12 -5
  51. package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
  52. package/src/engine/network/state/FrameBufferRing.js +32 -6
  53. package/src/engine/network/time/TimeDilation.d.ts +30 -14
  54. package/src/engine/network/time/TimeDilation.d.ts.map +1 -1
  55. package/src/engine/network/time/TimeDilation.js +47 -17
  56. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  57. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +3 -2
  58. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
  59. package/src/generation/foliage/skeleton/ShootWoodHash.js +25 -2
  60. package/src/shade/renderer/buffer/graph_read_buffer.d.ts +3 -1
  61. package/src/shade/renderer/buffer/graph_read_buffer.d.ts.map +1 -1
  62. package/src/shade/renderer/buffer/graph_read_buffer.js +9 -6
  63. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts +5 -0
  64. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.d.ts.map +1 -1
  65. package/src/shade/renderer/buffer/util/shader_buffer_copy_storage_to_storage.js +48 -43
  66. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  67. package/src/shade/renderer/material/GPUMaterialManager.js +117 -35
  68. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +2 -2
  69. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  70. package/src/shade/renderer/material/standard/fragment_gbuffer.js +10 -3
  71. package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts +15 -3
  72. package/src/shade/renderer/material/standard/material_gbuffer_vertex.d.ts.map +1 -1
  73. package/src/shade/renderer/material/standard/material_gbuffer_vertex.js +25 -4
  74. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +23 -5
  75. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  76. package/src/shade/renderer/particles/GPUParticleSystem.js +294 -20
  77. package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.d.ts +21 -0
  78. package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.d.ts.map +1 -0
  79. package/src/shade/renderer/particles/resize/shader_particle_shrink_alive_list.js +83 -0
  80. package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.d.ts +21 -0
  81. package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.d.ts.map +1 -0
  82. package/src/shade/renderer/particles/resize/shader_particle_shrink_free_list.js +64 -0
  83. package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
  84. package/src/shade/renderer/restir/di/chunk_restir_resolve.js +91 -94
  85. package/src/shade/renderer/restir/reservoir/chunk_rtxdi_stream_sample.js +1 -1
  86. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts +14 -0
  87. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.d.ts.map +1 -1
  88. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_decode.js +36 -21
  89. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts +22 -0
  90. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.d.ts.map +1 -0
  91. package/src/shade/renderer/shader/chunk/color/rgbe9995/chunk_rgbe9995_sample_gather.js +64 -0
  92. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.d.ts.map +1 -1
  93. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_vertex_normal.js +13 -18
  94. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.d.ts.map +1 -1
  95. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_encode_vertex_normal.js +28 -30
  96. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.d.ts.map +1 -1
  97. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_u32_to_vec2.js +15 -16
  98. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts +0 -1
  99. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.d.ts.map +1 -1
  100. package/src/shade/renderer/shader/chunk/geometry/vec2/chunk_unit_vec2_to_u32.js +15 -18
  101. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.d.ts +32 -0
  102. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.d.ts.map +1 -0
  103. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_bitset_or.js +73 -0
  104. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +8 -1
  105. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  106. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +7 -3
  107. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts +0 -2
  108. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.d.ts.map +0 -1
  109. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_sh3_color_encode.js +0 -6
package/CHANGELOG.md CHANGED
@@ -2,6 +2,96 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ### Network: a client ahead of the host repays its lead in seconds
6
+
7
+ - **Fixed:** a client that found itself far ahead of the host — the host lost time: a hidden or hitched
8
+ host tab, a slow host — slowed down at the steering's 5% whatever the size of the lead, and so took
9
+ about twenty frames per frame of lead to get back: half a minute after a 90-frame host stall at 60 Hz,
10
+ longer than a session would wait after 180. All that time its input reached the host that much late,
11
+ host frames landed past its action log, and a Replay client abandoned its reconciliations. `TimeDilation`
12
+ still steers an error behind, and one up to `max_dilation × T` frames ahead (4.35 at the default
13
+ `frame_capacity`), at up to `max_dilation`, and still runs fast at no more than that; a larger lead is
14
+ now repaid in proportion to its size — the client runs at `1 / (1 + lead / T)` of its rate, never
15
+ reaching a standstill, with `T` e times the longest round trip it is built for, so that on any round
16
+ trip up to that one it overshoots no further than the steering does. At 60 Hz with the default
17
+ `frame_capacity` a 90-frame lead is gone in about 400 frames and a 180-frame one in about 550.
18
+ - **Fixed:** `NetworkSession` ran a client at the host's latest factor however little that report still
19
+ held. A report names the newest frame of the client's the host has seen, a running maximum the host
20
+ never lowers, so after the client's clock went back — a `seek_to_frame` back, a re-sync from ahead — it
21
+ was about frames the client had left; the client now runs at its nominal rate until its clock passes
22
+ that frame again. With no report on the current binding, or none for longer than the longest round
23
+ trip, the latest one may still steer but repays nothing: held through a silent link, a repayment
24
+ would put the client behind the host and its input past the host's window.
25
+ - **Breaking:** `TimeDilation` takes `max_round_trip_frames`, the longest round trip in frames its reports
26
+ can be, and it is required. `NetworkSession` and `ServerAuthoritativeClient` pass their `frame_capacity`.
27
+
28
+ ### Particles: a scene's pool holds 131,072 particles
29
+
30
+ - **Changed:** `GPUParticleSystem`'s default capacity is 131,072 particles, up from 65,536. The
31
+ renderer creates every scene's particle system at the default, so this is every scene's pool: about
32
+ 18 MB of GPU memory (the 128-byte record pool, the free and alive lists and the coherence scratch),
33
+ up from about 9 MB. Spawns past a full pool are dropped as before.
34
+
35
+ ### Network: an abandoned reconciliation leaves the world at the present
36
+
37
+ - **Fixed:** a Replay client whose AUTH_STATE needed a frame its action log no longer holds — one
38
+ further ahead of the server's frame than `frame_capacity` covers, as after a host stall — undid its
39
+ frames from the present back to the missing one, up to `frame_capacity` of them, before it found the
40
+ gap. It then abandoned the reconciliation and predicted on from that past world: its own entities lost
41
+ those frames of input, and everything else the frames wrote went back as far. The client now checks
42
+ that the log holds every frame the rewind undoes before it undoes any, so an abandoned reconciliation
43
+ changes nothing; it is counted and announced as before. An error thrown during the rewind is no longer
44
+ counted as an abandoned reconciliation: it is thrown, as an error in the replay is.
45
+
46
+ ### Network: a client that comes back on a new connection applies each host frame once
47
+
48
+ - **Fixed:** a client that lost its connection and came back applied host frames it had already
49
+ applied a second time, so a relative write to an entity it does not own (`x += 1`) ran twice and
50
+ nothing corrected it. For every step the host closed before it read the client's `RESUME_HELLO`, it
51
+ packed the new connection's action stream from the oldest frame its log held, and the client applied
52
+ that stream once the host answered: on top of its world when the host resumed it, and on top of the
53
+ host's snapshot when the host refused the claim and sent its world again. The host now sends a
54
+ returning connection none of its action stream until it has read the claim, and on a resume only the
55
+ frames after the one claimed.
56
+ - **Fixed:** a client that lost its connection right after its join, before any frame after the
57
+ snapshot reached it, claimed frame 0, or the newest frame of the world it held before. While the
58
+ host's log still reached back to that frame, the frames up to the snapshot's were applied again; once
59
+ it did not, the host refused the claim and sent its whole world again. The client now claims the frame
60
+ its last join's snapshot was taken at, or the newest frame it has applied since.
61
+
62
+ ### Network: records for a frame the action log has moved past no longer erase a frame it holds
63
+
64
+ - **Fixed:** a peer that received records for a frame `frame_capacity` or more behind its newest — a
65
+ client on a round trip of about `frame_capacity` ticks, after a host stall, or after a link that held
66
+ its packets and delivered them at once — logged them in that frame's ring slot, which held one of its
67
+ own recent frames, and erased it: its own input there, which its outbound stream then counted as
68
+ sent without sending it again, and the prior state a rewind across the frame needs, so a Replay
69
+ client abandoned every reconciliation that crossed it. Such records are now applied to the world as
70
+ they arrive and not logged, since no rewind reaches their frame, and the frame in the slot keeps its
71
+ records. `ActionLog.resume_frame` keeps nothing of a frame the log has moved past;
72
+ `Replicator.onFrameApplied` still fires for one, and the log does not hold it.
73
+
74
+ ### Network: a host record that arrives late lands in its frame on a Replay client
75
+
76
+ - **Fixed:** a Replay client applied a host record that arrived for a frame it had already predicted
77
+ past to the world as it stood, frames later, and its later frames kept the prior state they had
78
+ captured before the record. A rewind for another entity's AUTH_STATE put that state back, undoing the
79
+ host's write until the entity's own next AUTH_STATE, or for good where none came (SW_316). When such a
80
+ record writes something a later record, or the server's correction of its own frame, holds prior
81
+ state of, the client now rewinds to the end of the record's frame, applies it there — before that
82
+ frame's corrections, as a replay writes a frame — and replays what it predicted since. A record about
83
+ nothing written since stays where it landed, with no rewind. The test is on what records write: one
84
+ that only reads predicted state keeps what it read at the present until a replay crosses its frame.
85
+ - **Fixed:** a replay that meets an arrived record which throws no longer stops in that frame with the
86
+ world in the past: every frame is replayed, the record is left out of the one it threw in, that
87
+ frame's corrections are applied as ever, and the first error is thrown once the world is back at the
88
+ present.
89
+ - **Added:** `ServerAuthoritativeClient` option `rebase_on_arrival` (default true; `NetworkSession`
90
+ passes it for `NetworkSessionReconcile.Replay` only, since Correct never rewinds) and counter
91
+ `rebase_count`; `RewindEngine.undo_frame_from(frame, from)`; `ActionLog.resume_frame_at(frame,
92
+ offset)`. `Replicator.onFrameApplied` passes a third argument, `records_start`: where in the action
93
+ log's frame the records it just applied begin.
94
+
5
95
  ### Probe clipmap GI: virtual geometry has cards, through a proxy
6
96
 
7
97
  - **Added:** `VirtualGeometry.get_proxy()`: an ordinary geometry standing in for a virtual one, cut from its
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Advanced 3D game engine",
7
7
  "type": "module",
8
8
  "author": "Alexander Goldring",
9
- "version": "3.60.9",
9
+ "version": "3.61.1",
10
10
  "exports": {
11
11
  "./build/*": "./build/*",
12
12
  "./src/*": "./src/*",
@@ -145,9 +145,9 @@ export class EntityManager {
145
145
  *
146
146
  * So this changes how often a fixed step runs, never how long one is: at `1.05` the simulation
147
147
  * advances 5% more steps per wall second, each one the same size, and the interpolation alpha
148
- * stays a true fraction of a step. That is what network time dilation needs — a client running a
149
- * few percent fast or slow to keep the host's input buffer at depth — and what dropping or
150
- * doubling whole steps could not give it: a skipped step reads as a hitch.
148
+ * stays a true fraction of a step. That is what network time dilation needs — a client running
149
+ * fast or slow to keep the host's input buffer at depth — and what dropping or doubling whole steps
150
+ * could not give it: a skipped step reads as a hitch.
151
151
  *
152
152
  * Must be finite and non-negative. `0` freezes the fixed-step simulation (the `update` pass keeps
153
153
  * running).
@@ -193,9 +193,9 @@ export class EntityManager {
193
193
  *
194
194
  * So this changes how often a fixed step runs, never how long one is: at `1.05` the simulation
195
195
  * advances 5% more steps per wall second, each one the same size, and the interpolation alpha
196
- * stays a true fraction of a step. That is what network time dilation needs — a client running a
197
- * few percent fast or slow to keep the host's input buffer at depth — and what dropping or
198
- * doubling whole steps could not give it: a skipped step reads as a hitch.
196
+ * stays a true fraction of a step. That is what network time dilation needs — a client running
197
+ * fast or slow to keep the host's input buffer at depth — and what dropping or doubling whole steps
198
+ * could not give it: a skipped step reads as a hitch.
199
199
  *
200
200
  * Must be finite and non-negative. `0` freezes the fixed-step simulation (the `update` pass keeps
201
201
  * running).
@@ -1 +1 @@
1
- {"version":3,"file":"populateEngineSerializationRegistry.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/storage/populateEngineSerializationRegistry.js"],"names":[],"mappings":"AA0MA;;;;;;;;GAQG;AACH,iGA0HC"}
1
+ {"version":3,"file":"populateEngineSerializationRegistry.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/storage/populateEngineSerializationRegistry.js"],"names":[],"mappings":"AA6MA;;;;;;;;GAQG;AACH,iGA2HC"}
@@ -85,6 +85,9 @@ import { DecalSerializationAdapter } from "../../graphics/ecs/decal/v2/DecalSeri
85
85
  import {
86
86
  DecalSerializationUpgrader_0_1
87
87
  } from "../../graphics/ecs/decal/v2/DecalSerializationUpgrader_0_1.js";
88
+ import {
89
+ DecalSerializationUpgrader_1_2
90
+ } from "../../graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.js";
88
91
  import Highlight from "../../graphics/ecs/highlight/Highlight.js";
89
92
  import { HighlightSerializationAdapter } from "../../graphics/ecs/highlight/HighlightSerializationAdapter.js";
90
93
  import {
@@ -291,6 +294,7 @@ export function populateEngineSerializationRegistry(registry) {
291
294
  registry.registerUpgrader(Tag.typeName, new TagSerializationUpgrader_0_1());
292
295
  registry.registerUpgrader(ParticipatingMedia.typeName, new ParticipatingMediaSerializationUpgrader_0_1());
293
296
  registry.registerUpgrader(Decal.typeName, new DecalSerializationUpgrader_0_1());
297
+ registry.registerUpgrader(Decal.typeName, new DecalSerializationUpgrader_1_2());
294
298
 
295
299
  registry.registerUpgrader(FogOfWar.typeName, new FogOfWarSerializationUpdater_0_1());
296
300
 
@@ -36,7 +36,12 @@ export class Decal {
36
36
  */
37
37
  uri: string;
38
38
  /**
39
- * Base colour and coverage. Its alpha is what the decal's coverage means.
39
+ * Base colour and the decal's mask. Its alpha is the coverage every channel blends by, scaled
40
+ * per channel by the `*_weight` fields — so a decal that writes only normals still takes its
41
+ * shape from this alpha, with {@link albedo_weight} at zero.
42
+ *
43
+ * Optional: with none, the mask is one across the whole projection volume and the colour is
44
+ * {@link color}.
40
45
  * @type {string}
41
46
  */
42
47
  uri_albedo: string;
@@ -87,6 +92,35 @@ export class Decal {
87
92
  * @type {number}
88
93
  */
89
94
  emissive_intensity: number;
95
+ /**
96
+ * How much of this decal's albedo is written, in [0, 1]. It scales the coverage this one channel
97
+ * blends by: zero leaves the surface's albedo exactly as it was, one writes it at the full
98
+ * coverage of the mask. Carried to the GPU as a 16-bit unorm.
99
+ * @type {number}
100
+ */
101
+ albedo_weight: number;
102
+ /**
103
+ * How much of this decal's normal is written, in [0, 1]. As {@link albedo_weight}.
104
+ * @type {number}
105
+ */
106
+ normal_weight: number;
107
+ /**
108
+ * How much of this decal's roughness is written, in [0, 1]. As {@link albedo_weight}.
109
+ * @type {number}
110
+ */
111
+ roughness_weight: number;
112
+ /**
113
+ * How much of this decal's metalness is written, in [0, 1]. As {@link albedo_weight}.
114
+ * @type {number}
115
+ */
116
+ metalness_weight: number;
117
+ /**
118
+ * How much of this decal's emission is written, in [0, 1]. As {@link albedo_weight} — and since a
119
+ * decal's emission replaces what is beneath it rather than adding to it, zero is also what keeps
120
+ * an emitting surface emitting under a decal.
121
+ * @type {number}
122
+ */
123
+ emissive_weight: number;
90
124
  /**
91
125
  * Internal transient reference to loaded asset
92
126
  * @type {Sampler2D|null}
@@ -119,8 +153,13 @@ export class Decal {
119
153
  metalness: number;
120
154
  emissive_color: string;
121
155
  emissive_intensity: number;
156
+ albedo_weight: number;
157
+ normal_weight: number;
158
+ roughness_weight: number;
159
+ metalness_weight: number;
160
+ emissive_weight: number;
122
161
  };
123
- fromJSON({ uri, uri_albedo, uri_normal, uri_orm, uri_emissive, priority, color, roughness, metalness, emissive_color, emissive_intensity }: {
162
+ fromJSON({ uri, uri_albedo, uri_normal, uri_orm, uri_emissive, priority, color, roughness, metalness, emissive_color, emissive_intensity, albedo_weight, normal_weight, roughness_weight, metalness_weight, emissive_weight }: {
124
163
  uri?: string;
125
164
  uri_albedo?: string;
126
165
  uri_normal?: string;
@@ -132,6 +171,11 @@ export class Decal {
132
171
  metalness?: number;
133
172
  emissive_color?: string;
134
173
  emissive_intensity?: number;
174
+ albedo_weight?: number;
175
+ normal_weight?: number;
176
+ roughness_weight?: number;
177
+ metalness_weight?: number;
178
+ emissive_weight?: number;
135
179
  }): void;
136
180
  hash(): number;
137
181
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Decal.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/ecs/decal/v2/Decal.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IAmGI,+BAMC;IAvGD;;;;;;;OAOG;IACH,KAFU,MAAM,CAEP;IAET;;;OAGG;IACH,YAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,YAFU,MAAM,CAEA;IAEhB;;;;;OAKG;IACH,SAFU,MAAM,CAEH;IAEb;;;;OAIG;IACH,cAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,OAFU,KAAK,CAEe;IAE9B;;;OAGG;IACH,WAFU,MAAM,CAEF;IAEd;;OAEG;IACH,WAFU,MAAM,CAEF;IAEd;;OAEG;IACH,gBAFU,KAAK,CAEwB;IAEvC;;;;OAIG;IACH,oBAFU,MAAM,CAEO;IAEvB;;;;OAIG;IACH,yBAAwB;IAExB;;;;OAIG;IACH,qBAAoB;IAEpB;;;;;;OAMG;IACH,yBAEC;IAUD;;;;;;;;;;;;MAcC;IAED;;;;;;;;;;;;aA+CC;IAED,eAkBC;IAED;;;;OAIG;IACH,cAHW,KAAK,GACH,OAAO,CAenB;CACJ;;;;sBApPqB,oCAAoC"}
1
+ {"version":3,"file":"Decal.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/ecs/decal/v2/Decal.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IA0II,+BAMC;IA9ID;;;;;;;OAOG;IACH,KAFU,MAAM,CAEP;IAET;;;;;;;;OAQG;IACH,YAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,YAFU,MAAM,CAEA;IAEhB;;;;;OAKG;IACH,SAFU,MAAM,CAEH;IAEb;;;;OAIG;IACH,cAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,OAFU,KAAK,CAEe;IAE9B;;;OAGG;IACH,WAFU,MAAM,CAEF;IAEd;;OAEG;IACH,WAFU,MAAM,CAEF;IAEd;;OAEG;IACH,gBAFU,KAAK,CAEwB;IAEvC;;;;OAIG;IACH,oBAFU,MAAM,CAEO;IAEvB;;;;;OAKG;IACH,eAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,eAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,kBAFU,MAAM,CAEK;IAErB;;;OAGG;IACH,kBAFU,MAAM,CAEK;IAErB;;;;;OAKG;IACH,iBAFU,MAAM,CAEI;IAEpB;;;;OAIG;IACH,yBAAwB;IAExB;;;;OAIG;IACH,qBAAoB;IAEpB;;;;;;OAMG;IACH,yBAEC;IAUD;;;;;;;;;;;;;;;;;MAmBC;IAED;;;;;;;;;;;;;;;;;aA+DC;IAED,eAsBC;IAED;;;;OAIG;IACH,cAHW,KAAK,GACH,OAAO,CAoBnB;CACJ;;;;sBAzTqB,oCAAoC"}
@@ -44,7 +44,12 @@ export class Decal {
44
44
  uri = "";
45
45
 
46
46
  /**
47
- * Base colour and coverage. Its alpha is what the decal's coverage means.
47
+ * Base colour and the decal's mask. Its alpha is the coverage every channel blends by, scaled
48
+ * per channel by the `*_weight` fields — so a decal that writes only normals still takes its
49
+ * shape from this alpha, with {@link albedo_weight} at zero.
50
+ *
51
+ * Optional: with none, the mask is one across the whole projection volume and the colour is
52
+ * {@link color}.
48
53
  * @type {string}
49
54
  */
50
55
  uri_albedo = "";
@@ -105,6 +110,40 @@ export class Decal {
105
110
  */
106
111
  emissive_intensity = 0;
107
112
 
113
+ /**
114
+ * How much of this decal's albedo is written, in [0, 1]. It scales the coverage this one channel
115
+ * blends by: zero leaves the surface's albedo exactly as it was, one writes it at the full
116
+ * coverage of the mask. Carried to the GPU as a 16-bit unorm.
117
+ * @type {number}
118
+ */
119
+ albedo_weight = 1;
120
+
121
+ /**
122
+ * How much of this decal's normal is written, in [0, 1]. As {@link albedo_weight}.
123
+ * @type {number}
124
+ */
125
+ normal_weight = 1;
126
+
127
+ /**
128
+ * How much of this decal's roughness is written, in [0, 1]. As {@link albedo_weight}.
129
+ * @type {number}
130
+ */
131
+ roughness_weight = 1;
132
+
133
+ /**
134
+ * How much of this decal's metalness is written, in [0, 1]. As {@link albedo_weight}.
135
+ * @type {number}
136
+ */
137
+ metalness_weight = 1;
138
+
139
+ /**
140
+ * How much of this decal's emission is written, in [0, 1]. As {@link albedo_weight} — and since a
141
+ * decal's emission replaces what is beneath it rather than adding to it, zero is also what keeps
142
+ * an emitting surface emitting under a decal.
143
+ * @type {number}
144
+ */
145
+ emissive_weight = 1;
146
+
108
147
  /**
109
148
  * Internal transient reference to loaded asset
110
149
  * @type {Sampler2D|null}
@@ -150,7 +189,12 @@ export class Decal {
150
189
  roughness: this.roughness,
151
190
  metalness: this.metalness,
152
191
  emissive_color: this.emissive_color.toCssRGBAString(),
153
- emissive_intensity: this.emissive_intensity
192
+ emissive_intensity: this.emissive_intensity,
193
+ albedo_weight: this.albedo_weight,
194
+ normal_weight: this.normal_weight,
195
+ roughness_weight: this.roughness_weight,
196
+ metalness_weight: this.metalness_weight,
197
+ emissive_weight: this.emissive_weight
154
198
  };
155
199
  }
156
200
 
@@ -165,7 +209,12 @@ export class Decal {
165
209
  roughness = 1,
166
210
  metalness = 0,
167
211
  emissive_color = '#FFFFFF',
168
- emissive_intensity = 0
212
+ emissive_intensity = 0,
213
+ albedo_weight = 1,
214
+ normal_weight = 1,
215
+ roughness_weight = 1,
216
+ metalness_weight = 1,
217
+ emissive_weight = 1
169
218
  }) {
170
219
 
171
220
  assert.isString(uri, 'uri');
@@ -178,6 +227,11 @@ export class Decal {
178
227
  assert.isNumber(roughness, 'roughness');
179
228
  assert.isNumber(metalness, 'metalness');
180
229
  assert.isNumber(emissive_intensity, 'emissive_intensity');
230
+ assert.isNumber(albedo_weight, 'albedo_weight');
231
+ assert.isNumber(normal_weight, 'normal_weight');
232
+ assert.isNumber(roughness_weight, 'roughness_weight');
233
+ assert.isNumber(metalness_weight, 'metalness_weight');
234
+ assert.isNumber(emissive_weight, 'emissive_weight');
181
235
 
182
236
  const albedo_before = this.albedo_uri;
183
237
 
@@ -199,12 +253,18 @@ export class Decal {
199
253
  this.metalness = metalness;
200
254
  this.emissive_intensity = emissive_intensity;
201
255
 
256
+ this.albedo_weight = albedo_weight;
257
+ this.normal_weight = normal_weight;
258
+ this.roughness_weight = roughness_weight;
259
+ this.metalness_weight = metalness_weight;
260
+ this.emissive_weight = emissive_weight;
261
+
202
262
  this.color.parse(color);
203
263
  this.emissive_color.parse(emissive_color);
204
264
  }
205
265
 
206
266
  hash() {
207
- return hash_mix3(
267
+ return hash_mix2(hash_mix3(
208
268
  computeStringHash(this.uri) ^ this.color.hash(),
209
269
  hash_mix2(
210
270
  hash_mix2(
@@ -220,7 +280,11 @@ export class Decal {
220
280
  hash_mix2(computeHashFloat(this.roughness), computeHashFloat(this.metalness)),
221
281
  hash_mix2(this.emissive_color.hash(), computeHashFloat(this.emissive_intensity))
222
282
  )
223
- );
283
+ ), hash_mix3(
284
+ hash_mix2(computeHashFloat(this.albedo_weight), computeHashFloat(this.normal_weight)),
285
+ hash_mix2(computeHashFloat(this.roughness_weight), computeHashFloat(this.metalness_weight)),
286
+ computeHashFloat(this.emissive_weight)
287
+ ));
224
288
  }
225
289
 
226
290
  /**
@@ -240,6 +304,11 @@ export class Decal {
240
304
  && this.metalness === other.metalness
241
305
  && this.emissive_color.equals(other.emissive_color)
242
306
  && this.emissive_intensity === other.emissive_intensity
307
+ && this.albedo_weight === other.albedo_weight
308
+ && this.normal_weight === other.normal_weight
309
+ && this.roughness_weight === other.roughness_weight
310
+ && this.metalness_weight === other.metalness_weight
311
+ && this.emissive_weight === other.emissive_weight
243
312
  ;
244
313
  }
245
314
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DecalSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js"],"names":[],"mappings":"AAGA;;IAEI,oBAAc;IAGd;;;;OAIG;IACH,uCAFW,KAAK,QAmBf;IAED;;;;OAIG;IACH,yCAFW,KAAK,QAmBf;CACJ;gDAvD+C,mEAAmE;sBAC7F,YAAY"}
1
+ {"version":3,"file":"DecalSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/ecs/decal/v2/DecalSerializationAdapter.js"],"names":[],"mappings":"AAGA;;IAEI,oBAAc;IAGd;;;;OAIG;IACH,uCAFW,KAAK,QAyBf;IAED;;;;OAIG;IACH,yCAFW,KAAK,QAyBf;CACJ;gDAnE+C,mEAAmE;sBAC7F,YAAY"}
@@ -4,7 +4,7 @@ import { Decal } from "./Decal.js";
4
4
  export class DecalSerializationAdapter extends BinaryClassSerializationAdapter {
5
5
 
6
6
  klass = Decal;
7
- version = 1;
7
+ version = 2;
8
8
 
9
9
  /**
10
10
  *
@@ -28,6 +28,12 @@ export class DecalSerializationAdapter extends BinaryClassSerializationAdapter {
28
28
  buffer.writeFloat32Array(value.emissive_color, 0, 4);
29
29
  buffer.writeFloat32(value.emissive_intensity);
30
30
 
31
+ buffer.writeFloat32(value.albedo_weight);
32
+ buffer.writeFloat32(value.normal_weight);
33
+ buffer.writeFloat32(value.roughness_weight);
34
+ buffer.writeFloat32(value.metalness_weight);
35
+ buffer.writeFloat32(value.emissive_weight);
36
+
31
37
  }
32
38
 
33
39
  /**
@@ -52,5 +58,11 @@ export class DecalSerializationAdapter extends BinaryClassSerializationAdapter {
52
58
  buffer.readFloat32Array(value.emissive_color, 0, 4);
53
59
  value.emissive_intensity = buffer.readFloat32();
54
60
 
61
+ value.albedo_weight = buffer.readFloat32();
62
+ value.normal_weight = buffer.readFloat32();
63
+ value.roughness_weight = buffer.readFloat32();
64
+ value.metalness_weight = buffer.readFloat32();
65
+ value.emissive_weight = buffer.readFloat32();
66
+
55
67
  }
56
68
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A v1 decal wrote every channel it carries. v2 adds a weight per channel, and a v1 decal comes
3
+ * back with all five at one — which is what writing every channel means.
4
+ */
5
+ export class DecalSerializationUpgrader_1_2 extends BinaryClassUpgrader {
6
+ upgrade(source: any, target: any): void;
7
+ }
8
+ import { BinaryClassUpgrader } from "../../../../ecs/storage/binary/BinaryClassUpgrader.js";
9
+ //# sourceMappingURL=DecalSerializationUpgrader_1_2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecalSerializationUpgrader_1_2.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/ecs/decal/v2/DecalSerializationUpgrader_1_2.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH;IAII,wCAyBC;CACJ;oCApCmC,uDAAuD"}
@@ -0,0 +1,37 @@
1
+ import { BinaryClassUpgrader } from "../../../../ecs/storage/binary/BinaryClassUpgrader.js";
2
+
3
+ /**
4
+ * A v1 decal wrote every channel it carries. v2 adds a weight per channel, and a v1 decal comes
5
+ * back with all five at one — which is what writing every channel means.
6
+ */
7
+ export class DecalSerializationUpgrader_1_2 extends BinaryClassUpgrader {
8
+ __startVersion = 1;
9
+ __targetVersion = 2;
10
+
11
+ upgrade(source, target) {
12
+ // uri, uri_albedo, uri_normal, uri_orm, uri_emissive
13
+ for (let i = 0; i < 5; i++) {
14
+ target.writeUTF8String(source.readUTF8String());
15
+ }
16
+
17
+ const scratch = [0, 0, 0, 0];
18
+
19
+ target.writeFloat32(source.readFloat32()); // priority
20
+
21
+ source.readFloat32Array(scratch, 0, 4);
22
+ target.writeFloat32Array(scratch, 0, 4); // color
23
+
24
+ target.writeFloat32(source.readFloat32()); // roughness
25
+ target.writeFloat32(source.readFloat32()); // metalness
26
+
27
+ source.readFloat32Array(scratch, 0, 4);
28
+ target.writeFloat32Array(scratch, 0, 4); // emissive_color
29
+
30
+ target.writeFloat32(source.readFloat32()); // emissive_intensity
31
+
32
+ // albedo, normal, roughness, metalness, emissive weights
33
+ for (let i = 0; i < 5; i++) {
34
+ target.writeFloat32(1);
35
+ }
36
+ }
37
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"DecalSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/DecalSystem.js"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;GAgBG;AACH;IAmHI;;;OAGG;IACH,4DAkCC;IAxJD,oDAAoC;IAyFpC;;;;OAIG;IACH,oBAEC;IAED;;OAEG;IACH,2BAEC;IAED;;;;OAIG;IACH,4BAEC;IAoDD,2CAUC;IAED,4CAgBC;IAED;;;;;;;;;;;;OAYG;IACH,YAJW,KAAK,aACL,WAAW,UACX,MAAM,QAmBhB;IAED;;;;OAIG;IACH,cAJW,KAAK,aACL,WAAW,UACX,MAAM,QAkBhB;IAqDD,6BAiDC;IAED;;OAEG;IACH,kCAkBC;;CACJ;AAED;;;;;;GAMG;AACH;IAYI;;OAEG;IACH,oBAFW,WAAW,EAMrB;IAED,yBAEC;;CACJ;uBAzbsB,kBAAkB;4BACb,iCAAiC;sBACvC,mCAAmC;gCALzB,mDAAmD"}
1
+ {"version":3,"file":"DecalSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/DecalSystem.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;GAgBG;AACH;IA+HI;;;OAGG;IACH,4DAkCC;IApKD,oDAAoC;IAqGpC;;;;OAIG;IACH,oBAEC;IAED;;OAEG;IACH,2BAEC;IAED;;;;OAIG;IACH,4BAEC;IAoDD,2CAUC;IAED,4CAgBC;IAED;;;;;;;;;;;;OAYG;IACH,YAJW,KAAK,aACL,WAAW,UACX,MAAM,QAoBhB;IAED;;;;OAIG;IACH,cAJW,KAAK,aACL,WAAW,UACX,MAAM,QAkBhB;IAoDD,6BAmDC;IAED;;OAEG;IACH,kCAkBC;;CACJ;AAED;;;;;;GAMG;AACH;IAYI;;OAEG;IACH,oBAFW,WAAW,EAMrB;IAED,yBAEC;;CACJ;uBAxcsB,kBAAkB;4BACb,iCAAiC;sBACvC,mCAAmC;gCALzB,mDAAmD"}