@woosh/meep-engine 3.14.6 → 3.15.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 (154) hide show
  1. package/package.json +1 -1
  2. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +48 -0
  3. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  4. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +246 -3
  5. package/src/shade/RENDERER_CONTRACT.md +584 -580
  6. package/src/shade/playground/avboit/README.md +117 -0
  7. package/src/shade/playground/avboit/index.html +215 -0
  8. package/src/shade/playground/avboit/main.d.ts +2 -0
  9. package/src/shade/playground/avboit/main.d.ts.map +1 -0
  10. package/src/shade/playground/avboit/main.js +875 -0
  11. package/src/shade/renderer/Renderer.d.ts +16 -0
  12. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  13. package/src/shade/renderer/Renderer.js +29 -28
  14. package/src/shade/renderer/ShadeTransparencyMode.d.ts +13 -0
  15. package/src/shade/renderer/ShadeTransparencyMode.d.ts.map +1 -0
  16. package/src/shade/renderer/ShadeTransparencyMode.js +30 -0
  17. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts +9 -0
  18. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  19. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +26 -0
  20. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts +7 -2
  21. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  22. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +12 -1
  23. package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.js +1 -1
  24. package/src/shade/renderer/rasterize/forward/FORWARD_VERTEX_SHADER_STRUCT.d.ts +3 -0
  25. package/src/shade/renderer/rasterize/forward/FORWARD_VERTEX_SHADER_STRUCT.d.ts.map +1 -0
  26. package/src/shade/renderer/rasterize/{native/oit → forward}/FORWARD_VERTEX_SHADER_STRUCT.js +4 -4
  27. package/src/shade/renderer/rasterize/forward/SHADING_SCENE_RESOURCE_GROUP.d.ts +3 -0
  28. package/src/shade/renderer/rasterize/forward/SHADING_SCENE_RESOURCE_GROUP.d.ts.map +1 -0
  29. package/src/shade/renderer/rasterize/forward/SHADING_SCENE_RESOURCE_GROUP.js +17 -0
  30. package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_brick4.d.ts +1 -1
  31. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -0
  32. package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_brick4.js +16 -16
  33. package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_ibl.d.ts +1 -1
  34. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -0
  35. package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_forward_shade_standard_fragment_ibl.js +17 -17
  36. package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_material_side_should_draw.d.ts +1 -1
  37. package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.d.ts.map +1 -0
  38. package/src/shade/renderer/rasterize/{native/oit → forward}/chunk_material_side_should_draw.js +2 -2
  39. package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts +3 -0
  40. package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts.map +1 -0
  41. package/src/shade/renderer/rasterize/{native/oit → forward}/vertex_shader_chunk.js +4 -4
  42. package/src/shade/renderer/rasterize/native/avboit/AVBOITSettings.d.ts +27 -0
  43. package/src/shade/renderer/rasterize/native/avboit/AVBOITSettings.d.ts.map +1 -0
  44. package/src/shade/renderer/rasterize/native/avboit/AVBOITSettings.js +27 -0
  45. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.d.ts +107 -0
  46. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.d.ts.map +1 -0
  47. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_CONSTANTS.js +120 -0
  48. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +463 -0
  49. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +509 -0
  50. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_WARP_STRUCT.d.ts +15 -0
  51. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_WARP_STRUCT.d.ts.map +1 -0
  52. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_WARP_STRUCT.js +33 -0
  53. package/src/shade/renderer/rasterize/native/avboit/avboit_build_depth_curve.d.ts +20 -0
  54. package/src/shade/renderer/rasterize/native/avboit/avboit_build_depth_curve.d.ts.map +1 -0
  55. package/src/shade/renderer/rasterize/native/avboit/avboit_build_depth_curve.js +38 -0
  56. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts +38 -0
  57. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts.map +1 -0
  58. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.js +130 -0
  59. package/src/shade/renderer/rasterize/native/avboit/avboit_spec_support.d.ts +37 -0
  60. package/src/shade/renderer/rasterize/native/avboit/avboit_spec_support.d.ts.map +1 -0
  61. package/src/shade/renderer/rasterize/native/avboit/avboit_spec_support.js +73 -0
  62. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.d.ts +9 -0
  63. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.d.ts.map +1 -0
  64. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_counts_to_extinction.js +17 -0
  65. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_dilate_word.d.ts +11 -0
  66. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_dilate_word.d.ts.map +1 -0
  67. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_dilate_word.js +18 -0
  68. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_counts.d.ts +9 -0
  69. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_counts.d.ts.map +1 -0
  70. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_counts.js +17 -0
  71. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_transmittance.d.ts +9 -0
  72. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_transmittance.d.ts.map +1 -0
  73. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_extinction_to_transmittance.js +17 -0
  74. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_fold_pairs.d.ts +15 -0
  75. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_fold_pairs.d.ts.map +1 -0
  76. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_fold_pairs.js +25 -0
  77. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_integral_depth_coordinate.d.ts +17 -0
  78. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_integral_depth_coordinate.d.ts.map +1 -0
  79. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_integral_depth_coordinate.js +35 -0
  80. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_range.d.ts +11 -0
  81. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_range.d.ts.map +1 -0
  82. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_range.js +21 -0
  83. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_word_mask.d.ts +9 -0
  84. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_word_mask.d.ts.map +1 -0
  85. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_occupancy_word_mask.js +26 -0
  86. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_overflows.d.ts +11 -0
  87. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_overflows.d.ts.map +1 -0
  88. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_overflows.js +22 -0
  89. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_pack_counts.d.ts +10 -0
  90. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_pack_counts.d.ts.map +1 -0
  91. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_pack_counts.js +21 -0
  92. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_sample_transmittance.d.ts +10 -0
  93. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_sample_transmittance.d.ts.map +1 -0
  94. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_sample_transmittance.js +32 -0
  95. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmission_tint.d.ts +20 -0
  96. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmission_tint.d.ts.map +1 -0
  97. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmission_tint.js +27 -0
  98. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmittance_to_extinction.d.ts +10 -0
  99. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmittance_to_extinction.d.ts.map +1 -0
  100. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_transmittance_to_extinction.js +18 -0
  101. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unpack_counts.d.ts +9 -0
  102. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unpack_counts.d.ts.map +1 -0
  103. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unpack_counts.js +21 -0
  104. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_physical.d.ts +9 -0
  105. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_physical.d.ts.map +1 -0
  106. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_physical.js +23 -0
  107. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_virtual.d.ts +13 -0
  108. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_virtual.d.ts.map +1 -0
  109. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_view_depth_to_virtual.js +27 -0
  110. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_warp.d.ts +22 -0
  111. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_warp.d.ts.map +1 -0
  112. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_warp.js +38 -0
  113. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +117 -0
  114. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -0
  115. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +935 -0
  116. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.d.ts +8 -0
  117. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.d.ts.map +1 -0
  118. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.js +135 -0
  119. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts +3 -0
  120. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts.map +1 -0
  121. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.js +101 -0
  122. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts +3 -0
  123. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts.map +1 -0
  124. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.js +96 -0
  125. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.d.ts +3 -0
  126. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.d.ts.map +1 -0
  127. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.js +83 -0
  128. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.d.ts +9 -0
  129. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.d.ts.map +1 -0
  130. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.js +119 -0
  131. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.d.ts +3 -0
  132. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.d.ts.map +1 -0
  133. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.js +81 -0
  134. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts +15 -0
  135. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts.map +1 -0
  136. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js +237 -0
  137. package/src/shade/renderer/rasterize/native/material_draw_indirect.d.ts +22 -0
  138. package/src/shade/renderer/rasterize/native/material_draw_indirect.d.ts.map +1 -0
  139. package/src/shade/renderer/rasterize/native/material_draw_indirect.js +69 -0
  140. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
  141. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +665 -722
  142. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +3 -3
  143. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +4 -4
  144. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +4 -4
  145. package/src/shade/renderer/rasterize/native/oit/FORWARD_VERTEX_SHADER_STRUCT.d.ts +0 -3
  146. package/src/shade/renderer/rasterize/native/oit/FORWARD_VERTEX_SHADER_STRUCT.d.ts.map +0 -1
  147. package/src/shade/renderer/rasterize/native/oit/SHADING_SCENE_RESOURCE_GROUP.d.ts +0 -3
  148. package/src/shade/renderer/rasterize/native/oit/SHADING_SCENE_RESOURCE_GROUP.d.ts.map +0 -1
  149. package/src/shade/renderer/rasterize/native/oit/SHADING_SCENE_RESOURCE_GROUP.js +0 -17
  150. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +0 -1
  151. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +0 -1
  152. package/src/shade/renderer/rasterize/native/oit/chunk_material_side_should_draw.d.ts.map +0 -1
  153. package/src/shade/renderer/rasterize/native/oit/vertex_shader_chunk.d.ts +0 -3
  154. package/src/shade/renderer/rasterize/native/oit/vertex_shader_chunk.d.ts.map +0 -1
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Per-frame inputs of the warp build, all of which land in the warp header.
3
+ */
4
+ export const AVBOIT_BUILD_WARP_SETTINGS_STRUCT: WebGPUStruct;
5
+ export const shader_avboit_build_warp: ComputeShader;
6
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
7
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
8
+ //# sourceMappingURL=shader_avboit_build_warp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_build_warp.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_build_warp.js"],"names":[],"mappings":"AAWA;;GAEG;AACH,6DAUqC;AA0GrC,qDAIG;6BApI0B,sCAAsC;8BAErC,kCAAkC"}
@@ -0,0 +1,135 @@
1
+ import { u32, vec3f } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
3
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
4
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
5
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
6
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { AVBOIT_OCCUPANCY_WORDS, AVBOIT_VIRTUAL_SLICES_MAX } from "./AVBOIT_CONSTANTS.js";
8
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
9
+ import { chunk_avboit_dilate_word } from "./chunk_avboit_dilate_word.js";
10
+ import { chunk_avboit_fold_pairs } from "./chunk_avboit_fold_pairs.js";
11
+
12
+ /**
13
+ * Per-frame inputs of the warp build, all of which land in the warp header.
14
+ */
15
+ export const AVBOIT_BUILD_WARP_SETTINGS_STRUCT = WebGPUStruct.from({
16
+ /** AVBOIT_PHYSICAL_SLICES */
17
+ physical_count: u32,
18
+ /** extinction volume XY resolution, copied into the warp header for the fragment shaders */
19
+ voxel_width: u32,
20
+ voxel_height: u32,
21
+ /** AVBOITSettings.transmission_tint_from_base_color as 0 / 1, copied into the header */
22
+ tint_from_base_color: u32,
23
+ /** the depth curve, see avboit_build_depth_curve */
24
+ cluster_parameters: vec3f,
25
+ }, "AVBOITBuildWarpSettings").pack();
26
+
27
+ const resources = new ShaderResourceSetDescriptor();
28
+
29
+ resources.createGroup()
30
+ .addUniform("settings", AVBOIT_BUILD_WARP_SETTINGS_STRUCT)
31
+ .addStorageBuffer("occupancy", WebGPUArray.from(u32, AVBOIT_OCCUPANCY_WORDS))
32
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT, true)
33
+ ;
34
+
35
+ /**
36
+ * AVBOIT warp build: turns the finest-level occupancy bits into the depth-warp LUT (plan §3.4).
37
+ *
38
+ * One invocation does the whole thing. Per level: dilate by one slice each side at that level,
39
+ * count; if the count fits the physical budget, or the level is already down at the physical count,
40
+ * stop — otherwise halve the *undilated* bits by OR-ing adjacent pairs and go again. Dilation is
41
+ * applied fresh at each level rather than once at the finest, because a one-slice margin at 1024
42
+ * slices is a quarter of a slice at 256 and rounds away; the margin is what keeps a fragment on the
43
+ * edge of a meshlet's bounds from linear-splatting into a neighbouring run.
44
+ *
45
+ * The LUT is then an exclusive prefix count of the dilated bits, with the bit itself in the low
46
+ * position — see `AVBOIT_WARP_STRUCT`.
47
+ *
48
+ * Single-lane by design, not as a fallback: 32 words and at most three halvings is a few thousand
49
+ * bit operations, and staying single-lane is what lets the WGSL emulator run this shader as-is.
50
+ */
51
+ const body = CodeChunk.from(
52
+ //language=WGSL
53
+ `
54
+ const AVBOIT_OCCUPANCY_WORDS: u32 = ${AVBOIT_OCCUPANCY_WORDS}u;
55
+
56
+ @compute @workgroup_size(1)
57
+ fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
58
+
59
+ if (global_id.x != 0u) {
60
+ return;
61
+ }
62
+
63
+ let physical = settings.physical_count;
64
+
65
+ var words: array<u32, AVBOIT_OCCUPANCY_WORDS>;
66
+ var dilated: array<u32, AVBOIT_OCCUPANCY_WORDS>;
67
+
68
+ for (var w = 0u; w < AVBOIT_OCCUPANCY_WORDS; w++) {
69
+ words[w] = occupancy[w];
70
+ dilated[w] = 0u;
71
+ }
72
+
73
+ var level_count = ${AVBOIT_VIRTUAL_SLICES_MAX}u;
74
+ var word_count = AVBOIT_OCCUPANCY_WORDS;
75
+
76
+ loop {
77
+ var occupied = 0u;
78
+
79
+ for (var w = 0u; w < word_count; w++) {
80
+ var below = 0u;
81
+ if (w > 0u) {
82
+ below = words[w - 1u] >> 31u;
83
+ }
84
+ var above = 0u;
85
+ if (w + 1u < word_count) {
86
+ above = (words[w + 1u] & 1u) << 31u;
87
+ }
88
+ let d = avboit_dilate_word(words[w], below, above);
89
+ dilated[w] = d;
90
+ occupied += countOneBits(d);
91
+ }
92
+
93
+ if (occupied <= physical || level_count <= physical) {
94
+ break;
95
+ }
96
+
97
+ // halve: two old words become one new word
98
+ let half_words = word_count / 2u;
99
+ for (var nw = 0u; nw < half_words; nw++) {
100
+ words[nw] = avboit_fold_pairs(words[2u * nw]) | (avboit_fold_pairs(words[2u * nw + 1u]) << 16u);
101
+ }
102
+
103
+ word_count = half_words;
104
+ level_count = level_count / 2u;
105
+ }
106
+
107
+ warp.virtual_count = level_count;
108
+ warp.physical_count = physical;
109
+ warp.voxel_width = settings.voxel_width;
110
+ warp.voxel_height = settings.voxel_height;
111
+ warp.tint_from_base_color = settings.tint_from_base_color;
112
+ warp.cluster_parameters = settings.cluster_parameters;
113
+
114
+ var prefix = 0u;
115
+
116
+ for (var v = 0u; v < level_count; v++) {
117
+ let bit = (dilated[v >> 5u] >> (v & 31u)) & 1u;
118
+ warp.lut[v] = (prefix << 1u) | bit;
119
+ prefix += bit;
120
+ }
121
+
122
+ warp.lut[level_count] = prefix << 1u;
123
+ warp.occupied_count = prefix;
124
+ }
125
+ `, [
126
+ chunk_avboit_dilate_word,
127
+ chunk_avboit_fold_pairs,
128
+ ]
129
+ );
130
+
131
+ export const shader_avboit_build_warp = ComputeShader.from({
132
+ label: 'AVBOIT / build warp',
133
+ resources,
134
+ body,
135
+ });
@@ -0,0 +1,3 @@
1
+ export const shader_avboit_draw_brick4: RenderPassDescriptor;
2
+ import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
3
+ //# sourceMappingURL=shader_avboit_draw_brick4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_draw_brick4.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.js"],"names":[],"mappings":"AA2FA,6DAAoE;qCAnF/B,8CAA8C"}
@@ -0,0 +1,101 @@
1
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
2
+ import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
3
+ import { SHADING_LIGHT_RESOURCE_GROUP } from "../../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js";
4
+ import { DEPTH_BACKGROUND_VALUE } from "../../../depth/DEPTH_BACKGROUND_VALUE.js";
5
+ import { BRICK4_DATA_STRUCT } from "../../../global_illumination/brick4/gpu/BRICK4_DATA_STRUCT.js";
6
+ import { SHADING_MATERIAL_RESOURCE_GROUP } from "../../../material/standard/SHADING_MATERIAL_RESOURCE_GROUP.js";
7
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
8
+ import { RenderPassColorAttachmentDescriptor } from "../../../shader/pass/RenderPassColorAttachmentDescriptor.js";
9
+ import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
10
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
11
+ import { ShaderDescriptor } from "../../../shader/ShaderDescriptor.js";
12
+ import { SAMPLER_LINEAR_UPSCALE } from "../../../texture/SAMPLER_LINEAR_UPSCALE.js";
13
+ import { VIEW_UNIFORM_STRUCT } from "../../../view/VIEW_UNIFORM_STRUCT.js";
14
+ import { VOLUMETRICS_METADATA_STRUCT } from "../../../volumetrics/VOLUMETRICS_METADATA_STRUCT.js";
15
+ import {
16
+ chunk_forward_shade_standard_fragment_brick4
17
+ } from "../../forward/chunk_forward_shade_standard_fragment_brick4.js";
18
+ import { SHADING_SCENE_RESOURCE_GROUP } from "../../forward/SHADING_SCENE_RESOURCE_GROUP.js";
19
+ import { vertex_shader_chunk } from "../../forward/vertex_shader_chunk.js";
20
+ import { rasterization_primitive_state } from "../rasterization_primitive_state.js";
21
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
22
+ import {
23
+ AVBOIT_DRAW_FRAGMENT_BODY,
24
+ AVBOIT_DRAW_FRAGMENT_DEPENDENCIES,
25
+ AVBOIT_DRAW_TARGETS
26
+ } from "./avboit_draw_fragment_body.js";
27
+
28
+ const resources = new ShaderResourceSetDescriptor();
29
+
30
+ resources.addGroup(SHADING_MATERIAL_RESOURCE_GROUP);
31
+ resources.addGroup(SHADING_SCENE_RESOURCE_GROUP);
32
+
33
+ // Order is load-bearing: the orchestrator's view bind group lists its entries in this sequence.
34
+ // Identical to the IBL variant except for the brick4 buffer after the integral sampler.
35
+ resources.createGroup()
36
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
37
+ .addUniform("view", VIEW_UNIFORM_STRUCT)
38
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
39
+ // sampled through sLinear below: linear, clamped on every axis, which is what the integral needs
40
+ .addTexture("tIntegral", "float", "3d")
41
+ .addStorageBuffer("brick4", BRICK4_DATA_STRUCT, false)
42
+ .addTexture("tSplitSum", "float")
43
+ .addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
44
+ // volumetrics (composited inline)
45
+ .addUniform("volumetrics_metadata", VOLUMETRICS_METADATA_STRUCT)
46
+ .addTexture("tVolumetrics", "float", "3d")
47
+ .addTexture("tSTBN_vec3", "float", "3d")
48
+
49
+ resources.addGroup(SHADING_LIGHT_RESOURCE_GROUP);
50
+
51
+ const shader_vertex = ShaderDescriptor.from({
52
+ label: 'AVBOIT Brick4 / vertex shader',
53
+ body: vertex_shader_chunk,
54
+ resources,
55
+ });
56
+
57
+ /**
58
+ * AVBOIT draw, Brick4 (sparse volumetric lightmap) indirect lighting. See `avboit_draw_fragment_body.js`.
59
+ */
60
+ const shader_fragment = ShaderDescriptor.from({
61
+ label: "AVBOIT Brick4 / draw",
62
+ resources,
63
+ body: CodeChunk.from(AVBOIT_DRAW_FRAGMENT_BODY, [
64
+ ...AVBOIT_DRAW_FRAGMENT_DEPENDENCIES,
65
+ chunk_forward_shade_standard_fragment_brick4,
66
+ ])
67
+ });
68
+
69
+ const pipeline = RenderPipelineDescriptor.from({
70
+ label: "AVBOIT Brick4 / draw",
71
+ layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
72
+ vertex: {
73
+ module: {
74
+ code: shader_vertex.source
75
+ }
76
+ },
77
+ fragment: {
78
+ module: {
79
+ code: shader_fragment.source
80
+ },
81
+ targets: AVBOIT_DRAW_TARGETS,
82
+ },
83
+ depthStencil: {
84
+ // reversed Z
85
+ depthCompare: "greater",
86
+ format: "depth32float",
87
+ depthWriteEnabled: false
88
+ },
89
+ primitive: rasterization_primitive_state,
90
+ });
91
+
92
+ export const shader_avboit_draw_brick4 = new RenderPassDescriptor();
93
+ shader_avboit_draw_brick4.pipeline = pipeline;
94
+ shader_avboit_draw_brick4.resources = resources;
95
+ shader_avboit_draw_brick4.colorAttachments = AVBOIT_DRAW_TARGETS.map(() => RenderPassColorAttachmentDescriptor.from({
96
+ clearValue: [0, 0, 0, 0],
97
+ }));
98
+ /**
99
+ * Clear depth to 0 for reverse Z technique
100
+ */
101
+ shader_avboit_draw_brick4.depthStencilAttachment.depthClearValue = DEPTH_BACKGROUND_VALUE;
@@ -0,0 +1,3 @@
1
+ export const shader_avboit_draw_ibl: RenderPassDescriptor;
2
+ import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
3
+ //# sourceMappingURL=shader_avboit_draw_ibl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_draw_ibl.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.js"],"names":[],"mappings":"AAsFA,0DAAiE;qCA/E5B,8CAA8C"}
@@ -0,0 +1,96 @@
1
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
2
+ import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
3
+ import { SHADING_LIGHT_RESOURCE_GROUP } from "../../../deferred/SHADING_LIGHT_RESOURCE_GROUP.js";
4
+ import { DEPTH_BACKGROUND_VALUE } from "../../../depth/DEPTH_BACKGROUND_VALUE.js";
5
+ import { SHADING_MATERIAL_RESOURCE_GROUP } from "../../../material/standard/SHADING_MATERIAL_RESOURCE_GROUP.js";
6
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
7
+ import { RenderPassColorAttachmentDescriptor } from "../../../shader/pass/RenderPassColorAttachmentDescriptor.js";
8
+ import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
9
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
10
+ import { ShaderDescriptor } from "../../../shader/ShaderDescriptor.js";
11
+ import { SAMPLER_LINEAR_UPSCALE } from "../../../texture/SAMPLER_LINEAR_UPSCALE.js";
12
+ import { VIEW_UNIFORM_STRUCT } from "../../../view/VIEW_UNIFORM_STRUCT.js";
13
+ import { VOLUMETRICS_METADATA_STRUCT } from "../../../volumetrics/VOLUMETRICS_METADATA_STRUCT.js";
14
+ import { chunk_forward_shade_standard_fragment_ibl } from "../../forward/chunk_forward_shade_standard_fragment_ibl.js";
15
+ import { SHADING_SCENE_RESOURCE_GROUP } from "../../forward/SHADING_SCENE_RESOURCE_GROUP.js";
16
+ import { vertex_shader_chunk } from "../../forward/vertex_shader_chunk.js";
17
+ import { rasterization_primitive_state } from "../rasterization_primitive_state.js";
18
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
19
+ import {
20
+ AVBOIT_DRAW_FRAGMENT_BODY,
21
+ AVBOIT_DRAW_FRAGMENT_DEPENDENCIES,
22
+ AVBOIT_DRAW_TARGETS
23
+ } from "./avboit_draw_fragment_body.js";
24
+
25
+ const resources = new ShaderResourceSetDescriptor();
26
+
27
+ resources.addGroup(SHADING_MATERIAL_RESOURCE_GROUP);
28
+ resources.addGroup(SHADING_SCENE_RESOURCE_GROUP);
29
+
30
+ // Order is load-bearing: the orchestrator's view bind group lists its entries in this sequence.
31
+ resources.createGroup()
32
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
33
+ .addUniform("view", VIEW_UNIFORM_STRUCT)
34
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
35
+ // sampled through sLinear below: linear, clamped on every axis, which is what the integral needs
36
+ .addTexture("tIntegral", "float", "3d")
37
+ .addTexture("tSplitSum", "float")
38
+ .addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
39
+ // volumetrics (composited inline)
40
+ .addUniform("volumetrics_metadata", VOLUMETRICS_METADATA_STRUCT)
41
+ .addTexture("tVolumetrics", "float", "3d")
42
+ .addTexture("tSTBN_vec3", "float", "3d")
43
+
44
+ resources.addGroup(SHADING_LIGHT_RESOURCE_GROUP);
45
+
46
+ const shader_vertex = ShaderDescriptor.from({
47
+ label: 'AVBOIT IBL / vertex shader',
48
+ body: vertex_shader_chunk,
49
+ resources,
50
+ });
51
+
52
+ /**
53
+ * AVBOIT draw, image-based indirect lighting. See `avboit_draw_fragment_body.js`.
54
+ */
55
+ const shader_fragment = ShaderDescriptor.from({
56
+ label: "AVBOIT IBL / draw",
57
+ resources,
58
+ body: CodeChunk.from(AVBOIT_DRAW_FRAGMENT_BODY, [
59
+ ...AVBOIT_DRAW_FRAGMENT_DEPENDENCIES,
60
+ chunk_forward_shade_standard_fragment_ibl,
61
+ ])
62
+ });
63
+
64
+ const pipeline = RenderPipelineDescriptor.from({
65
+ label: "AVBOIT IBL / draw",
66
+ layout: resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
67
+ vertex: {
68
+ module: {
69
+ code: shader_vertex.source
70
+ }
71
+ },
72
+ fragment: {
73
+ module: {
74
+ code: shader_fragment.source
75
+ },
76
+ targets: AVBOIT_DRAW_TARGETS,
77
+ },
78
+ depthStencil: {
79
+ // reversed Z
80
+ depthCompare: "greater",
81
+ format: "depth32float",
82
+ depthWriteEnabled: false
83
+ },
84
+ primitive: rasterization_primitive_state,
85
+ });
86
+
87
+ export const shader_avboit_draw_ibl = new RenderPassDescriptor();
88
+ shader_avboit_draw_ibl.pipeline = pipeline;
89
+ shader_avboit_draw_ibl.resources = resources;
90
+ shader_avboit_draw_ibl.colorAttachments = AVBOIT_DRAW_TARGETS.map(() => RenderPassColorAttachmentDescriptor.from({
91
+ clearValue: [0, 0, 0, 0],
92
+ }));
93
+ /**
94
+ * Clear depth to 0 for reverse Z technique
95
+ */
96
+ shader_avboit_draw_ibl.depthStencilAttachment.depthClearValue = DEPTH_BACKGROUND_VALUE;
@@ -0,0 +1,3 @@
1
+ export const shader_avboit_integrate: ComputeShader;
2
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
3
+ //# sourceMappingURL=shader_avboit_integrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_integrate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_integrate.js"],"names":[],"mappings":"AA8EA,oDAIG;8BA/E2B,kCAAkC"}
@@ -0,0 +1,83 @@
1
+ import { u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
3
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
4
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
5
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
6
+ import { AVBOIT_INTEGRAL_FORMAT, AVBOIT_INTEGRATE_WORKGROUP_SIZE } from "./AVBOIT_CONSTANTS.js";
7
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
8
+ import { chunk_avboit_counts_to_extinction } from "./chunk_avboit_counts_to_extinction.js";
9
+ import { chunk_avboit_unpack_counts } from "./chunk_avboit_unpack_counts.js";
10
+
11
+ const resources = new ShaderResourceSetDescriptor();
12
+
13
+ resources.createGroup()
14
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
15
+ .addStorageBuffer("extinction_volume", WebGPUArray.from(u32))
16
+ .addStorageBuffer("overflow_slice", WebGPUArray.from(u32))
17
+ .addStorageTexture("integral", AVBOIT_INTEGRAL_FORMAT, "3d", "write-only")
18
+ ;
19
+
20
+ /**
21
+ * AVBOIT integration: one thread per voxel column, summing extinction front to back into the 3D
22
+ * integral texture (plan §3.6).
23
+ *
24
+ * Exclusive prefix: texel `s` holds the integral at the *near boundary* of slice `s`, and the texture
25
+ * has `P + 1` depth texels so that texel `P` holds the total. That convention is what lets a sample
26
+ * that the warp has snapped to a run boundary read exactly the runs in front of it.
27
+ *
28
+ * Per channel, the running value saturates at 1.0 (a transmittance of `1/256`), and from the slice
29
+ * the splat recorded as that channel's first overflow it is pinned there: the packed field may have
30
+ * wrapped past that point and its contents no longer mean anything, but a ray that has overflowed
31
+ * a field is extinct anyway.
32
+ */
33
+ const body = CodeChunk.from(
34
+ //language=WGSL
35
+ `
36
+ @compute @workgroup_size(${AVBOIT_INTEGRATE_WORKGROUP_SIZE}, ${AVBOIT_INTEGRATE_WORKGROUP_SIZE}, 1)
37
+ fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
38
+
39
+ let width = warp.voxel_width;
40
+ let height = warp.voxel_height;
41
+
42
+ if (global_id.x >= width || global_id.y >= height) {
43
+ return;
44
+ }
45
+
46
+ let physical = warp.physical_count;
47
+ let texel = global_id.y * width + global_id.x;
48
+ let column = texel * physical;
49
+ let overflow_base = texel * 3u;
50
+
51
+ // first overflow slice per channel; a zero mark means none, which no slice reaches
52
+ let marks = vec3<u32>(
53
+ overflow_slice[overflow_base],
54
+ overflow_slice[overflow_base + 1u],
55
+ overflow_slice[overflow_base + 2u],
56
+ );
57
+ let stop = select(vec3<u32>(physical) - marks, vec3<u32>(physical), marks == vec3<u32>(0u));
58
+
59
+ var accumulated = vec3<f32>(0.0);
60
+
61
+ for (var s = 0u; s < physical; s++) {
62
+ textureStore(integral, vec3<i32>(i32(global_id.x), i32(global_id.y), i32(s)), vec4<f32>(accumulated, 1.0));
63
+
64
+ let counts = avboit_unpack_counts(extinction_volume[column + s]);
65
+ let extinction = avboit_counts_to_extinction(counts);
66
+
67
+ let pinned = vec3<u32>(s) >= stop;
68
+ accumulated = select(min(accumulated + extinction, vec3<f32>(1.0)), vec3<f32>(1.0), pinned);
69
+ }
70
+
71
+ textureStore(integral, vec3<i32>(i32(global_id.x), i32(global_id.y), i32(physical)), vec4<f32>(accumulated, 1.0));
72
+ }
73
+ `, [
74
+ chunk_avboit_counts_to_extinction,
75
+ chunk_avboit_unpack_counts,
76
+ ]
77
+ );
78
+
79
+ export const shader_avboit_integrate = ComputeShader.from({
80
+ label: 'AVBOIT / integrate',
81
+ resources,
82
+ body,
83
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The depth curve, built by `avboit_build_depth_curve`; the same values the warp header carries,
3
+ * needed here before the header exists.
4
+ */
5
+ export const AVBOIT_OCCUPANCY_SETTINGS_STRUCT: WebGPUStruct;
6
+ export const shader_avboit_occupancy: ComputeShader;
7
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
8
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
9
+ //# sourceMappingURL=shader_avboit_occupancy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_occupancy.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_occupancy.js"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,4DAEqC;AAyFrC,oDAIG;6BApH0B,sCAAsC;8BAUrC,kCAAkC"}
@@ -0,0 +1,119 @@
1
+ import { atomic_u32, u32, vec3f } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
3
+ import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
4
+ import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
5
+ import { chunk_cluster_depth_to_z_slice } from "../../../light/cluster/chunk_cluster_depth_to_z_slice.js";
6
+ import { MESHLET_METADATA_STRUCT } from "../../../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
7
+ import { chunk_scene_database_access } from "../../../scene/chunk_scene_database_access.js";
8
+ import { AABB3_STRUCT } from "../../../shader/chunk/geometry/aabb3/AABB3_STRUCT.js";
9
+ import { chunk_aabb3_project } from "../../../shader/chunk/geometry/aabb3/chunk_aabb3_project.js";
10
+ import { chunk_array_to_aabb3 } from "../../../shader/chunk/geometry/aabb3/chunk_array_to_aabb3.js";
11
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
12
+ import { COMPUTE_SHADER_DEFAULT_GROUP_SIZE } from "../../../shader/COMPUTE_SHADER_DEFAULT_GROUP_SIZE.js";
13
+ import { ComputeShader } from "../../../shader/ComputeShader.js";
14
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
15
+ import { MESHLET_COLLECTION_STRUCT } from "../../MESHLET_COLLECTION_STRUCT.js";
16
+ import { AVBOIT_OCCUPANCY_WORDS, AVBOIT_VIRTUAL_SLICES_MAX } from "./AVBOIT_CONSTANTS.js";
17
+ import { chunk_avboit_occupancy_range } from "./chunk_avboit_occupancy_range.js";
18
+ import { chunk_avboit_occupancy_word_mask } from "./chunk_avboit_occupancy_word_mask.js";
19
+
20
+ /**
21
+ * The depth curve, built by `avboit_build_depth_curve`; the same values the warp header carries,
22
+ * needed here before the header exists.
23
+ */
24
+ export const AVBOIT_OCCUPANCY_SETTINGS_STRUCT = WebGPUStruct.from({
25
+ cluster_parameters: vec3f,
26
+ }, "AVBOITOccupancySettings").pack();
27
+
28
+ const resources = new ShaderResourceSetDescriptor();
29
+
30
+ resources.createGroup()
31
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
32
+ .addUniform("settings", AVBOIT_OCCUPANCY_SETTINGS_STRUCT)
33
+ .addStorageBuffer("scene_database", WebGPUArray.from(u32))
34
+ .addStorageBuffer("meshlet_metadata", WebGPUArray.from(MESHLET_METADATA_STRUCT))
35
+ ;
36
+
37
+ resources.createGroup()
38
+ .addStorageBuffer("input", MESHLET_COLLECTION_STRUCT)
39
+ ;
40
+
41
+ resources.createGroup()
42
+ .addStorageBuffer("occupancy", WebGPUArray.from(atomic_u32, AVBOIT_OCCUPANCY_WORDS), true)
43
+ ;
44
+
45
+ /**
46
+ * AVBOIT occupancy prepass: one thread per HZB-surviving meshlet, marking the virtual depth slices its
47
+ * bounds span. The deck voxelizes quads and boxes conservatively in a compute job (slide 75); the
48
+ * engine already has per-meshlet AABBs on the GPU, which are tighter than a mesh box and free.
49
+ *
50
+ * Bounds go local → world → view through `aabb3_project` twice, the same projection the HZB meshlet
51
+ * filter uses. The camera looks down −Z, so the view-space depth interval is `[-max.z, -min.z]`.
52
+ * A meshlet entirely in front of the near plane marks nothing; anything else goes through the depth
53
+ * curve (`cluster_depth_to_z_slice`, clamped to the volume by its own limit) and is dilated one slice
54
+ * each side (`avboit_occupancy_range`).
55
+ *
56
+ * Runs once per transparent bucket (front-sided, double-sided) into the same word array.
57
+ */
58
+ const body = CodeChunk.from(
59
+ //language=WGSL
60
+ `
61
+ @compute @workgroup_size(${COMPUTE_SHADER_DEFAULT_GROUP_SIZE})
62
+ fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
63
+
64
+ let input_index = global_id.x;
65
+
66
+ if (input_index >= input.count) {
67
+ return;
68
+ }
69
+
70
+ let meshlet = input.elements[input_index];
71
+
72
+ let mesh = scene_read_mesh(&scene_database, meshlet.mesh);
73
+ let node = scene_read_node(&scene_database, mesh.node);
74
+
75
+ let local_bounds = array_to_aabb3(meshlet_metadata[meshlet.index].bounds_box);
76
+ let world_bounds = aabb3_project(local_bounds, node.global);
77
+ let view_bounds: ${AABB3_STRUCT.wgsl_ref} = aabb3_project(world_bounds, camera.view_matrix);
78
+
79
+ // camera looks down -Z: the nearest point of the box has the largest z
80
+ let depth_min = -view_bounds.max.z;
81
+ let depth_max = -view_bounds.min.z;
82
+
83
+ if (depth_max < camera.clip_near_far.x) {
84
+ // entirely in front of the near plane
85
+ return;
86
+ }
87
+
88
+ let limit = ${AVBOIT_VIRTUAL_SLICES_MAX}.0;
89
+ let slice_near = cluster_depth_to_z_slice(depth_min, settings.cluster_parameters, limit);
90
+ let slice_far = cluster_depth_to_z_slice(depth_max, settings.cluster_parameters, limit);
91
+
92
+ let range = avboit_occupancy_range(slice_near, slice_far);
93
+
94
+ let word_first = u32(range.x) >> 5u;
95
+ let word_last = u32(range.y) >> 5u;
96
+
97
+ for (var word = word_first; word <= word_last; word++) {
98
+ let mask = avboit_occupancy_word_mask(word, range.x, range.y);
99
+ if (mask != 0u) {
100
+ atomicOr(&occupancy[word], mask);
101
+ }
102
+ }
103
+ }
104
+ `, [
105
+ AABB3_STRUCT.declaration_chunk,
106
+ chunk_array_to_aabb3,
107
+ chunk_aabb3_project,
108
+ chunk_scene_database_access,
109
+ chunk_cluster_depth_to_z_slice,
110
+ chunk_avboit_occupancy_range,
111
+ chunk_avboit_occupancy_word_mask,
112
+ ]
113
+ );
114
+
115
+ export const shader_avboit_occupancy = ComputeShader.from({
116
+ label: 'AVBOIT / occupancy',
117
+ resources,
118
+ body,
119
+ });
@@ -0,0 +1,3 @@
1
+ export const shader_avboit_resolve: ImageShader;
2
+ import { ImageShader } from "../../../shader/ImageShader.js";
3
+ //# sourceMappingURL=shader_avboit_resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_resolve.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.js"],"names":[],"mappings":"AAsEA,gDAUE;4BA9E0B,gCAAgC"}