@woosh/meep-engine 3.68.0 → 3.69.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 (190) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts +2 -17
  3. package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts.map +1 -1
  4. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +3 -18
  5. package/package.json +1 -1
  6. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +33 -65
  7. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  8. package/src/engine/graphics/ecs/trail3d/Trail3D.js +37 -245
  9. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.d.ts +0 -4
  10. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +4 -10
  11. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.d.ts +13 -10
  12. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.d.ts.map +1 -1
  13. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +28 -37
  14. package/src/engine/graphics/ecs/trail3d/trail_knot_count.d.ts +10 -0
  15. package/src/engine/graphics/ecs/trail3d/trail_knot_count.d.ts.map +1 -0
  16. package/src/engine/graphics/ecs/trail3d/trail_knot_count.js +27 -0
  17. package/src/engine/graphics/trail/TrailKnots.d.ts +62 -0
  18. package/src/engine/graphics/trail/TrailKnots.d.ts.map +1 -0
  19. package/src/engine/graphics/trail/TrailKnots.js +137 -0
  20. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.d.ts +1 -1
  21. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +1 -1
  22. package/src/engine/graphics3/EntityRowHold.d.ts +48 -0
  23. package/src/engine/graphics3/EntityRowHold.d.ts.map +1 -0
  24. package/src/engine/graphics3/EntityRowHold.js +128 -0
  25. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -2
  26. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  27. package/src/engine/graphics3/GPUParticleEmitterSystem.js +11 -44
  28. package/src/engine/graphics3/Trail3DSystem.d.ts +69 -35
  29. package/src/engine/graphics3/Trail3DSystem.d.ts.map +1 -1
  30. package/src/engine/graphics3/Trail3DSystem.js +380 -81
  31. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts +17 -0
  32. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts.map +1 -1
  33. package/src/engine/physics/fluid/ecs/FluidObstacle.js +22 -2
  34. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +6 -5
  35. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts.map +1 -1
  36. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +14 -3
  37. package/src/engine/physics/fluid/obstacle/FLUID_OBSTACLE_RECORD_STRUCT.d.ts +9 -1
  38. package/src/engine/physics/fluid/obstacle/FLUID_OBSTACLE_RECORD_STRUCT.d.ts.map +1 -1
  39. package/src/engine/physics/fluid/obstacle/FLUID_OBSTACLE_RECORD_STRUCT.js +11 -1
  40. package/src/engine/physics/fluid/obstacle/fluid_obstacle_record_create.d.ts +5 -0
  41. package/src/engine/physics/fluid/obstacle/fluid_obstacle_record_create.d.ts.map +1 -1
  42. package/src/engine/physics/fluid/obstacle/fluid_obstacle_record_create.js +2 -0
  43. package/src/engine/physics/fluid/obstacle/fluid_obstacle_write_gpu_record.d.ts +4 -3
  44. package/src/engine/physics/fluid/obstacle/fluid_obstacle_write_gpu_record.d.ts.map +1 -1
  45. package/src/engine/physics/fluid/obstacle/fluid_obstacle_write_gpu_record.js +11 -3
  46. package/src/shade/playground/trails/index.html +50 -0
  47. package/src/shade/playground/trails/main.d.ts +2 -0
  48. package/src/shade/playground/trails/main.d.ts.map +1 -0
  49. package/src/shade/playground/trails/main.js +258 -0
  50. package/src/shade/renderer/animation/animation_curve_write_keys.d.ts +18 -0
  51. package/src/shade/renderer/animation/animation_curve_write_keys.d.ts.map +1 -0
  52. package/src/shade/renderer/animation/animation_curve_write_keys.js +34 -0
  53. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -1
  54. package/src/shade/renderer/deferred/tonemap/ColorGrade.js +13 -36
  55. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +2 -2
  56. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts +2 -13
  57. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts.map +1 -1
  58. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.js +6 -21
  59. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts +17 -6
  60. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts.map +1 -1
  61. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.js +38 -178
  62. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts +7 -9
  63. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts.map +1 -1
  64. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.js +17 -106
  65. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts +7 -17
  66. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts.map +1 -1
  67. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js +18 -118
  68. package/src/shade/renderer/fluid/forcing/FLUID_FORCING.d.ts +14 -0
  69. package/src/shade/renderer/fluid/forcing/FLUID_FORCING.d.ts.map +1 -1
  70. package/src/shade/renderer/fluid/forcing/FLUID_FORCING.js +18 -0
  71. package/src/shade/renderer/fluid/forcing/FLUID_FORCING_APPLY_STRUCT.d.ts +3 -1
  72. package/src/shade/renderer/fluid/forcing/FLUID_FORCING_APPLY_STRUCT.d.ts.map +1 -1
  73. package/src/shade/renderer/fluid/forcing/FLUID_FORCING_APPLY_STRUCT.js +4 -1
  74. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +9 -0
  75. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  76. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +20 -4
  77. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_cell.d.ts +11 -2
  78. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_cell.d.ts.map +1 -1
  79. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_cell.js +59 -2
  80. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.d.ts +4 -1
  81. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.d.ts.map +1 -1
  82. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.js +367 -341
  83. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.d.ts +6 -2
  84. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.d.ts.map +1 -1
  85. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.js +339 -282
  86. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +3 -2
  87. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -1
  88. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +5 -3
  89. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.d.ts +49 -0
  90. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.d.ts.map +1 -0
  91. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.js +144 -0
  92. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.d.ts +71 -0
  93. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.d.ts.map +1 -0
  94. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.js +152 -0
  95. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.d.ts +21 -0
  96. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.d.ts.map +1 -0
  97. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.js +30 -0
  98. package/src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.d.ts +101 -0
  99. package/src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.d.ts.map +1 -0
  100. package/src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.js +306 -0
  101. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts +9 -0
  102. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts.map +1 -1
  103. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js +11 -4
  104. package/src/shade/renderer/trails/GPUTrailAVBOITChannel.d.ts +69 -0
  105. package/src/shade/renderer/trails/GPUTrailAVBOITChannel.d.ts.map +1 -0
  106. package/src/shade/renderer/trails/GPUTrailAVBOITChannel.js +129 -0
  107. package/src/shade/renderer/trails/GPUTrailSystem.d.ts +164 -0
  108. package/src/shade/renderer/trails/GPUTrailSystem.d.ts.map +1 -0
  109. package/src/shade/renderer/trails/GPUTrailSystem.js +725 -0
  110. package/src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.d.ts +14 -0
  111. package/src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.d.ts.map +1 -0
  112. package/src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.js +38 -0
  113. package/src/shade/renderer/trails/data/TRAIL_KNOT.d.ts +66 -0
  114. package/src/shade/renderer/trails/data/TRAIL_KNOT.d.ts.map +1 -0
  115. package/src/shade/renderer/trails/data/TRAIL_KNOT.js +154 -0
  116. package/src/shade/renderer/trails/data/TRAIL_RECORD.d.ts +19 -0
  117. package/src/shade/renderer/trails/data/TRAIL_RECORD.d.ts.map +1 -0
  118. package/src/shade/renderer/trails/data/TRAIL_RECORD.js +68 -0
  119. package/src/shade/renderer/trails/data/TRAIL_STATE.d.ts +18 -0
  120. package/src/shade/renderer/trails/data/TRAIL_STATE.d.ts.map +1 -0
  121. package/src/shade/renderer/trails/data/TRAIL_STATE.js +43 -0
  122. package/src/shade/renderer/trails/graph_trails.d.ts +58 -0
  123. package/src/shade/renderer/trails/graph_trails.d.ts.map +1 -0
  124. package/src/shade/renderer/trails/graph_trails.js +155 -0
  125. package/src/shade/renderer/trails/graph_trails_avboit.d.ts +126 -0
  126. package/src/shade/renderer/trails/graph_trails_avboit.d.ts.map +1 -0
  127. package/src/shade/renderer/trails/graph_trails_avboit.js +300 -0
  128. package/src/shade/renderer/trails/runtime/TrailFadeCurves.d.ts +56 -0
  129. package/src/shade/renderer/trails/runtime/TrailFadeCurves.d.ts.map +1 -0
  130. package/src/shade/renderer/trails/runtime/TrailFadeCurves.js +220 -0
  131. package/src/shade/renderer/trails/runtime/TrailKnotPool.d.ts +49 -0
  132. package/src/shade/renderer/trails/runtime/TrailKnotPool.d.ts.map +1 -0
  133. package/src/shade/renderer/trails/runtime/TrailKnotPool.js +162 -0
  134. package/src/shade/renderer/trails/runtime/TrailParameters.d.ts +52 -0
  135. package/src/shade/renderer/trails/runtime/TrailParameters.d.ts.map +1 -0
  136. package/src/shade/renderer/trails/runtime/TrailParameters.js +126 -0
  137. package/src/shade/renderer/trails/shaders/chunk_trail_frame_transport.d.ts +23 -0
  138. package/src/shade/renderer/trails/shaders/chunk_trail_frame_transport.d.ts.map +1 -0
  139. package/src/shade/renderer/trails/shaders/chunk_trail_frame_transport.js +57 -0
  140. package/src/shade/renderer/trails/shaders/chunk_trail_knot_alpha.d.ts +14 -0
  141. package/src/shade/renderer/trails/shaders/chunk_trail_knot_alpha.d.ts.map +1 -0
  142. package/src/shade/renderer/trails/shaders/chunk_trail_knot_alpha.js +40 -0
  143. package/src/shade/renderer/trails/shaders/chunk_trail_seed.d.ts +18 -0
  144. package/src/shade/renderer/trails/shaders/chunk_trail_seed.d.ts.map +1 -0
  145. package/src/shade/renderer/trails/shaders/chunk_trail_seed.js +64 -0
  146. package/src/shade/renderer/trails/shaders/chunk_trail_segment.d.ts +14 -0
  147. package/src/shade/renderer/trails/shaders/chunk_trail_segment.d.ts.map +1 -0
  148. package/src/shade/renderer/trails/shaders/chunk_trail_segment.js +51 -0
  149. package/src/shade/renderer/trails/shaders/chunk_trail_update.d.ts +48 -0
  150. package/src/shade/renderer/trails/shaders/chunk_trail_update.d.ts.map +1 -0
  151. package/src/shade/renderer/trails/shaders/chunk_trail_update.js +197 -0
  152. package/src/shade/renderer/trails/shaders/chunk_trail_vertex.d.ts +34 -0
  153. package/src/shade/renderer/trails/shaders/chunk_trail_vertex.d.ts.map +1 -0
  154. package/src/shade/renderer/trails/shaders/chunk_trail_vertex.js +111 -0
  155. package/src/shade/renderer/trails/shaders/shader_trail_avboit.d.ts +24 -0
  156. package/src/shade/renderer/trails/shaders/shader_trail_avboit.d.ts.map +1 -0
  157. package/src/shade/renderer/trails/shaders/shader_trail_avboit.js +78 -0
  158. package/src/shade/renderer/trails/shaders/shader_trail_avboit_segments.d.ts +23 -0
  159. package/src/shade/renderer/trails/shaders/shader_trail_avboit_segments.d.ts.map +1 -0
  160. package/src/shade/renderer/trails/shaders/shader_trail_avboit_segments.js +130 -0
  161. package/src/shade/renderer/trails/shaders/shader_trail_draw_args.d.ts +29 -0
  162. package/src/shade/renderer/trails/shaders/shader_trail_draw_args.d.ts.map +1 -0
  163. package/src/shade/renderer/trails/shaders/shader_trail_draw_args.js +78 -0
  164. package/src/shade/renderer/trails/shaders/shader_trail_seed.d.ts +18 -0
  165. package/src/shade/renderer/trails/shaders/shader_trail_seed.d.ts.map +1 -0
  166. package/src/shade/renderer/trails/shaders/shader_trail_seed.js +79 -0
  167. package/src/shade/renderer/trails/shaders/shader_trail_update.d.ts +20 -0
  168. package/src/shade/renderer/trails/shaders/shader_trail_update.d.ts.map +1 -0
  169. package/src/shade/renderer/trails/shaders/shader_trail_update.js +101 -0
  170. package/src/engine/graphics/ecs/trail3d/advance_trail.d.ts +0 -18
  171. package/src/engine/graphics/ecs/trail3d/advance_trail.d.ts.map +0 -1
  172. package/src/engine/graphics/ecs/trail3d/advance_trail.js +0 -42
  173. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.d.ts +0 -14
  174. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.d.ts.map +0 -1
  175. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +0 -75
  176. package/src/engine/graphics/ecs/trail3d/trail_head_position.d.ts +0 -17
  177. package/src/engine/graphics/ecs/trail3d/trail_head_position.d.ts.map +0 -1
  178. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +0 -19
  179. package/src/engine/graphics/trail/tube/TubeX.d.ts +0 -186
  180. package/src/engine/graphics/trail/tube/TubeX.d.ts.map +0 -1
  181. package/src/engine/graphics/trail/tube/TubeX.js +0 -575
  182. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts +0 -16
  183. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts.map +0 -1
  184. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +0 -34
  185. package/src/engine/graphics/trail/tube/tube_attributes_spec.d.ts +0 -27
  186. package/src/engine/graphics/trail/tube/tube_attributes_spec.d.ts.map +0 -1
  187. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +0 -70
  188. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts +0 -38
  189. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts.map +0 -1
  190. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +0 -119
@@ -17,8 +17,9 @@ export const GRASS_PRESS_MARK_WORKGROUP_SIZE: number;
17
17
  * It also writes the clock's time into the word of every tile of the window that its box comes within a
18
18
  * cell of, at the front of the field, `grass_press`: the tiles whose blades read a cell it may press.
19
19
  *
20
- * Two kinds of obstacle list themselves nowhere, and so press nothing. One with no box, a half-space:
21
- * there is no end to what it would press. And one whose row is ground of a grass surface (a member, by the
20
+ * Three kinds of obstacle list themselves nowhere, and so press nothing. One with no box, a half-space:
21
+ * there is no end to what it would press. A porous one (`drag` above 0): the air passes through it,
22
+ * and so does the grass. And one whose row is ground of a grass surface (a member, by the
22
23
  * scene's `mesh_ground_covers`): ground does not press what grows on it, and under everything that
23
24
  * stands on it, it would be the lowest obstacle of every cell.
24
25
  *
@@ -1 +1 @@
1
- {"version":3,"file":"shader_grass_press_mark.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/grass/press/shader_grass_press_mark.js"],"names":[],"mappings":"AA0BA;;;;GAIG;AACH,8CAFU,MAAM,CAEkC;AAYlD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,sCAFU,aAAa,CAyGpB;8BAlK2B,+BAA+B"}
1
+ {"version":3,"file":"shader_grass_press_mark.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/grass/press/shader_grass_press_mark.js"],"names":[],"mappings":"AA0BA;;;;GAIG;AACH,8CAFU,MAAM,CAEkC;AAYlD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,sCAFU,aAAa,CA0GpB;8BApK2B,+BAA+B"}
@@ -54,8 +54,9 @@ resources.createGroup()
54
54
  * It also writes the clock's time into the word of every tile of the window that its box comes within a
55
55
  * cell of, at the front of the field, `grass_press`: the tiles whose blades read a cell it may press.
56
56
  *
57
- * Two kinds of obstacle list themselves nowhere, and so press nothing. One with no box, a half-space:
58
- * there is no end to what it would press. And one whose row is ground of a grass surface (a member, by the
57
+ * Three kinds of obstacle list themselves nowhere, and so press nothing. One with no box, a half-space:
58
+ * there is no end to what it would press. A porous one (`drag` above 0): the air passes through it,
59
+ * and so does the grass. And one whose row is ground of a grass surface (a member, by the
59
60
  * scene's `mesh_ground_covers`): ground does not press what grows on it, and under everything that
60
61
  * stands on it, it would be the lowest obstacle of every cell.
61
62
  *
@@ -86,7 +87,8 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
86
87
  let row = press_rows[i];
87
88
  let record = ${FLUID_OBSTACLE_DESCRIPTOR.marshalling_method_read}(&fluid_database, row);
88
89
 
89
- if (!shape_record_local_bounded(record.shape_kind)) {
90
+ // a half-space, and what the air passes through, such as grass's own canopy
91
+ if (!shape_record_local_bounded(record.shape_kind) || record.drag != 0.0) {
90
92
  return;
91
93
  }
92
94
 
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The render pipeline for an unlit draw shader: additive into the accumulators with the emission
3
+ * target masked off, the opaque scene's depth tested and never written, both faces.
4
+ *
5
+ * @param {object} params
6
+ * @param {string} params.label
7
+ * @param {import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} params.resources
8
+ * the shader's resources; must hold {@link AVBOIT_UNLIT_DRAW_PASS_GROUP}
9
+ * @param {string} params.source the assembled shader, with a vertex entry point named `vs_main` and
10
+ * {@link chunk_avboit_unlit_draw_fragment}'s `fs_main`
11
+ * @returns {RenderPipelineDescriptor}
12
+ */
13
+ export function avboit_unlit_draw_pipeline({ label, resources, source }: {
14
+ label: string;
15
+ resources: import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor;
16
+ source: string;
17
+ }): RenderPipelineDescriptor;
18
+ /**
19
+ * What the unlit draw reads once per pass: the view, the warp, the integral and the fog.
20
+ *
21
+ * @type {ShaderResourceGroupDescriptor}
22
+ */
23
+ export const AVBOIT_UNLIT_DRAW_PASS_GROUP: ShaderResourceGroupDescriptor;
24
+ /**
25
+ * The unlit AVBOIT draw's fragment stage, `fs_main`: unlit straight-alpha geometry — a dynamic mesh, a
26
+ * trail — drawn at internal resolution into the four accumulators the transparent meshes and the
27
+ * particles draw into (`avboit_draw_fragment_body`), so it composites against both order-independently.
28
+ * Any vertex stage that hands it `AVBOITUnlitVaryings` (`chunk_avboit_unlit_varyings`) can be linked
29
+ * with it.
30
+ *
31
+ * Per fragment: nothing at all if it has faded out (the unlit splat recorded nothing for it either),
32
+ * then the transmittance of everything in front from the integral texture — a fragment the volume
33
+ * already calls extinct is discarded unshaded — the volumetric fog at its depth, and the accumulators
34
+ * through `avboit_premultiplied_contribution`, the routing every side channel shares.
35
+ *
36
+ * The colour is straight alpha and unlit: it is premultiplied here and never emits — a fragment that
37
+ * can get past the first test covers something — so {@link avboit_unlit_draw_pipeline} does not write
38
+ * the emission target at all rather than blend zeros into it over every covered pixel.
39
+ *
40
+ * The enclosing shader binds {@link AVBOIT_UNLIT_DRAW_PASS_GROUP} and names its vertex entry point
41
+ * anything but `fs_main`.
42
+ *
43
+ * @type {CodeChunk}
44
+ */
45
+ export const chunk_avboit_unlit_draw_fragment: CodeChunk;
46
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
47
+ import { ShaderResourceGroupDescriptor } from "../../../shader/resource/ShaderResourceGroupDescriptor.js";
48
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
49
+ //# sourceMappingURL=avboit_unlit_draw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avboit_unlit_draw.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.js"],"names":[],"mappings":"AAiHA;;;;;;;;;;;GAWG;AACH;IAP0B,KAAK,EAApB,MAAM;IACgG,SAAS,EAA/G,OAAO,yDAAyD,EAAE,2BAA2B;IAE9E,MAAM,EAArB,MAAM;IAEJ,wBAAwB,CAoBpC;AA5HD;;;;GAIG;AACH,2CAFU,6BAA6B,CAEyC;AAahF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,+CAFU,SAAS,CAuDjB;yCA7GuC,oEAAoE;8CAI/D,2DAA2D;0BAD/E,uCAAuC"}
@@ -0,0 +1,144 @@
1
+ import { GPUShaderStage } from "../../../../descriptor/GPUShaderStage.js";
2
+ import { DepthStencilState } from "../../../../descriptor/pipeline/render/DepthStencilState.js";
3
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
4
+ import { assert } from "../../../../../core/assert.js";
5
+ import { chunk_sample_volumetrics } from "../../../deferred/chunk_sample_volumetrics.js";
6
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
7
+ import { ShaderResourceGroupDescriptor } from "../../../shader/resource/ShaderResourceGroupDescriptor.js";
8
+ import { SAMPLER_LINEAR_UPSCALE } from "../../../texture/SAMPLER_LINEAR_UPSCALE.js";
9
+ import { VIEW_UNIFORM_STRUCT } from "../../../view/VIEW_UNIFORM_STRUCT.js";
10
+ import { VOLUMETRICS_METADATA_STRUCT } from "../../../volumetrics/VOLUMETRICS_METADATA_STRUCT.js";
11
+ import { AVBOIT_EXTINCT_TRANSMITTANCE } from "./AVBOIT_CONSTANTS.js";
12
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
13
+ import { AVBOIT_DRAW_TARGETS } from "./avboit_draw_fragment_body.js";
14
+ import { chunk_avboit_footprint_bias } from "./chunk_avboit_footprint_bias.js";
15
+ import { chunk_avboit_premultiplied_contribution } from "./chunk_avboit_premultiplied_contribution.js";
16
+ import { chunk_avboit_sample_transmittance } from "./chunk_avboit_sample_transmittance.js";
17
+ import { chunk_avboit_unlit_varyings } from "./chunk_avboit_unlit_varyings.js";
18
+ import { chunk_avboit_view_depth_to_virtual } from "./chunk_avboit_view_depth_to_virtual.js";
19
+
20
+ /**
21
+ * What the unlit draw reads once per pass: the view, the warp, the integral and the fog.
22
+ *
23
+ * @type {ShaderResourceGroupDescriptor}
24
+ */
25
+ export const AVBOIT_UNLIT_DRAW_PASS_GROUP = new ShaderResourceGroupDescriptor();
26
+
27
+ AVBOIT_UNLIT_DRAW_PASS_GROUP
28
+ .addUniform("view", VIEW_UNIFORM_STRUCT)
29
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
30
+ // sampled through sLinear: linear, clamped on every axis, which is what the integral needs
31
+ .addTexture("tIntegral", "float", "3d")
32
+ .addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
33
+ // volumetrics (composited inline)
34
+ .addUniform("volumetrics_metadata", VOLUMETRICS_METADATA_STRUCT)
35
+ .addTexture("tVolumetrics", "float", "3d")
36
+ .addTexture("tSTBN_vec3", "float", "3d");
37
+
38
+ /**
39
+ * The unlit AVBOIT draw's fragment stage, `fs_main`: unlit straight-alpha geometry — a dynamic mesh, a
40
+ * trail — drawn at internal resolution into the four accumulators the transparent meshes and the
41
+ * particles draw into (`avboit_draw_fragment_body`), so it composites against both order-independently.
42
+ * Any vertex stage that hands it `AVBOITUnlitVaryings` (`chunk_avboit_unlit_varyings`) can be linked
43
+ * with it.
44
+ *
45
+ * Per fragment: nothing at all if it has faded out (the unlit splat recorded nothing for it either),
46
+ * then the transmittance of everything in front from the integral texture — a fragment the volume
47
+ * already calls extinct is discarded unshaded — the volumetric fog at its depth, and the accumulators
48
+ * through `avboit_premultiplied_contribution`, the routing every side channel shares.
49
+ *
50
+ * The colour is straight alpha and unlit: it is premultiplied here and never emits — a fragment that
51
+ * can get past the first test covers something — so {@link avboit_unlit_draw_pipeline} does not write
52
+ * the emission target at all rather than blend zeros into it over every covered pixel.
53
+ *
54
+ * The enclosing shader binds {@link AVBOIT_UNLIT_DRAW_PASS_GROUP} and names its vertex entry point
55
+ * anything but `fs_main`.
56
+ *
57
+ * @type {CodeChunk}
58
+ */
59
+ export const chunk_avboit_unlit_draw_fragment = CodeChunk.from(
60
+ //language=WGSL
61
+ `
62
+ struct AVBOITUnlitDrawOutput {
63
+ @location(0) color : vec4<f32>,
64
+ @location(1) norm : vec4<f32>,
65
+ @location(2) extinction : vec4<f32>,
66
+ @location(3) emission : vec4<f32>,
67
+ }
68
+
69
+ @fragment
70
+ fn fs_main(fragment : AVBOITUnlitVaryings) -> AVBOITUnlitDrawOutput {
71
+ // a ribbon seen at an angle runs through depth across a voxel; see avboit_footprint_bias. Taken
72
+ // first, in uniform control flow
73
+ let footprint = avboit_footprint_bias(&warp, fwidth(avboit_view_depth_to_virtual(&warp, fragment.view_depth)));
74
+
75
+ if (fragment.color.a <= 0.0) {
76
+ // faded out: covers nothing, and straight alpha carries no light without coverage
77
+ discard;
78
+ }
79
+
80
+ let screen_uv = fragment.clip.xy / vec2<f32>(f32(view.width), f32(view.height));
81
+
82
+ let transmittance = avboit_sample_transmittance(&warp, tIntegral, sLinear, screen_uv, fragment.view_depth, footprint);
83
+
84
+ if (all(transmittance <= vec3<f32>(${AVBOIT_EXTINCT_TRANSMITTANCE}))) {
85
+ // nothing this fragment contributes survives what is in front of it; skip the shading
86
+ discard;
87
+ }
88
+
89
+ let volumetrics = sample_volumetrics(fragment.view_depth, screen_uv, fragment.clip.xy);
90
+
91
+ let premultiplied = vec4<f32>(fragment.color.rgb * fragment.color.a, fragment.color.a);
92
+
93
+ let contribution = avboit_premultiplied_contribution(premultiplied, transmittance, volumetrics);
94
+
95
+ var out : AVBOITUnlitDrawOutput;
96
+
97
+ out.color = contribution.color;
98
+ out.norm = contribution.norm;
99
+ out.extinction = contribution.extinction;
100
+ out.emission = contribution.emission;
101
+
102
+ return out;
103
+ }
104
+ `, [
105
+ chunk_avboit_unlit_varyings,
106
+ chunk_avboit_view_depth_to_virtual,
107
+ chunk_avboit_footprint_bias,
108
+ chunk_avboit_sample_transmittance,
109
+ chunk_sample_volumetrics,
110
+ chunk_avboit_premultiplied_contribution,
111
+ ]
112
+ );
113
+
114
+ /**
115
+ * The render pipeline for an unlit draw shader: additive into the accumulators with the emission
116
+ * target masked off, the opaque scene's depth tested and never written, both faces.
117
+ *
118
+ * @param {object} params
119
+ * @param {string} params.label
120
+ * @param {import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} params.resources
121
+ * the shader's resources; must hold {@link AVBOIT_UNLIT_DRAW_PASS_GROUP}
122
+ * @param {string} params.source the assembled shader, with a vertex entry point named `vs_main` and
123
+ * {@link chunk_avboit_unlit_draw_fragment}'s `fs_main`
124
+ * @returns {RenderPipelineDescriptor}
125
+ */
126
+ export function avboit_unlit_draw_pipeline({ label, resources, source }) {
127
+ assert.isString(label, "label");
128
+ assert.isString(source, "source");
129
+ assert.notEqual(resources.groups.indexOf(AVBOIT_UNLIT_DRAW_PASS_GROUP), -1, "resources must hold the unlit draw's pass group");
130
+
131
+ return RenderPipelineDescriptor.from({
132
+ label,
133
+ layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
134
+ vertex: { module: { code: source }, entryPoint: "vs_main" },
135
+ fragment: {
136
+ module: { code: source },
137
+ entryPoint: "fs_main",
138
+ // color, norm, extinction — and not emission
139
+ targets: AVBOIT_DRAW_TARGETS.map((target, i) => ({ ...target, writeMask: [0xF, 0xF, 0xF, 0][i] })),
140
+ },
141
+ depthStencil: DepthStencilState.from({ format: "depth32float", depthWriteEnabled: false, depthCompare: "greater" }),
142
+ primitive: { topology: "triangle-list", cullMode: "none" },
143
+ });
144
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The render pipeline for an unlit splat shader: no depth, one never-written attachment to size the
3
+ * raster ({@link AVBOIT_UNLIT_SPLAT_SAMPLES} samples, not the volume's single-sampled one the meshlet
4
+ * and particle splats share), both faces — a trail is seen from inside and out.
5
+ *
6
+ * The layout is built group by group: the volume's atomics are fragment-only, and WebGPU refuses a
7
+ * read-write storage buffer that is visible to the vertex stage. Every other group is visible to both
8
+ * stages, so a group the shader shares with other pipelines keeps the one layout they all declare.
9
+ *
10
+ * @param {object} params
11
+ * @param {string} params.label
12
+ * @param {import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} params.resources
13
+ * the shader's resources; must hold {@link AVBOIT_UNLIT_SPLAT_PASS_GROUP} and `AVBOIT_SPLAT_VOLUME_GROUP`
14
+ * @param {string} params.source the assembled shader, with a vertex entry point named `vs_main` and
15
+ * {@link chunk_avboit_unlit_splat_fragment}'s `fs_main`
16
+ * @returns {RenderPipelineDescriptor}
17
+ */
18
+ export function avboit_unlit_splat_pipeline({ label, resources, source }: {
19
+ label: string;
20
+ resources: import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor;
21
+ source: string;
22
+ }): RenderPipelineDescriptor;
23
+ /**
24
+ * Samples per pixel of the unlit splat's raster, which is what a fragment's extinction is weighted by
25
+ * the share of. Four, being the only count above one that WebGPU guarantees.
26
+ * @type {number}
27
+ */
28
+ export const AVBOIT_UNLIT_SPLAT_SAMPLES: number;
29
+ /**
30
+ * What the unlit splat reads once per pass: the warp, which places a view depth in the volume.
31
+ *
32
+ * @type {ShaderResourceGroupDescriptor}
33
+ */
34
+ export const AVBOIT_UNLIT_SPLAT_PASS_GROUP: ShaderResourceGroupDescriptor;
35
+ /**
36
+ * The unlit AVBOIT splat's fragment stage, `fs_main`: unlit straight-alpha geometry — a dynamic mesh,
37
+ * a trail — adding its extinction into the voxel volume through `avboit_splat_slice`, the same write
38
+ * path as the meshlet and particle splats, so a trail, a particle and a surface at one depth pile up in
39
+ * one field. Any vertex stage that hands it `AVBOITUnlitVaryings` (`chunk_avboit_unlit_varyings`) can
40
+ * be linked with it.
41
+ *
42
+ * Coverage is the varyings' alpha through `avboit_coverage` — the function the unlit draw weights the
43
+ * same fragment by — and `T_self = 1 - coverage`, untinted. A fragment that has faded to nothing covers
44
+ * nothing and writes nothing, which on a trail is its whole aged-out tail.
45
+ *
46
+ * **Weighted by the share of the voxel the triangle covers.** A voxel is eight pixels across, and a
47
+ * trail is often narrower than that. Sampled at the voxel's centre alone, a thin trail either crosses
48
+ * the centre and writes its full extinction there or misses it and writes nothing, so its occlusion of
49
+ * what lies behind it comes and goes as it moves by a fraction of a voxel. The raster has
50
+ * {@link AVBOIT_UNLIT_SPLAT_SAMPLES} samples per pixel, the fragment runs wherever any of them is
51
+ * covered, and its extinction is scaled by the covered fraction: the voxel gets the triangle's
52
+ * extinction averaged over its footprint, as a volume that coarse can hold it. The triangles of one
53
+ * mesh cover disjoint samples, so the fractions of the triangles sharing a voxel add up to at most one
54
+ * layer; a fully covered voxel is written exactly as an unweighted splat would write it. What remains
55
+ * is the average's own bias — a trail a fraction of a voxel wide occludes what is behind it by that
56
+ * fraction of its extinction — which holds still as the trail moves.
57
+ *
58
+ * Depth is the fragment's own view depth from the varyings, through curve → warp → physical and the
59
+ * two-slice linear split the other splats make. No depth attachment, for the reason the meshlet splat
60
+ * has none: a splat behind an opaque surface lies deeper than anything the draw will look it up for.
61
+ *
62
+ * The enclosing shader binds {@link AVBOIT_UNLIT_SPLAT_PASS_GROUP} and `AVBOIT_SPLAT_VOLUME_GROUP`,
63
+ * and names its vertex entry point anything but `fs_main`.
64
+ *
65
+ * @type {CodeChunk}
66
+ */
67
+ export const chunk_avboit_unlit_splat_fragment: CodeChunk;
68
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
69
+ import { ShaderResourceGroupDescriptor } from "../../../shader/resource/ShaderResourceGroupDescriptor.js";
70
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
71
+ //# sourceMappingURL=avboit_unlit_splat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avboit_unlit_splat.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.js"],"names":[],"mappings":"AAwGA;;;;;;;;;;;;;;;;GAgBG;AACH;IAP0B,KAAK,EAApB,MAAM;IACgG,SAAS,EAA/G,OAAO,yDAAyD,EAAE,2BAA2B;IAE9E,MAAM,EAArB,MAAM;IAEJ,wBAAwB,CAgCpC;AAzID;;;;GAIG;AACH,yCAFU,MAAM,CAE4B;AAE5C;;;;GAIG;AACH,4CAFU,6BAA6B,CAE0C;AAKjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,gDAFU,SAAS,CAyCjB;yCApGuC,oEAAoE;8CAG/D,2DAA2D;0BAD/E,uCAAuC"}
@@ -0,0 +1,152 @@
1
+ import { GPUShaderStage } from "../../../../descriptor/GPUShaderStage.js";
2
+ import { PipelineLayoutDescriptor } from "../../../../descriptor/pipeline/PipelineLayoutDescriptor.js";
3
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
4
+ import { assert } from "../../../../../core/assert.js";
5
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
6
+ import { ShaderResourceGroupDescriptor } from "../../../shader/resource/ShaderResourceGroupDescriptor.js";
7
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
8
+ import { chunk_avboit_coverage } from "./chunk_avboit_coverage.js";
9
+ import { chunk_avboit_splat_slice } from "./chunk_avboit_splat_slice.js";
10
+ import { chunk_avboit_transmittance_to_extinction } from "./chunk_avboit_transmittance_to_extinction.js";
11
+ import { chunk_avboit_unlit_varyings } from "./chunk_avboit_unlit_varyings.js";
12
+ import { chunk_avboit_view_depth_to_physical } from "./chunk_avboit_view_depth_to_physical.js";
13
+ import { AVBOIT_SPLAT_DUMMY_FORMAT, AVBOIT_SPLAT_VOLUME_GROUP } from "./shader_avboit_splat.js";
14
+
15
+ /**
16
+ * Samples per pixel of the unlit splat's raster, which is what a fragment's extinction is weighted by
17
+ * the share of. Four, being the only count above one that WebGPU guarantees.
18
+ * @type {number}
19
+ */
20
+ export const AVBOIT_UNLIT_SPLAT_SAMPLES = 4;
21
+
22
+ /**
23
+ * What the unlit splat reads once per pass: the warp, which places a view depth in the volume.
24
+ *
25
+ * @type {ShaderResourceGroupDescriptor}
26
+ */
27
+ export const AVBOIT_UNLIT_SPLAT_PASS_GROUP = new ShaderResourceGroupDescriptor();
28
+
29
+ AVBOIT_UNLIT_SPLAT_PASS_GROUP
30
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT);
31
+
32
+ /**
33
+ * The unlit AVBOIT splat's fragment stage, `fs_main`: unlit straight-alpha geometry — a dynamic mesh,
34
+ * a trail — adding its extinction into the voxel volume through `avboit_splat_slice`, the same write
35
+ * path as the meshlet and particle splats, so a trail, a particle and a surface at one depth pile up in
36
+ * one field. Any vertex stage that hands it `AVBOITUnlitVaryings` (`chunk_avboit_unlit_varyings`) can
37
+ * be linked with it.
38
+ *
39
+ * Coverage is the varyings' alpha through `avboit_coverage` — the function the unlit draw weights the
40
+ * same fragment by — and `T_self = 1 - coverage`, untinted. A fragment that has faded to nothing covers
41
+ * nothing and writes nothing, which on a trail is its whole aged-out tail.
42
+ *
43
+ * **Weighted by the share of the voxel the triangle covers.** A voxel is eight pixels across, and a
44
+ * trail is often narrower than that. Sampled at the voxel's centre alone, a thin trail either crosses
45
+ * the centre and writes its full extinction there or misses it and writes nothing, so its occlusion of
46
+ * what lies behind it comes and goes as it moves by a fraction of a voxel. The raster has
47
+ * {@link AVBOIT_UNLIT_SPLAT_SAMPLES} samples per pixel, the fragment runs wherever any of them is
48
+ * covered, and its extinction is scaled by the covered fraction: the voxel gets the triangle's
49
+ * extinction averaged over its footprint, as a volume that coarse can hold it. The triangles of one
50
+ * mesh cover disjoint samples, so the fractions of the triangles sharing a voxel add up to at most one
51
+ * layer; a fully covered voxel is written exactly as an unweighted splat would write it. What remains
52
+ * is the average's own bias — a trail a fraction of a voxel wide occludes what is behind it by that
53
+ * fraction of its extinction — which holds still as the trail moves.
54
+ *
55
+ * Depth is the fragment's own view depth from the varyings, through curve → warp → physical and the
56
+ * two-slice linear split the other splats make. No depth attachment, for the reason the meshlet splat
57
+ * has none: a splat behind an opaque surface lies deeper than anything the draw will look it up for.
58
+ *
59
+ * The enclosing shader binds {@link AVBOIT_UNLIT_SPLAT_PASS_GROUP} and `AVBOIT_SPLAT_VOLUME_GROUP`,
60
+ * and names its vertex entry point anything but `fs_main`.
61
+ *
62
+ * @type {CodeChunk}
63
+ */
64
+ export const chunk_avboit_unlit_splat_fragment = CodeChunk.from(
65
+ //language=WGSL
66
+ `
67
+ @fragment
68
+ fn fs_main(fragment : AVBOITUnlitVaryings, @builtin(sample_mask) sample_mask : u32) {
69
+ // the coverage the draw weights this fragment by, through the same function
70
+ let coverage = avboit_coverage(fragment.color.a);
71
+
72
+ if (coverage <= 0.0) {
73
+ // faded out: occludes nothing
74
+ return;
75
+ }
76
+
77
+ // the share of the voxel's samples this triangle covers
78
+ let footprint = f32(countOneBits(sample_mask)) / ${AVBOIT_UNLIT_SPLAT_SAMPLES}.0;
79
+
80
+ let extinction = avboit_transmittance_to_extinction(vec3<f32>(1.0 - coverage)) * footprint;
81
+
82
+ let p = avboit_view_depth_to_physical(&warp, fragment.view_depth);
83
+
84
+ // fragment.clip is @builtin(position): .xy the low-resolution pixel
85
+ let texel = vec2<u32>(fragment.clip.xy);
86
+ let column = texel.y * warp.voxel_width + texel.x;
87
+
88
+ // linear splat between the two slices around the fragment
89
+ let c = p - 0.5;
90
+ let slice = i32(floor(c));
91
+ let fraction = c - floor(c);
92
+
93
+ avboit_splat_slice(column, slice, extinction * (1.0 - fraction), texel);
94
+ avboit_splat_slice(column, slice + 1, extinction * fraction, texel);
95
+ }
96
+ `, [
97
+ chunk_avboit_unlit_varyings,
98
+ chunk_avboit_coverage,
99
+ chunk_avboit_transmittance_to_extinction,
100
+ chunk_avboit_view_depth_to_physical,
101
+ chunk_avboit_splat_slice,
102
+ ]
103
+ );
104
+
105
+ /**
106
+ * The render pipeline for an unlit splat shader: no depth, one never-written attachment to size the
107
+ * raster ({@link AVBOIT_UNLIT_SPLAT_SAMPLES} samples, not the volume's single-sampled one the meshlet
108
+ * and particle splats share), both faces — a trail is seen from inside and out.
109
+ *
110
+ * The layout is built group by group: the volume's atomics are fragment-only, and WebGPU refuses a
111
+ * read-write storage buffer that is visible to the vertex stage. Every other group is visible to both
112
+ * stages, so a group the shader shares with other pipelines keeps the one layout they all declare.
113
+ *
114
+ * @param {object} params
115
+ * @param {string} params.label
116
+ * @param {import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} params.resources
117
+ * the shader's resources; must hold {@link AVBOIT_UNLIT_SPLAT_PASS_GROUP} and `AVBOIT_SPLAT_VOLUME_GROUP`
118
+ * @param {string} params.source the assembled shader, with a vertex entry point named `vs_main` and
119
+ * {@link chunk_avboit_unlit_splat_fragment}'s `fs_main`
120
+ * @returns {RenderPipelineDescriptor}
121
+ */
122
+ export function avboit_unlit_splat_pipeline({ label, resources, source }) {
123
+ assert.isString(label, "label");
124
+ assert.isString(source, "source");
125
+
126
+ const groups = resources.groups;
127
+
128
+ assert.notEqual(groups.indexOf(AVBOIT_UNLIT_SPLAT_PASS_GROUP), -1, "resources must hold the unlit splat's pass group");
129
+ assert.notEqual(groups.indexOf(AVBOIT_SPLAT_VOLUME_GROUP), -1, "resources must hold the splat volume group");
130
+
131
+ const layout = PipelineLayoutDescriptor.from(
132
+ groups.map(group => group.generateBindGroupLayoutDescriptor(
133
+ group === AVBOIT_SPLAT_VOLUME_GROUP
134
+ ? GPUShaderStage.FRAGMENT
135
+ : GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT
136
+ )),
137
+ resources.immediateSize
138
+ );
139
+
140
+ return RenderPipelineDescriptor.from({
141
+ label,
142
+ layout,
143
+ vertex: { module: { code: source }, entryPoint: "vs_main" },
144
+ fragment: {
145
+ module: { code: source },
146
+ entryPoint: "fs_main",
147
+ targets: [{ format: AVBOIT_SPLAT_DUMMY_FORMAT, writeMask: 0 }],
148
+ },
149
+ primitive: { topology: "triangle-list", cullMode: "none" },
150
+ multisample: { count: AVBOIT_UNLIT_SPLAT_SAMPLES },
151
+ });
152
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * What a vertex stage hands the unlit AVBOIT fragment stages (`chunk_avboit_unlit_splat_fragment`,
3
+ * `chunk_avboit_unlit_draw_fragment`): `struct AVBOITUnlitVaryings`.
4
+ *
5
+ * - `clip` is the clip-space position.
6
+ * - `color` is straight, not premultiplied: RGB and the fragment's own opacity.
7
+ * - `view_depth` is the vertex's view-space depth, interpolated across the triangle. The splat
8
+ * positions a fragment's extinction by it and the draw looks the volume up at it, so both take it
9
+ * from here rather than reconstructing it from `@builtin(position).z`.
10
+ *
11
+ * `color` and `view_depth` are interpolated at the **centroid** of the samples a triangle covers. The
12
+ * splat is multisampled, and a thin triangle can cover some of a pixel's samples but not its centre;
13
+ * at the centre its depth and alpha would be extrapolated off the triangle's edge, which on a ribbon
14
+ * seen nearly edge-on lands the extinction slices away from the ribbon. The draw has one sample, where
15
+ * a fragment exists only if the centre is covered and the centroid is the centre.
16
+ *
17
+ * @type {CodeChunk}
18
+ */
19
+ export const chunk_avboit_unlit_varyings: CodeChunk;
20
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
21
+ //# sourceMappingURL=chunk_avboit_unlit_varyings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_avboit_unlit_varyings.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,0CAFU,SAAS,CAWjB;0BA7BwB,uCAAuC"}
@@ -0,0 +1,30 @@
1
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
2
+
3
+ /**
4
+ * What a vertex stage hands the unlit AVBOIT fragment stages (`chunk_avboit_unlit_splat_fragment`,
5
+ * `chunk_avboit_unlit_draw_fragment`): `struct AVBOITUnlitVaryings`.
6
+ *
7
+ * - `clip` is the clip-space position.
8
+ * - `color` is straight, not premultiplied: RGB and the fragment's own opacity.
9
+ * - `view_depth` is the vertex's view-space depth, interpolated across the triangle. The splat
10
+ * positions a fragment's extinction by it and the draw looks the volume up at it, so both take it
11
+ * from here rather than reconstructing it from `@builtin(position).z`.
12
+ *
13
+ * `color` and `view_depth` are interpolated at the **centroid** of the samples a triangle covers. The
14
+ * splat is multisampled, and a thin triangle can cover some of a pixel's samples but not its centre;
15
+ * at the centre its depth and alpha would be extrapolated off the triangle's edge, which on a ribbon
16
+ * seen nearly edge-on lands the extinction slices away from the ribbon. The draw has one sample, where
17
+ * a fragment exists only if the centre is covered and the centroid is the centre.
18
+ *
19
+ * @type {CodeChunk}
20
+ */
21
+ export const chunk_avboit_unlit_varyings = CodeChunk.from(
22
+ //language=WGSL
23
+ `
24
+ struct AVBOITUnlitVaryings {
25
+ @builtin(position) clip : vec4<f32>,
26
+ @location(0) @interpolate(perspective, centroid) color : vec4<f32>,
27
+ @location(1) @interpolate(perspective, centroid) view_depth : f32,
28
+ }
29
+ `
30
+ );
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Splat a channel's unlit geometry into the voxel volume.
3
+ *
4
+ * The raster is multisampled ({@link AVBOIT_UNLIT_SPLAT_SAMPLES}), so it cannot use the volume's
5
+ * single-sampled splat target: the pass makes its own at the volume's resolution, never written,
6
+ * cleared and discarded, and hands the volume's back untouched.
7
+ *
8
+ * @param {object} params
9
+ * @param {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
10
+ * @param {string} params.label the pass's label; its target is labelled after it
11
+ * @param {import("../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js").RenderPipelineDescriptor} params.pipeline
12
+ * from `avboit_unlit_splat_pipeline`
13
+ * @param {import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} params.resources
14
+ * the pipeline's shader resources
15
+ * @param {Object<string, number>} params.inputs graph handles the channel's draws read, by name
16
+ * @param {number} params.warp graph handle
17
+ * @param {number[]} params.voxel_resolution the volume's width and height, which the raster is
18
+ * @param {{extinction: number, overflow: number, dummy: number}} params.volume the volume, to add to
19
+ * @param {function(): boolean} params.is_empty asked when the pass executes; `true` records no render pass
20
+ * @param {function(GPURenderPassEncoder, GraphicsContext, Object<string, *>): void} params.record issues
21
+ * the draws into the open pass, whose pass-level groups are set, with `inputs` resolved
22
+ * @returns {{extinction: number, overflow: number, dummy: number}} the volume after the write
23
+ */
24
+ export function graph_avboit_unlit_splat({ graph, label, pipeline, resources, inputs, warp, voxel_resolution, volume, is_empty, record, }: {
25
+ graph: import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
26
+ label: string;
27
+ pipeline: import("../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js").RenderPipelineDescriptor;
28
+ resources: import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor;
29
+ inputs: {
30
+ [x: string]: number;
31
+ };
32
+ warp: number;
33
+ voxel_resolution: number[];
34
+ volume: {
35
+ extinction: number;
36
+ overflow: number;
37
+ dummy: number;
38
+ };
39
+ is_empty: () => boolean;
40
+ record: (arg0: GPURenderPassEncoder, arg1: GraphicsContext, arg2: {
41
+ [x: string]: any;
42
+ }) => void;
43
+ }): {
44
+ extinction: number;
45
+ overflow: number;
46
+ dummy: number;
47
+ };
48
+ /**
49
+ * Draw a channel's unlit geometry into the four accumulators, depth-tested against the opaque scene.
50
+ *
51
+ * @param {object} params
52
+ * @param {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
53
+ * @param {string} params.label
54
+ * @param {import("../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js").RenderPipelineDescriptor} params.pipeline
55
+ * from `avboit_unlit_draw_pipeline`
56
+ * @param {import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} params.resources
57
+ * the pipeline's shader resources
58
+ * @param {Object<string, number>} params.inputs graph handles the channel's draws read, by name
59
+ * @param {import("../../../view/GPUViewContext.js").GPUViewContext} params.view_ctx
60
+ * @param {number} params.depth_texture graph handle of the opaque scene's depth — tested, never written
61
+ * @param {number} params.warp graph handle
62
+ * @param {number} params.integral graph handle of the integral texture
63
+ * @param {number} params.volumetrics_lut graph handle
64
+ * @param {number} params.volumetrics_metadata graph handle
65
+ * @param {{color: number, norm: number, extinction: number, emission: number}} params.accumulators to add to
66
+ * @param {function(): boolean} params.is_empty asked when the pass executes; `true` records no render pass
67
+ * @param {function(GPURenderPassEncoder, GraphicsContext, Object<string, *>): void} params.record issues
68
+ * the draws into the open pass, whose pass-level group is set, with `inputs` resolved
69
+ * @returns {{color: number, norm: number, extinction: number, emission: number}} the accumulators after the draw
70
+ */
71
+ export function graph_avboit_unlit_draw({ graph, label, pipeline, resources, inputs, view_ctx, depth_texture, warp, integral, volumetrics_lut, volumetrics_metadata, accumulators, is_empty, record, }: {
72
+ graph: import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
73
+ label: string;
74
+ pipeline: import("../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js").RenderPipelineDescriptor;
75
+ resources: import("../../../shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor;
76
+ inputs: {
77
+ [x: string]: number;
78
+ };
79
+ view_ctx: import("../../../view/GPUViewContext.js").GPUViewContext;
80
+ depth_texture: number;
81
+ warp: number;
82
+ integral: number;
83
+ volumetrics_lut: number;
84
+ volumetrics_metadata: number;
85
+ accumulators: {
86
+ color: number;
87
+ norm: number;
88
+ extinction: number;
89
+ emission: number;
90
+ };
91
+ is_empty: () => boolean;
92
+ record: (arg0: GPURenderPassEncoder, arg1: GraphicsContext, arg2: {
93
+ [x: string]: any;
94
+ }) => void;
95
+ }): {
96
+ color: number;
97
+ norm: number;
98
+ extinction: number;
99
+ emission: number;
100
+ };
101
+ //# sourceMappingURL=graph_avboit_unlit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph_avboit_unlit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.js"],"names":[],"mappings":"AAuEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAfwG,KAAK,EAAlG,OAAO,iEAAiE,EAAE,UAAU;IACrE,KAAK,EAApB,MAAM;IACwG,QAAQ,EAAtH,OAAO,oEAAoE,EAAE,wBAAwB;IAEC,SAAS,EAA/G,OAAO,yDAAyD,EAAE,2BAA2B;IAE9D,MAAM;YAA9B,MAAM,GAAE,MAAM;;IACN,IAAI,EAAnB,MAAM;IACW,gBAAgB,EAAjC,MAAM,EAAE;IACsD,MAAM,EAApE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC;IACzB,QAAQ,QAAxB,OAAO;IAC8D,MAAM;YAAhC,MAAM;UAAO,IAAI;IAEtE;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA4FjE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAnBwG,KAAK,EAAlG,OAAO,iEAAiE,EAAE,UAAU;IACrE,KAAK,EAApB,MAAM;IACwG,QAAQ,EAAtH,OAAO,oEAAoE,EAAE,wBAAwB;IAEC,SAAS,EAA/G,OAAO,yDAAyD,EAAE,2BAA2B;IAE9D,MAAM;YAA9B,MAAM,GAAE,MAAM;;IAC4C,QAAQ,EAAzE,OAAO,iCAAiC,EAAE,cAAc;IACzC,aAAa,EAA5B,MAAM;IACS,IAAI,EAAnB,MAAM;IACS,QAAQ,EAAvB,MAAM;IACS,eAAe,EAA9B,MAAM;IACS,oBAAoB,EAAnC,MAAM;IACsE,YAAY,EAAxF;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC;IACvC,QAAQ,QAAxB,OAAO;IAC8D,MAAM;YAAhC,MAAM;UAAO,IAAI;IAEtE;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAkG/E"}