@woosh/meep-engine 3.18.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -1
  4. package/editor/view/particles/effect/ParticleCurveEditorView.js +303 -120
  5. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -1
  6. package/editor/view/particles/effect/ParticleGradientEditorView.js +108 -63
  7. package/editor/view/particles/effect/ParticleGraphEditorView.js +2 -2
  8. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  9. package/editor/view/particles/effect/ParticleNodeParametersView.js +7 -46
  10. package/editor/view/particles/effect/particle-editor.css +60 -30
  11. package/package.json +1 -2
  12. package/samples/engine/README.md +1 -1
  13. package/src/core/binary/compression/decompress_bytes.d.ts +13 -0
  14. package/src/core/binary/compression/decompress_bytes.d.ts.map +1 -0
  15. package/src/core/binary/compression/decompress_bytes.js +28 -0
  16. package/src/core/collection/array/array_group_by.d.ts.map +1 -1
  17. package/src/core/collection/array/array_group_by.js +2 -11
  18. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  19. package/src/core/geom/3d/shape/HeightMapShape3D.js +4 -9
  20. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +67 -22
  21. package/src/core/model/object/optional_clone.d.ts +7 -0
  22. package/src/core/model/object/optional_clone.d.ts.map +1 -0
  23. package/src/core/model/object/optional_equality.d.ts +10 -0
  24. package/src/core/model/object/optional_equality.d.ts.map +1 -0
  25. package/src/{shade/descriptor/util → core/model/object}/optional_equality.js +2 -2
  26. package/src/core/model/object/optional_hash.d.ts +9 -0
  27. package/src/core/model/object/optional_hash.d.ts.map +1 -0
  28. package/src/{shade/descriptor/util → core/model/object}/optional_hash.js +3 -3
  29. package/src/engine/asset/Asset.d.ts +1 -1
  30. package/src/engine/asset/Asset.d.ts.map +1 -1
  31. package/src/engine/asset/Asset.js +3 -1
  32. package/src/engine/asset/loaders/image/ImageDecoderWorker.js +12 -27
  33. package/src/engine/asset/loaders/image/prototypePNG.js +8 -7
  34. package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.d.ts.map +1 -1
  35. package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +9 -10
  36. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  37. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
  38. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +266 -0
  39. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -0
  40. package/src/engine/graphics/ecs/particles/ParticleEffect.js +439 -0
  41. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +58 -0
  42. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -0
  43. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +219 -0
  44. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +178 -25
  45. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  46. package/src/engine/graphics3/GPUParticleEmitterSystem.js +809 -310
  47. package/src/format/image/png/PNGReader.d.ts +7 -6
  48. package/src/format/image/png/PNGReader.d.ts.map +1 -1
  49. package/src/format/image/png/PNGReader.js +13 -12
  50. package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts +3 -2
  51. package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +1 -1
  52. package/src/format/image/png/chunk/png_chunk_decode_iTXt.js +5 -4
  53. package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts +3 -2
  54. package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts.map +1 -1
  55. package/src/format/image/png/chunk/png_chunk_decode_zTXt.js +5 -4
  56. package/src/format/image/png/png_inflate.d.ts +3 -3
  57. package/src/format/image/png/png_inflate.d.ts.map +1 -1
  58. package/src/format/image/png/png_inflate.js +29 -39
  59. package/src/format/texture/ktx2/ktx2_read.d.ts +4 -4
  60. package/src/format/texture/ktx2/ktx2_read.d.ts.map +1 -1
  61. package/src/format/texture/ktx2/ktx2_read.js +18 -21
  62. package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.js +1 -1
  63. package/src/shade/descriptor/binding/BindGroupLayoutEntry.js +3 -3
  64. package/src/shade/descriptor/pipeline/PipelineDescriptorBase.js +1 -1
  65. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +1 -1
  66. package/src/shade/descriptor/pipeline/render/ColorTargetState.js +3 -3
  67. package/src/shade/descriptor/pipeline/render/FragmentState.js +1 -1
  68. package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.js +3 -3
  69. package/src/shade/playground/particle_ecs/README.md +203 -0
  70. package/src/shade/playground/particle_ecs/bonfire_editor.d.ts +39 -0
  71. package/src/shade/playground/particle_ecs/bonfire_editor.d.ts.map +1 -0
  72. package/src/shade/playground/particle_ecs/bonfire_editor.js +315 -0
  73. package/src/shade/playground/particle_ecs/bonfire_effects.d.ts +145 -0
  74. package/src/shade/playground/particle_ecs/bonfire_effects.d.ts.map +1 -0
  75. package/src/shade/playground/particle_ecs/bonfire_effects.js +202 -0
  76. package/src/shade/playground/particle_ecs/bonfire_sprites.d.ts +23 -0
  77. package/src/shade/playground/particle_ecs/bonfire_sprites.d.ts.map +1 -0
  78. package/src/shade/playground/particle_ecs/bonfire_sprites.js +315 -0
  79. package/src/shade/playground/particle_ecs/bonfire_world.d.ts +86 -0
  80. package/src/shade/playground/particle_ecs/bonfire_world.d.ts.map +1 -0
  81. package/src/shade/playground/particle_ecs/bonfire_world.js +303 -0
  82. package/src/shade/playground/particle_ecs/effects/embers.json +1634 -0
  83. package/src/shade/playground/particle_ecs/effects/flame.json +1882 -0
  84. package/src/shade/playground/particle_ecs/effects/smoke.json +1860 -0
  85. package/src/shade/playground/particle_ecs/effects/soot.json +1606 -0
  86. package/src/shade/playground/particle_ecs/index.html +330 -0
  87. package/src/shade/playground/particle_ecs/main.d.ts +2 -0
  88. package/src/shade/playground/particle_ecs/main.d.ts.map +1 -0
  89. package/src/shade/playground/particle_ecs/main.js +566 -0
  90. package/src/shade/playground/particle_ecs/moonlit_environment.d.ts +16 -0
  91. package/src/shade/playground/particle_ecs/moonlit_environment.d.ts.map +1 -0
  92. package/src/shade/playground/particle_ecs/moonlit_environment.js +144 -0
  93. package/src/shade/playground/particle_editor/README.md +5 -4
  94. package/src/shade/playground/particle_system/particle_prototype.d.ts +7 -9
  95. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  96. package/src/shade/playground/particle_system/particle_prototype.js +7 -9
  97. package/src/shade/playground/profile_hotkey.d.ts +58 -0
  98. package/src/shade/playground/profile_hotkey.d.ts.map +1 -0
  99. package/src/shade/playground/profile_hotkey.js +325 -0
  100. package/src/shade/playground/ssr_motion/README.md +22 -0
  101. package/src/shade/playground/ssr_motion/index.html +18 -0
  102. package/src/shade/playground/ssr_motion/main.d.ts +2 -0
  103. package/src/shade/playground/ssr_motion/main.d.ts.map +1 -0
  104. package/src/shade/playground/ssr_motion/main.js +149 -0
  105. package/src/shade/playground/ssr_variance/README.md +105 -0
  106. package/src/shade/playground/ssr_variance/capture.d.ts +16 -0
  107. package/src/shade/playground/ssr_variance/capture.d.ts.map +1 -0
  108. package/src/shade/playground/ssr_variance/capture.js +96 -0
  109. package/src/shade/playground/ssr_variance/index.html +23 -0
  110. package/src/shade/playground/ssr_variance/main.d.ts +2 -0
  111. package/src/shade/playground/ssr_variance/main.d.ts.map +1 -0
  112. package/src/shade/playground/ssr_variance/main.js +246 -0
  113. package/src/shade/playground/ssr_variance/reference.d.ts +18 -0
  114. package/src/shade/playground/ssr_variance/reference.d.ts.map +1 -0
  115. package/src/shade/playground/ssr_variance/reference.js +78 -0
  116. package/src/shade/playground/ssr_variance/scene.d.ts +11 -0
  117. package/src/shade/playground/ssr_variance/scene.d.ts.map +1 -0
  118. package/src/shade/playground/ssr_variance/scene.js +61 -0
  119. package/src/shade/playground/ssr_variance/statistics.d.ts +44 -0
  120. package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -0
  121. package/src/shade/playground/ssr_variance/statistics.js +51 -0
  122. package/src/shade/renderer/geometry/Geometry.d.ts.map +1 -1
  123. package/src/shade/renderer/geometry/Geometry.js +4 -7
  124. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts.map +1 -1
  125. package/src/shade/renderer/loader/gltf/tiny-gltf.js +9 -3
  126. package/src/shade/renderer/loader/usd/usd_decode_image.d.ts +4 -4
  127. package/src/shade/renderer/loader/usd/usd_decode_image.d.ts.map +1 -1
  128. package/src/shade/renderer/loader/usd/usd_decode_image.js +4 -4
  129. package/src/shade/renderer/material/StandardShadeMaterial.js +2 -2
  130. package/src/shade/renderer/particles/DESIGN.md +745 -702
  131. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  132. package/src/shade/renderer/particles/GPUParticleSystem.js +3 -1
  133. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +1 -1
  134. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +1 -1
  135. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  136. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +9 -15
  137. package/src/shade/renderer/particles/graph/particle_group_library.d.ts.map +1 -1
  138. package/src/shade/renderer/particles/graph/particle_group_library.js +8 -3
  139. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +0 -2
  140. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  141. package/src/shade/renderer/particles/graph/particle_node_parameters.js +0 -9
  142. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  143. package/src/shade/renderer/particles/graph/particle_node_presentation.js +0 -10
  144. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +2 -8
  145. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -1
  146. package/src/shade/renderer/particles/graph/particle_ramp.js +2 -8
  147. package/src/shade/renderer/particles/graph/validate_particle_graph.js +0 -6
  148. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  149. package/src/shade/renderer/particles/graph_particles_avboit.js +13 -4
  150. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +1 -12
  151. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/isa/InstructionStream.js +1 -12
  153. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +54 -60
  154. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  155. package/src/shade/renderer/particles/isa/ParticleVMISA.js +9 -17
  156. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +0 -1
  157. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  158. package/src/shade/renderer/particles/isa/particle_assembly.js +2 -16
  159. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +1 -1
  160. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +1 -1
  161. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +0 -14
  162. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +3 -17
  163. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  164. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +15 -36
  165. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  166. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +1 -5
  167. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  168. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +1 -8
  169. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +2 -11
  170. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  171. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +2 -11
  172. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +11 -4
  173. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  174. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +431 -424
  175. package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.js +13 -0
  177. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts +3 -6
  178. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  179. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +49 -17
  180. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  181. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +0 -2
  182. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -1
  183. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +0 -2
  184. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  185. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +1 -5
  186. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -1
  187. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +0 -2
  188. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +1 -3
  189. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  190. package/src/shade/renderer/particles/vm/ParticleVMReference.js +4 -20
  191. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  192. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +2 -5
  193. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts.map +1 -1
  194. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js +0 -2
  195. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts.map +1 -1
  196. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js +0 -2
  197. package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
  198. package/src/shade/renderer/postprocess/ssr/SSR.js +2 -1
  199. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts.map +1 -1
  200. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js +20 -5
  201. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts.map +1 -1
  202. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js +19 -5
  203. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts +4 -0
  204. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -0
  205. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +137 -0
  206. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +0 -8
  207. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
  208. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +18 -114
  209. package/src/shade/renderer/scene/Mesh.js +1 -1
  210. package/src/shade/renderer/texture/ShadeTexture.js +1 -1
  211. package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts +2 -2
  212. package/src/shade/renderer/texture/source/texel_data_from_ktx2.d.ts.map +1 -1
  213. package/src/shade/renderer/texture/source/texel_data_from_ktx2.js +3 -3
  214. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts +0 -19
  215. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +0 -1
  216. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +0 -30
  217. package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.d.ts +0 -11
  218. package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.d.ts.map +0 -1
  219. package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.js +0 -13
  220. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts +0 -20
  221. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts.map +0 -1
  222. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.d.ts +0 -14
  223. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.d.ts.map +0 -1
  224. package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts +0 -50
  225. package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts.map +0 -1
  226. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts +0 -17
  227. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.d.ts.map +0 -1
  228. /package/src/{shade/descriptor/util → core/model/object}/optional_clone.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_particle_avboit_contribution.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,iDAFU,SAAS,CA0Dc;0BA1EP,oCAAoC"}
1
+ {"version":3,"file":"chunk_particle_avboit_contribution.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,iDAFU,SAAS,CAuEc;0BAvFP,oCAAoC"}
@@ -24,6 +24,19 @@ struct ParticleAVBOITContribution {
24
24
  emission : vec4<f32>,
25
25
  }
26
26
 
27
+ // Black covering fragments still contribute extinction; zero-alpha premultiplied RGB still emits.
28
+ fn particle_avboit_is_empty(color : vec4<f32>, blend : u32) -> bool {
29
+ return all(particle_premultiply(color, blend) == vec4<f32>(0.0));
30
+ }
31
+
32
+ // The atlas is unorm, so non-negative straight alpha cannot produce emission. Signed alpha and
33
+ // premultiplied sprites keep all four outputs: either can emit without positive coverage.
34
+ fn particle_avboit_draw_blend(color : vec4<f32>, blend : u32) -> u32 {
35
+ if (blend == PARTICLE_BLEND_ADDITIVE) { return PARTICLE_BLEND_ADDITIVE; }
36
+ if (blend == PARTICLE_BLEND_ALPHA && color.a >= 0.0) { return PARTICLE_BLEND_ALPHA; }
37
+ return PARTICLE_BLEND_PREMULTIPLIED;
38
+ }
39
+
27
40
  fn particle_avboit_contribution(
28
41
  shaded : vec4<f32>,
29
42
  blend : u32,
@@ -1,9 +1,6 @@
1
- /**
2
- * The draw pipeline: the four additive accumulators, reverse-Z depth test against the scene, no
3
- * depth write.
4
- * @type {RenderPipelineDescriptor}
5
- */
6
- export const PARTICLE_AVBOIT_DRAW_PIPELINE: RenderPipelineDescriptor;
1
+ export const PARTICLE_AVBOIT_DRAW_ALPHA_PIPELINE: RenderPipelineDescriptor;
2
+ export const PARTICLE_AVBOIT_DRAW_ADDITIVE_PIPELINE: RenderPipelineDescriptor;
3
+ export const PARTICLE_AVBOIT_DRAW_GENERAL_PIPELINE: RenderPipelineDescriptor;
7
4
  /** The draw shader's resource set, for building its bind group. */
8
5
  export const PARTICLE_AVBOIT_DRAW_RESOURCES: ShaderResourceSetDescriptor;
9
6
  /** The assembled shader, for the validity tier. */
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_avboit_draw.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js"],"names":[],"mappings":"AAkIA;;;;GAIG;AACH,4CAFU,wBAAwB,CAa/B;AAEH,mEAAmE;AACnE,yEAAwD;AAExD,mDAAmD;AACnD,2DAAsD;yCAxJb,iEAAiE;4CAW9D,sDAAsD;iCAFjE,kCAAkC"}
1
+ {"version":3,"file":"shader_particle_avboit_draw.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js"],"names":[],"mappings":"AAgLA,2EAAsI;AACtI,8EAA2I;AAC3I,6EAA8I;AAE9I,mEAAmE;AACnE,yEAAwD;AAExD,mDAAmD;AACnD,2DAAsD;yCAxLb,iEAAiE;4CAW9D,sDAAsD;iCAFjE,kCAAkC"}
@@ -77,9 +77,28 @@ struct ParticleAVBOITDrawOutput {
77
77
  @location(3) emission : vec4<f32>,
78
78
  }
79
79
 
80
+ // Each draw uses the same GPU-owned alive list. Clip the other modes before rasterization.
81
+ fn particle_avboit_vertex(vi : u32, ii : u32, blend : u32) -> ParticleVertexOut {
82
+ var out = particle_billboard_vertex(vi, ii);
83
+ if (particle_avboit_draw_blend(out.color, out.blend) != blend) {
84
+ out.clip = vec4<f32>(2.0, 2.0, 2.0, 1.0);
85
+ }
86
+ return out;
87
+ }
88
+
80
89
  @vertex
81
- fn vs_main(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
82
- return particle_billboard_vertex(vi, ii);
90
+ fn vs_alpha(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
91
+ return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_ALPHA);
92
+ }
93
+
94
+ @vertex
95
+ fn vs_additive(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
96
+ return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_ADDITIVE);
97
+ }
98
+
99
+ @vertex
100
+ fn vs_general(@builtin(vertex_index) vi : u32, @builtin(instance_index) ii : u32) -> ParticleVertexOut {
101
+ return particle_avboit_vertex(vi, ii, PARTICLE_BLEND_PREMULTIPLIED);
83
102
  }
84
103
 
85
104
  @fragment
@@ -104,6 +123,10 @@ fn fs_main(in : ParticleVertexOut) -> ParticleAVBOITDrawOutput {
104
123
  color = particle_apply_lighting(color, in.world_position, normalize(in.normal));
105
124
  }
106
125
 
126
+ if (particle_avboit_is_empty(color, in.blend)) {
127
+ discard;
128
+ }
129
+
107
130
  let volumetrics = sample_volumetrics(in.view_depth, screen_uv, in.clip.xy);
108
131
 
109
132
  let contribution = particle_avboit_contribution(color, in.blend, transmittance, volumetrics);
@@ -129,22 +152,31 @@ fn fs_main(in : ParticleVertexOut) -> ParticleAVBOITDrawOutput {
129
152
  const descriptor = ShaderDescriptor.from({ label: "Particle AVBOIT Draw", body, resources });
130
153
 
131
154
  /**
132
- * The draw pipeline: the four additive accumulators, reverse-Z depth test against the scene, no
133
- * depth write.
134
- * @type {RenderPipelineDescriptor}
155
+ * The variants share WGSL, bindings and attachments; only the vertex entry point and target writes
156
+ * differ. Disabling unused targets avoids blending zeros over every billboard pixel.
157
+ * @param {string} label
158
+ * @param {string} entryPoint
159
+ * @param {number[]} writeMasks
160
+ * @returns {RenderPipelineDescriptor}
135
161
  */
136
- export const PARTICLE_AVBOIT_DRAW_PIPELINE = RenderPipelineDescriptor.from({
137
- label: "Particle AVBOIT Draw",
138
- layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
139
- vertex: { module: { code: descriptor.source }, entryPoint: "vs_main" },
140
- fragment: {
141
- module: { code: descriptor.source },
142
- entryPoint: "fs_main",
143
- targets: AVBOIT_DRAW_TARGETS,
144
- },
145
- depthStencil: DepthStencilState.from({ format: "depth32float", depthWriteEnabled: false, depthCompare: "greater" }),
146
- primitive: { topology: "triangle-list", cullMode: "none" },
147
- });
162
+ function create_draw_pipeline(label, entryPoint, writeMasks) {
163
+ return RenderPipelineDescriptor.from({
164
+ label,
165
+ layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
166
+ vertex: { module: { code: descriptor.source }, entryPoint },
167
+ fragment: {
168
+ module: { code: descriptor.source },
169
+ entryPoint: "fs_main",
170
+ targets: AVBOIT_DRAW_TARGETS.map((target, i) => ({ ...target, writeMask: writeMasks[i] })),
171
+ },
172
+ depthStencil: DepthStencilState.from({ format: "depth32float", depthWriteEnabled: false, depthCompare: "greater" }),
173
+ primitive: { topology: "triangle-list", cullMode: "none" },
174
+ });
175
+ }
176
+
177
+ export const PARTICLE_AVBOIT_DRAW_ALPHA_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw Alpha", "vs_alpha", [0xF, 0xF, 0xF, 0]);
178
+ export const PARTICLE_AVBOIT_DRAW_ADDITIVE_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw Additive", "vs_additive", [0, 0, 0, 0xF]);
179
+ export const PARTICLE_AVBOIT_DRAW_GENERAL_PIPELINE = create_draw_pipeline("Particle AVBOIT Draw General", "vs_general", [0xF, 0xF, 0xF, 0xF]);
148
180
 
149
181
  /** The draw shader's resource set, for building its bind group. */
150
182
  export const PARTICLE_AVBOIT_DRAW_RESOURCES = resources;
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_emit.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,kDAA8E;AAE9E;;;;;;;;GAQG;AACH,4BAFU,YAAY,CAOK;AAqD3B,iDAIG;6BA1G0B,mCAAmC;8BAGlC,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_emit.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,kDAA8E;AAE9E;;;;;;;;GAQG;AACH,4BAFU,YAAY,CAOK;AAoD3B,iDAIG;6BAxG0B,mCAAmC;8BAGlC,+BAA+B"}
@@ -8,7 +8,6 @@ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
8
8
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
9
9
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
10
10
  import { chunk_particle_vm_registers_fast } from "../vm/chunk_particle_vm_registers_fast.js";
11
- import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
12
11
  import { chunk_particle_emit_step } from "./chunk_particle_emit_step.js";
13
12
 
14
13
  /**
@@ -99,7 +98,6 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
99
98
  `, [
100
99
  chunk_particle_emit_step,
101
100
  chunk_particle_vm_registers_fast,
102
- chunk_particle_curve_disabled,
103
101
  ]);
104
102
 
105
103
  export const shader_particle_emit = ComputeShader.from({
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_emit_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit_wide.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;GAIG;AACH,iDAFU,MAAM,CAGiD;AAiEjE,sDAIG;8BA9G2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_emit_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_emit_wide.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;GAIG;AACH,iDAFU,MAAM,CAGiD;AAgEjE,sDAIG;8BA5G2B,+BAA+B"}
@@ -7,7 +7,6 @@ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourc
7
7
  import { PARTICLE_VM_WIDE_LAUNCH_LANES } from "../ParticleConstants.js";
8
8
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
9
9
  import { chunk_particle_vm_registers_wide } from "../vm/chunk_particle_vm_registers_wide.js";
10
- import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
11
10
  import { chunk_particle_emit_step } from "./chunk_particle_emit_step.js";
12
11
  import { EMIT_SETTINGS, PARTICLE_EMIT_WORKGROUP_SIZE } from "./shader_particle_emit.js";
13
12
 
@@ -104,7 +103,6 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
104
103
  `, [
105
104
  chunk_particle_emit_step,
106
105
  chunk_particle_vm_registers_wide,
107
- chunk_particle_curve_disabled,
108
106
  ]);
109
107
 
110
108
  export const shader_particle_emit_wide = ComputeShader.from({
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":";AA0DA;;;;;GAKG;AACH,gCAFU,YAAY,CAMS;AAuD/B,qDAIG;iDAxH8C,yBAAyB;6BAJ7C,mCAAmC;8BAClC,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_simulate.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate.js"],"names":[],"mappings":";AAuDA;;;;;GAKG;AACH,gCAFU,YAAY,CAMS;AAsD/B,qDAIG;iDApH8C,yBAAyB;6BAJ7C,mCAAmC;8BAClC,+BAA+B"}
@@ -8,7 +8,6 @@ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourc
8
8
  import { PARTICLE_SIMULATE_WORKGROUP_SIZE } from "../ParticleConstants.js";
9
9
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
10
10
  import { chunk_particle_vm_registers_fast } from "../vm/chunk_particle_vm_registers_fast.js";
11
- import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
12
11
  import { chunk_particle_simulate_step } from "./chunk_particle_simulate_step.js";
13
12
 
14
13
  /**
@@ -47,9 +46,7 @@ import { chunk_particle_simulate_step } from "./chunk_particle_simulate_step.js"
47
46
  * frame from that same value, so thread count and bound agree by construction — and, because the
48
47
  * padded length is a whole number of workgroups, agree exactly.
49
48
  *
50
- * All structured reads go through `array<u32>` for emulator-testability. Curve sampling uses the
51
- * pluggable `particle_vm_sample_curve` — here the no-op provider; the feature swaps in the
52
- * animation-database-backed one.
49
+ * All structured reads go through `array<u32>` for emulator-testability.
53
50
  *
54
51
  * @type {ComputeShader}
55
52
  */
@@ -116,7 +113,6 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
116
113
  `, [
117
114
  chunk_particle_simulate_step,
118
115
  chunk_particle_vm_registers_fast,
119
- chunk_particle_curve_disabled,
120
116
  ]);
121
117
 
122
118
  body.addExtension(WebGPUExtensionType.Subgroups);
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_simulate_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;GAGG;AACH,qDAFU,MAAM,CAGqD;AA8DrE,0DAIG;8BAvH2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_simulate_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;GAGG;AACH,qDAFU,MAAM,CAGqD;AA6DrE,0DAIG;8BArH2B,+BAA+B"}
@@ -7,7 +7,6 @@ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourc
7
7
  import { PARTICLE_SIMULATE_WORKGROUP_SIZE, PARTICLE_VM_WIDE_LAUNCH_LANES } from "../ParticleConstants.js";
8
8
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
9
9
  import { chunk_particle_vm_registers_wide } from "../vm/chunk_particle_vm_registers_wide.js";
10
- import { chunk_particle_curve_disabled } from "./chunk_particle_curve_disabled.js";
11
10
  import { chunk_particle_simulate_step } from "./chunk_particle_simulate_step.js";
12
11
  import { SIMULATE_SETTINGS } from "./shader_particle_simulate.js";
13
12
 
@@ -111,7 +110,6 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
111
110
  `, [
112
111
  chunk_particle_simulate_step,
113
112
  chunk_particle_vm_registers_wide,
114
- chunk_particle_curve_disabled,
115
113
  ]);
116
114
 
117
115
  body.addExtension(WebGPUExtensionType.Subgroups);
@@ -36,17 +36,15 @@ export function u32_to_unit_f32(u: number): number;
36
36
  * @param {Uint32Array} params.record particle record words (mutated in place); attributes are f32 bits
37
37
  * @param {number[][]} [params.builtins] builtin values indexed by {@link VM_BUILTIN} id, each a 4-array
38
38
  * @param {number} [params.rng_state] initial RNG state (u32)
39
- * @param {(handle: number, t: number) => number} [params.sampleCurve] curve evaluator for the CURVE op
40
39
  * @returns {{ killed: boolean, rng_state: number }}
41
40
  */
42
- export function execute_particle_vm({ words, constants, register_count, record, builtins, rng_state, sampleCurve, }: {
41
+ export function execute_particle_vm({ words, constants, register_count, record, builtins, rng_state, }: {
43
42
  words: Uint32Array;
44
43
  constants: Float32Array;
45
44
  register_count: number;
46
45
  record: Uint32Array;
47
46
  builtins?: number[][];
48
47
  rng_state?: number;
49
- sampleCurve?: (handle: number, t: number) => number;
50
48
  }): {
51
49
  killed: boolean;
52
50
  rng_state: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleVMReference.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/vm/ParticleVMReference.js"],"names":[],"mappings":"AA0BA;;;;;;;GAOG;AACH,gCAHW,MAAM;WACK,MAAM;WAAS,MAAM;EAW1C;AAED;;;;;GAKG;AACH,mCAHW,MAAM,GACJ,MAAM,CAIlB;AAqED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;WATW,WAAW;eACX,YAAY;oBACZ,MAAM;YACN,WAAW;eACX,MAAM,EAAE,EAAE;gBACV,MAAM;2BACG,MAAM,KAAK,MAAM,KAAK,MAAM;;YACzB,OAAO;eAAa,MAAM;EA+RhD"}
1
+ {"version":3,"file":"ParticleVMReference.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/vm/ParticleVMReference.js"],"names":[],"mappings":"AA0BA;;;;;;;GAOG;AACH,gCAHW,MAAM;WACK,MAAM;WAAS,MAAM;EAW1C;AAED;;;;;GAKG;AACH,mCAHW,MAAM,GACJ,MAAM,CAIlB;AA8DD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAR+B,KAAK,EAAzB,WAAW;IACU,SAAS,EAA9B,YAAY;IACG,cAAc,EAA7B,MAAM;IACc,MAAM,EAA1B,WAAW;IACS,QAAQ,GAA5B,MAAM,EAAE,EAAE;IACM,SAAS,GAAzB,MAAM;;YACM,OAAO;eAAa,MAAM;EAuRhD"}
@@ -72,17 +72,10 @@ const OP_WIDTH = new Int8Array(OP_COUNT);
72
72
  /** The lanes the opcode always writes, or `-1` for as many as it operates on. @type {Int8Array} */
73
73
  const OP_DEST = new Int8Array(OP_COUNT);
74
74
 
75
- /** Bit `n` set where source slot `n` is read one lane whatever the width. @type {Uint8Array} */
76
- const OP_SCALAR = new Uint8Array(OP_COUNT);
77
-
78
75
  for (const [op, meta] of VM_ISA) {
79
76
  OP_DEFINED[op] = 1;
80
77
  OP_WIDTH[op] = meta.width === VM_WIDTH.VARIABLE ? -1 : vm_operation_width(op, 0);
81
78
  OP_DEST[op] = meta.dest === VM_DEST.WIDTH ? -1 : vm_dest_width(op, 0);
82
-
83
- for (const slot of meta.scalar_operands) {
84
- OP_SCALAR[op] |= 1 << slot;
85
- }
86
79
  }
87
80
 
88
81
  // --- module-local copies of what the loop reads per instruction ----------------------------------
@@ -92,7 +85,7 @@ for (const [op, meta] of VM_ISA) {
92
85
  // constants to the JIT, and the opcode switch can be a jump table.
93
86
 
94
87
  const {
95
- ABS, ACOS, ADD, ASIN, ATAN2, CLAMP, CMP_EQ, CMP_GE, CMP_GT, CMP_LE, CMP_LT, COS, CROSS, CURVE,
88
+ ABS, ACOS, ADD, ASIN, ATAN2, CLAMP, CMP_EQ, CMP_GE, CMP_GT, CMP_LE, CMP_LT, COS, CROSS,
96
89
  DISTANCE, DIV, DOT, EXP, FLOOR, FRACT, HALT, KILL, LENGTH, LOAD_ATTR, LOAD_BUILTIN, LOAD_CONST,
97
90
  LOG, MAD, MAX, MIN, MIX, MOV, MUL, NEG, NOP, NORMALIZE, POW, RANDOM, RSQRT, SELECT, SIN,
98
91
  SMOOTHSTEP, SQRT, STEP, STORE_ATTR, SUB, TAN,
@@ -139,7 +132,6 @@ const LITERAL_U32 = new Uint32Array(LITERAL_F32.buffer);
139
132
  * @param {Uint32Array} params.record particle record words (mutated in place); attributes are f32 bits
140
133
  * @param {number[][]} [params.builtins] builtin values indexed by {@link VM_BUILTIN} id, each a 4-array
141
134
  * @param {number} [params.rng_state] initial RNG state (u32)
142
- * @param {(handle: number, t: number) => number} [params.sampleCurve] curve evaluator for the CURVE op
143
135
  * @returns {{ killed: boolean, rng_state: number }}
144
136
  */
145
137
  export function execute_particle_vm({
@@ -149,7 +141,6 @@ export function execute_particle_vm({
149
141
  record,
150
142
  builtins = [],
151
143
  rng_state = 0,
152
- sampleCurve = () => 0,
153
144
  }) {
154
145
  // Register file: one f32 per slot. A value of width w occupies w consecutive slots.
155
146
  const reg = new Float32Array(register_count);
@@ -217,14 +208,13 @@ export function execute_particle_vm({
217
208
  const w = fixed_width < 0 ? (word0 >>> WIDTH_SHIFT) & WIDTH_MASK : fixed_width;
218
209
  const dst = (word0 >>> DST_SHIFT) & DST_MASK;
219
210
  const kinds = word0 >>> KIND_SHIFT;
220
- const scalar = OP_SCALAR[op];
221
211
  const s0 = words[base + 1];
222
212
  const s1 = words[base + 2];
223
213
  const s2 = words[base + 3];
224
214
 
225
- gather(a, kinds & KIND_MASK, s0, (scalar & 1) !== 0 ? 1 : w);
226
- gather(b, (kinds >>> KIND_BITS) & KIND_MASK, s1, (scalar & 2) !== 0 ? 1 : w);
227
- gather(c, (kinds >>> (2 * KIND_BITS)) & KIND_MASK, s2, (scalar & 4) !== 0 ? 1 : w);
215
+ gather(a, kinds & KIND_MASK, s0, w);
216
+ gather(b, (kinds >>> KIND_BITS) & KIND_MASK, s1, w);
217
+ gather(c, (kinds >>> (2 * KIND_BITS)) & KIND_MASK, s2, w);
228
218
 
229
219
  switch (op) {
230
220
  case HALT:
@@ -408,12 +398,6 @@ export function execute_particle_vm({
408
398
  for (let i = 0; i < w; i++) d[i] = draw_unit();
409
399
  break;
410
400
 
411
- case CURVE: {
412
- const v = sampleCurve(s0, b[0]);
413
- for (let i = 0; i < w; i++) d[i] = v;
414
- break;
415
- }
416
-
417
401
  default:
418
402
  throw new Error(`ParticleVMReference: unhandled opcode ${op} at pc ${pc}`);
419
403
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_particle_vm.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/vm/chunk_particle_vm.js"],"names":[],"mappings":"AA6UA;;;GAGG;AACH,gCAFU,SAAS,CAEmG;0BAhV5F,oCAAoC"}
1
+ {"version":3,"file":"chunk_particle_vm.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/vm/chunk_particle_vm.js"],"names":[],"mappings":"AA0UA;;;GAGG;AACH,gCAFU,SAAS,CAEmG;0BA7U5F,oCAAoC"}
@@ -66,8 +66,8 @@ import { PARTICLE_VM_CONTEXT_STRUCT } from "./PARTICLE_VM_CONTEXT_STRUCT.js";
66
66
  * VGPRs on RDNA2 and held the shader to 10 waves against a cap of 16.
67
67
  *
68
68
  * Where those slots LIVE is not this chunk's business. The interpreter reads and writes them through
69
- * `vm_reg_read` and `vm_reg_write`, which a backing chunk supplies — the same external-symbol seam
70
- * `particle_vm_sample_curve` uses. There are two backings and they are the two interpreters:
69
+ * `vm_reg_read` and `vm_reg_write`, which a backing chunk supplies. There are two backings and they
70
+ * are the two interpreters:
71
71
  *
72
72
  * - {@link ./chunk_particle_vm_registers_fast.js} — a `var<private>` array of
73
73
  * {@link ../ParticleConstants.js PARTICLE_VM_FAST_REGISTER_SLOTS}. Dynamically indexed, so it
@@ -128,8 +128,6 @@ import { PARTICLE_VM_CONTEXT_STRUCT } from "./PARTICLE_VM_CONTEXT_STRUCT.js";
128
128
  * driver then fetches the instruction words through the scalar unit, branches the switch on a
129
129
  * scalar and indexes `vm_reg` through M0 without the per-lane waterfall. Emit cannot: its waves
130
130
  * span emitters.
131
- * - The `CURVE` opcode calls the external symbol `particle_vm_sample_curve(handle: u32, t: f32) ->
132
- * f32`. The enclosing shader must define it (production: animation-curve backed; tests: a stub).
133
131
  */
134
132
 
135
133
  const source = /* language=wgsl */ `
@@ -318,7 +316,6 @@ fn particle_vm_execute(
318
316
  if (w > 2u) { d.z = random(); }
319
317
  if (w > 3u) { d.w = random(); }
320
318
  }
321
- case ${VM_OP.CURVE}u: { d = vec4<f32>(particle_vm_sample_curve(s0, b.x)); }
322
319
 
323
320
  default: { lanes = 0u; }
324
321
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_warmup_advance.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,sCAFU,YAAY,CAMc;AAgBpC;;;;GAIG;AACH,kCAFU,MAAM,CA6Bd;AAEF,2DAeG;;6BAvG0B,mCAAmC;8BAClC,+BAA+B;gDAQb,6BAA6B"}
1
+ {"version":3,"file":"shader_particle_warmup_advance.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,sCAFU,YAAY,CAMc;AAgBpC;;;;GAIG;AACH,kCAFU,MAAM,CA6Bd;AAEF,2DAcG;;6BArG0B,mCAAmC;8BAClC,+BAA+B;gDAOb,6BAA6B"}
@@ -6,7 +6,6 @@ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
6
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
7
  import { PARTICLE_WARMUP_LAUNCH_LANES, PARTICLE_WARMUP_WORKGROUP_SIZE } from "../ParticleConstants.js";
8
8
  import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
9
- import { chunk_particle_curve_disabled } from "../shaders/chunk_particle_curve_disabled.js";
10
9
  import { chunk_particle_vm_registers_fast } from "../vm/chunk_particle_vm_registers_fast.js";
11
10
  import { chunk_particle_warmup_step } from "./chunk_particle_warmup_step.js";
12
11
  import { PARTICLE_WARMUP_WORKGROUP_COUNT } from "./shader_particle_warmup.js";
@@ -101,7 +100,6 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
101
100
  `, [
102
101
  chunk_particle_warmup_step,
103
102
  chunk_particle_vm_registers_fast,
104
- chunk_particle_curve_disabled,
105
103
  ]),
106
104
  });
107
105
 
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_warmup_advance_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js"],"names":[],"mappings":"AAkDA,gEAmBG;8BAlE2B,+BAA+B"}
1
+ {"version":3,"file":"shader_particle_warmup_advance_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js"],"names":[],"mappings":"AAiDA,gEAkBG;8BAhE2B,+BAA+B"}
@@ -9,7 +9,6 @@ import {
9
9
  PARTICLE_WARMUP_LAUNCH_LANES,
10
10
  PARTICLE_WARMUP_WORKGROUP_SIZE,
11
11
  } from "../ParticleConstants.js";
12
- import { chunk_particle_curve_disabled } from "../shaders/chunk_particle_curve_disabled.js";
13
12
  import { chunk_particle_vm_registers_wide } from "../vm/chunk_particle_vm_registers_wide.js";
14
13
  import { chunk_particle_warmup_step } from "./chunk_particle_warmup_step.js";
15
14
  import { WARMUP_ADVANCE_BODY, WARMUP_ADVANCE_SETTINGS } from "./shader_particle_warmup_advance.js";
@@ -65,6 +64,5 @@ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
65
64
  `, [
66
65
  chunk_particle_warmup_step,
67
66
  chunk_particle_vm_registers_wide,
68
- chunk_particle_curve_disabled,
69
67
  ]),
70
68
  });
@@ -1 +1 @@
1
- {"version":3,"file":"SSR.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/ssr/SSR.js"],"names":[],"mappings":"AAiBA;IAyDI;;;OAGG;IACH,sBAFW,OAAO,0BAA0B,EAAE,eAAe,EAiB5D;IA1DD,oBAAgB;IAMhB,4CAOC;IATD,iGAAiG;IACjG,yCAA2E;IA0B3E,gCAMC;IAZD;;;;OAIG;IACH,6BAAmD;IAbnD,mCAMC;IARD,qCAAqC;IACrC,gCAA2D;IA4C3D;;;;OAIG;IACH,UAHW,MAAM,KACN,MAAM,QAUhB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH;QAtBsG,KAAK,EAAhG,OAAO,8DAA8D,EAAE,UAAU;QACjE,WAAW,EAA3B,MAAM;QACW,oBAAoB,GAArC,MAAM;QACU,SAAS,EAAzB,MAAM;QACU,iBAAiB,EAAjC,MAAM;QACU,YAAY,EAA5B,MAAM;QACU,SAAS,EAAzB,MAAM;QACU,YAAY,EAA5B,MAAM;QACU,cAAc,EAA9B,MAAM;QACU,eAAe,EAA/B,MAAM;QACW,iBAAiB,GAAlC,MAAM;QACqB,UAAU,EAArC,UAAU,MAAM,CAAC;QACD,cAAc,EAA9B,MAAM;QACU,eAAe,EAA/B,MAAM;QAC8B,sBAAsB,GAA1D,yBAAyB;QAC6D,MAAM,GAA5F,OAAO,oDAAoD,EAAE,cAAc;QACkB,GAAG,GAAhG,OAAO,sDAAsD,EAAE,mBAAmB;QAClB,QAAQ,GAAxE,OAAO,8BAA8B,EAAE,cAAc;QACzB,MAAM,GAAlC,UAAU,MAAM,CAAC;QACA,GAAG,GAApB,MAAM;;eACG,MAAM;eAAQ,MAAM;qBAAc,MAAM;kBAAW,MAAM;oBAAa,MAAM;MAkQ/F;;CACJ;0CAxYyC,oCAAoC"}
1
+ {"version":3,"file":"SSR.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/ssr/SSR.js"],"names":[],"mappings":"AAiBA;IAyDI;;;OAGG;IACH,sBAFW,OAAO,0BAA0B,EAAE,eAAe,EAkB5D;IA3DD,oBAAgB;IAMhB,4CAOC;IATD,iGAAiG;IACjG,yCAA2E;IA0B3E,gCAMC;IAZD;;;;OAIG;IACH,6BAAmD;IAbnD,mCAMC;IARD,qCAAqC;IACrC,gCAA2D;IA6C3D;;;;OAIG;IACH,UAHW,MAAM,KACN,MAAM,QAUhB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH;QAtBsG,KAAK,EAAhG,OAAO,8DAA8D,EAAE,UAAU;QACjE,WAAW,EAA3B,MAAM;QACW,oBAAoB,GAArC,MAAM;QACU,SAAS,EAAzB,MAAM;QACU,iBAAiB,EAAjC,MAAM;QACU,YAAY,EAA5B,MAAM;QACU,SAAS,EAAzB,MAAM;QACU,YAAY,EAA5B,MAAM;QACU,cAAc,EAA9B,MAAM;QACU,eAAe,EAA/B,MAAM;QACW,iBAAiB,GAAlC,MAAM;QACqB,UAAU,EAArC,UAAU,MAAM,CAAC;QACD,cAAc,EAA9B,MAAM;QACU,eAAe,EAA/B,MAAM;QAC8B,sBAAsB,GAA1D,yBAAyB;QAC6D,MAAM,GAA5F,OAAO,oDAAoD,EAAE,cAAc;QACkB,GAAG,GAAhG,OAAO,sDAAsD,EAAE,mBAAmB;QAClB,QAAQ,GAAxE,OAAO,8BAA8B,EAAE,cAAc;QACzB,MAAM,GAAlC,UAAU,MAAM,CAAC;QACA,GAAG,GAApB,MAAM;;eACG,MAAM;eAAQ,MAAM;qBAAc,MAAM;kBAAW,MAAM;oBAAa,MAAM;MAkQ/F;;CACJ;0CAzYyC,oCAAoC"}
@@ -80,7 +80,8 @@ export class SSR {
80
80
 
81
81
  for (const [history, format, label] of [
82
82
  [this.#history, "rgba16float", "radiance"],
83
- [this.#metadata, "rg32float", "metadata"],
83
+ // xy: reflected distance/support, z: history age, w: short-term luminance.
84
+ [this.#metadata, "rgba32float", "metadata"],
84
85
  [this.#geometry, "rgba16float", "geometry"],
85
86
  ]) {
86
87
  for (let i = 0; i < 2; i++) {
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_ssr_reprojection.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js"],"names":[],"mappings":"AAIA,+CAyBuC;0BA7Bb,uCAAuC"}
1
+ {"version":3,"file":"chunk_ssr_reprojection.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js"],"names":[],"mappings":"AAIA,+CAwCuC;0BA5Cb,uCAAuC"}
@@ -21,10 +21,25 @@ fn ssr_surface_history_uv(pixel: vec2f, velocity: vec2f, jitter_delta: vec2f, si
21
21
  return (pixel - velocity + jitter_delta) / size;
22
22
  }
23
23
 
24
- // Apply confidence LAST. Variance and clamp heuristics cannot resurrect rejected history.
25
- fn ssr_history_weight(current_variance: f32, history_variance: f32, current_blend: f32, confidence: f32) -> f32 {
26
- let c = current_blend / (1.0 + max(current_variance, 0.0));
27
- let h = (1.0 - current_blend) / (1.0 + max(history_variance, 0.0));
28
- return h / max(c + h, 1e-20) * saturate(confidence);
24
+ // Surface motion does not include reflection parallax. Bound the expected lag of
25
+ // an exponential history to one internal pixel when this correspondence is used.
26
+ // Rotation and raster jitter cancel between the two projections; translation does not.
27
+ fn ssr_surface_parallax_confidence(camera_position: vec3f, position: vec3f, distance: f32,
28
+ previous_view_projection: mat4x4f, size: vec2f) -> f32 {
29
+ let surface_uv = ssr_history_uv(position, previous_view_projection);
30
+ var reflected_uv: vec2f;
31
+ if (is_finite(distance) && distance > 0.0) {
32
+ reflected_uv = ssr_history_uv(ssr_virtual_position(camera_position,position,distance),previous_view_projection);
33
+ } else {
34
+ // A miss has no finite reflected depth. Infinity bounds the parallax of
35
+ // a stale finite reflection that can still be present in this history.
36
+ let clip = previous_view_projection * vec4f(position-camera_position,0.0);
37
+ if (!is_finite(clip.w) || clip.w <= 1e-6) { return 0.0; }
38
+ reflected_uv = ndc_to_uv(clip.xy/clip.w);
39
+ }
40
+ let displacement = length((reflected_uv-surface_uv)*size);
41
+ if (!is_finite(displacement)) { return 0.0; }
42
+ return 1.0/(1.0+displacement);
29
43
  }
44
+
30
45
  `, [chunk_ndc_to_uv, chunk_is_finite]);
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_ssr_sample_history.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js"],"names":[],"mappings":"AAUA,8FAA8F;AAC9F,iDA0DkD;0BArExB,uCAAuC"}
1
+ {"version":3,"file":"chunk_ssr_sample_history.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js"],"names":[],"mappings":"AAUA,8FAA8F;AAC9F,iDAwEkD;0BAnFxB,uCAAuC"}
@@ -13,6 +13,8 @@ export const chunk_ssr_sample_history = CodeChunk.from(/* language=WGSL */ `
13
13
  struct SSRHistorySample {
14
14
  radiance: vec4f,
15
15
  confidence: f32,
16
+ age: f32,
17
+ short_luma: f32,
16
18
  }
17
19
 
18
20
  fn ssr_sample_history(
@@ -43,10 +45,12 @@ fn ssr_sample_history(
43
45
  texel_coordinate_to_uv(vec2f(coord), size), depth, camera_previous.view_projection_matrix_inverse);
44
46
  let plane_distance = abs(point_distance_above_plane(previous_position, plane));
45
47
  if (!is_finite(plane_distance) || plane_distance > plane_tolerance) { continue; }
46
- let previous_metadata = textureLoad(tHistoryMetadata, coord, 0).rg;
48
+ let previous_metadata = textureLoad(tHistoryMetadata, coord, 0);
47
49
  if (!is_finite(previous_metadata.x) || !is_finite(previous_metadata.y)) { continue; }
48
- // A source/support transition must not preserve the previous, unrelated reflection.
49
- if (abs(previous_metadata.y - metadata.y) > 0.25) { continue; }
50
+ if (!is_finite(previous_metadata.z) || !is_finite(previous_metadata.w)) { continue; }
51
+ // On a rough reflector, hit/miss support is itself a stochastic sample. It is
52
+ // not evidence that the receiving surface or the reflected scene has moved.
53
+ if (roughness <= 0.2 && abs(previous_metadata.y - metadata.y) > 0.25) { continue; }
50
54
  var support = 1.0;
51
55
  if (virtual_candidate) {
52
56
  if (previous_metadata.y < 0.5 || previous_metadata.x <= 0.0) { continue; }
@@ -59,10 +63,20 @@ fn ssr_sample_history(
59
63
  let radiance = textureLoad(tHistory, coord, 0);
60
64
  if (!is_finite(radiance.x) || !is_finite(radiance.y) || !is_finite(radiance.z) || !is_finite(radiance.w)) { continue; }
61
65
  let w = weights[i] * support;
62
- result.radiance += max(radiance, vec4f(0.0)) * w;
66
+ let age = clamp(previous_metadata.z, 1.0, 128.0);
67
+ // Reconstruct each tap's distribution variance BEFORE interpolation.
68
+ // E[variance/age] * E[age] can wildly inflate noise at an age boundary.
69
+ result.radiance += max(radiance, vec4f(0.0)) * vec4f(w,w,w,w*age);
70
+ result.age += age * w;
71
+ result.short_luma += previous_metadata.w * w;
63
72
  result.confidence += w;
64
73
  }
65
- if (result.confidence > 1e-6) { result.radiance /= result.confidence; }
74
+ if (result.confidence > 1e-6) {
75
+ result.radiance /= result.confidence;
76
+ result.age /= result.confidence;
77
+ result.radiance.w /= result.age;
78
+ result.short_luma /= result.confidence;
79
+ }
66
80
  return result;
67
81
  }
68
82
  `, [chunk_project_position_from_depth, chunk_is_background, chunk_plane_from_normal_and_point,
@@ -0,0 +1,4 @@
1
+ /** Linear radiance accumulation. Spatial contrast and single stochastic hits are not motion. */
2
+ export const chunk_ssr_temporal_accumulate: CodeChunk;
3
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
4
+ //# sourceMappingURL=chunk_ssr_temporal_accumulate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_ssr_temporal_accumulate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js"],"names":[],"mappings":"AAUA,gGAAgG;AAChG,sDA6HuH;0BAxI7F,uCAAuC"}