@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,81 @@
1
+ import { chunk_is_nan } from "../../../shader/chunk/math/chunk_is_nan.js";
2
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
3
+ import { ImageShader } from "../../../shader/ImageShader.js";
4
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
5
+ import { ShaderDescriptor } from "../../../shader/ShaderDescriptor.js";
6
+
7
+ const resources = new ShaderResourceSetDescriptor();
8
+ resources.createGroup()
9
+ .addTexture("tScene")
10
+ .addTexture("tColor")
11
+ .addTexture("tNorm")
12
+ .addTexture("tExtinction")
13
+
14
+ /**
15
+ * AVBOIT resolve: composites the three draw accumulators over the scene colour (plan §3.9).
16
+ *
17
+ * Per channel:
18
+ *
19
+ * ```
20
+ * T_total = exp(-Σ extinction)
21
+ * norm = Σ norm > ε ? (1 - T_total) / Σ norm : 0
22
+ * out = scene × T_total + Σ color × norm
23
+ * ```
24
+ *
25
+ * The total transmittance is RGB, which fixed-function blending cannot apply to the destination
26
+ * without dual-source blending, so this reads the scene colour and writes a fresh target rather than
27
+ * blending in place. A NaN in any accumulator drops the transparency for that pixel and keeps the
28
+ * scene, the same backstop the MBOIT blend carries.
29
+ */
30
+ const body = CodeChunk.from(
31
+ //language=WGSL
32
+ `
33
+ @fragment
34
+ fn main(
35
+ @builtin(position) coord: vec4<f32>
36
+ ) -> @location(0) vec4<f32> {
37
+
38
+ let coord_u = vec2<u32>(coord.xy);
39
+
40
+ let scene = textureLoad(tScene, coord_u, 0);
41
+
42
+ let accum_color = textureLoad(tColor, coord_u, 0).rgb;
43
+ let accum_norm = textureLoad(tNorm, coord_u, 0).rgb;
44
+ let accum_extinction = textureLoad(tExtinction, coord_u, 0).rgb;
45
+
46
+ if (is_nan(accum_color.r) || is_nan(accum_norm.r) || is_nan(accum_extinction.r)) {
47
+ // one NaN fragment poisons the whole pixel of an additive accumulator; keeping the opaque
48
+ // scene beats smearing NaN into the frame
49
+ return scene;
50
+ }
51
+
52
+ let total_transmittance = exp(-accum_extinction);
53
+
54
+ // sum of (1 - T_self) * T at each fragment; zero where nothing transparent was drawn
55
+ let safe = accum_norm > vec3<f32>(1e-4);
56
+ let renormalization = select(
57
+ vec3<f32>(0.0),
58
+ (vec3<f32>(1.0) - total_transmittance) / max(accum_norm, vec3<f32>(1e-4)),
59
+ safe
60
+ );
61
+
62
+ let transparent = accum_color * renormalization;
63
+
64
+ return vec4<f32>(scene.rgb * total_transmittance + transparent, scene.a);
65
+ }
66
+ `, [
67
+ chunk_is_nan
68
+ ]
69
+ )
70
+
71
+ export const shader_avboit_resolve = ImageShader.from({
72
+ descriptor: ShaderDescriptor.from({
73
+ label: "AVBOIT / resolve",
74
+ resources,
75
+ body,
76
+ }),
77
+ targets: [{
78
+ label: "AVBOIT composited",
79
+ format: "rgba16float",
80
+ }]
81
+ })
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Bind group index of the atomics the splat writes; the three below it are the rasterization
3
+ * path's fixed material / scene / view slots.
4
+ * @type {number}
5
+ */
6
+ export const AVBOIT_SPLAT_BIND_GROUP_VOLUME: number;
7
+ /**
8
+ * Format of the attachment the splat pass rasterizes against. It is never written (`writeMask: 0`);
9
+ * WebGPU requires at least one attachment and this is the cheapest one.
10
+ * @type {GPUTextureFormat}
11
+ */
12
+ export const AVBOIT_SPLAT_DUMMY_FORMAT: GPUTextureFormat;
13
+ export const shader_avboit_splat: RenderPassDescriptor;
14
+ import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
15
+ //# sourceMappingURL=shader_avboit_splat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_avboit_splat.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH,6CAFU,MAAM,CAEgC;AAEhD;;;;GAIG;AACH,yDAAmD;AA6LnD,uDAA8D;qCAzNzB,8CAA8C"}
@@ -0,0 +1,237 @@
1
+ import { PipelineLayoutDescriptor } from "../../../../descriptor/pipeline/PipelineLayoutDescriptor.js";
2
+ import { RenderPipelineDescriptor } from "../../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
3
+ import { atomic_u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
4
+ import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
5
+ import { CAMERA_UNIFORM_STRUCT } from "../../../camera/CAMERA_UNIFORM_STRUCT.js";
6
+ import { SHADING_MATERIAL_RESOURCE_GROUP } from "../../../material/standard/SHADING_MATERIAL_RESOURCE_GROUP.js";
7
+ import { chunk_F_Hauber } from "../../../shader/chunk/brdf/fresnel/chunk_F_Hauber.js";
8
+ import { chunk_get_view_space_depth } from "../../../shader/chunk/depth/chunk_get_view_space_depth.js";
9
+ import { chunk_mat4_extract_position } from "../../../shader/chunk/geometry/mat4/chunk_mat4_extract_position.js";
10
+ import { chunk_dielectric_specular_color } from "../../../shader/chunk/material/chunk_dielectric_specular_color.js";
11
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
12
+ import { RenderPassColorAttachmentDescriptor } from "../../../shader/pass/RenderPassColorAttachmentDescriptor.js";
13
+ import { RenderPassDescriptor } from "../../../shader/pass/RenderPassDescriptor.js";
14
+ import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
15
+ import { ShaderDescriptor } from "../../../shader/ShaderDescriptor.js";
16
+ import { FORWARD_VERTEX_SHADER_STRUCT } from "../../forward/FORWARD_VERTEX_SHADER_STRUCT.js";
17
+ import { SHADING_SCENE_RESOURCE_GROUP } from "../../forward/SHADING_SCENE_RESOURCE_GROUP.js";
18
+ import { vertex_shader_chunk } from "../../forward/vertex_shader_chunk.js";
19
+ import { OIT_COVERAGE_MAX } from "../oit/OIT_CONSTANTS.js";
20
+ import { rasterization_primitive_state } from "../rasterization_primitive_state.js";
21
+ import { AVBOIT_WARP_STRUCT } from "./AVBOIT_WARP_STRUCT.js";
22
+ import { chunk_avboit_extinction_to_counts } from "./chunk_avboit_extinction_to_counts.js";
23
+ import { chunk_avboit_overflows } from "./chunk_avboit_overflows.js";
24
+ import { chunk_avboit_pack_counts } from "./chunk_avboit_pack_counts.js";
25
+ import { chunk_avboit_transmission_tint } from "./chunk_avboit_transmission_tint.js";
26
+ import { chunk_avboit_transmittance_to_extinction } from "./chunk_avboit_transmittance_to_extinction.js";
27
+ import { chunk_avboit_view_depth_to_physical } from "./chunk_avboit_view_depth_to_physical.js";
28
+
29
+ /**
30
+ * Bind group index of the atomics the splat writes; the three below it are the rasterization
31
+ * path's fixed material / scene / view slots.
32
+ * @type {number}
33
+ */
34
+ export const AVBOIT_SPLAT_BIND_GROUP_VOLUME = 3;
35
+
36
+ /**
37
+ * Format of the attachment the splat pass rasterizes against. It is never written (`writeMask: 0`);
38
+ * WebGPU requires at least one attachment and this is the cheapest one.
39
+ * @type {GPUTextureFormat}
40
+ */
41
+ export const AVBOIT_SPLAT_DUMMY_FORMAT = "r8unorm";
42
+
43
+ const resources = new ShaderResourceSetDescriptor();
44
+
45
+ resources.addGroup(SHADING_MATERIAL_RESOURCE_GROUP);
46
+ resources.addGroup(SHADING_SCENE_RESOURCE_GROUP);
47
+
48
+ resources.createGroup()
49
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
50
+ .addStorageBuffer("warp", AVBOIT_WARP_STRUCT)
51
+ ;
52
+
53
+ resources.createGroup()
54
+ .addStorageBuffer("extinction_volume", WebGPUArray.from(atomic_u32), true)
55
+ .addStorageBuffer("overflow_slice", WebGPUArray.from(atomic_u32), true)
56
+ ;
57
+
58
+ const shader_vertex = ShaderDescriptor.from({
59
+ label: 'AVBOIT / splat vertex shader',
60
+ body: vertex_shader_chunk,
61
+ resources,
62
+ });
63
+
64
+ /**
65
+ * AVBOIT splat: rasterizes the transparent buckets at 1/8 resolution and adds each fragment's RGB
66
+ * extinction into the voxel volume with atomics (plan §3.5).
67
+ *
68
+ * Coverage is computed the way `shader_oit_generate_moments` computes it — texture alpha, or the
69
+ * view-angle Fresnel when the material transmits — and then, new to this path, a per-channel
70
+ * self-transmittance: `(1 - coverage) × tint`, with `tint` the base colour weighted by
71
+ * `transmission_factor` — but only while `AVBOITSettings.transmission_tint_from_base_color` is on,
72
+ * which the warp header carries. A plain alpha-blended material lands exactly where it would under
73
+ * MBOIT (`tint = 1`), and so does glass unless the tint is opted into.
74
+ *
75
+ * Depth goes view-space → curve → warp → physical, and the extinction is linear-splat between the
76
+ * two physical slices around it (`c = p - 0.5`) so a surface crossing a slice boundary does not
77
+ * alias. A field that crosses 255 with this add records the slice in the per-channel overflow
78
+ * plane — stored as `P - slice` under `atomicMax`, so the buffer's zero clear reads as "none" and
79
+ * the nearest overflow wins.
80
+ *
81
+ * No depth attachment: a splat behind opaque geometry lies deeper than any visible transparent
82
+ * fragment and the integral at a depth only contains what is in front of it. No TAA un-jitter: the
83
+ * jitter is expressed in internal-resolution pixels and the derivative-based correction would be
84
+ * eight times too large here.
85
+ */
86
+ const fragment_body = CodeChunk.from(
87
+ //language=WGSL
88
+ `
89
+ fn avboit_splat_slice(column: u32, slice: i32, extinction: vec3<f32>, texel: vec2<u32>) {
90
+ let physical = i32(warp.physical_count);
91
+ let s = clamp(slice, 0, physical - 1);
92
+
93
+ let counts = avboit_extinction_to_counts(extinction);
94
+
95
+ if (all(counts == vec3<u32>(0u))) {
96
+ return;
97
+ }
98
+
99
+ let previous = atomicAdd(&extinction_volume[column + u32(s)], avboit_pack_counts(counts));
100
+
101
+ let overflow = avboit_overflows(previous, counts);
102
+
103
+ if (any(overflow)) {
104
+ let base = (texel.y * warp.voxel_width + texel.x) * 3u;
105
+ // inverted so that the zero-cleared buffer means "no overflow" and max keeps the nearest
106
+ let mark = u32(physical - s);
107
+ if (overflow.x) {
108
+ atomicMax(&overflow_slice[base], mark);
109
+ }
110
+ if (overflow.y) {
111
+ atomicMax(&overflow_slice[base + 1u], mark);
112
+ }
113
+ if (overflow.z) {
114
+ atomicMax(&overflow_slice[base + 2u], mark);
115
+ }
116
+ }
117
+ }
118
+
119
+ @fragment
120
+ fn main(
121
+ @builtin(front_facing) front_facing : bool,
122
+ vert: ${FORWARD_VERTEX_SHADER_STRUCT.wgsl_ref},
123
+ ) {
124
+ let uv = vert.uv;
125
+
126
+ let t_diffuse = textureSample(texture_diffuse, texture_diffuse_sampler, uv);
127
+ let surface_alpha = t_diffuse.a * material_info.albedo_color.a;
128
+
129
+ var opacity = surface_alpha;
130
+ var tint = vec3<f32>(1.0);
131
+
132
+ let f_transmission = material_info.transmission_factor;
133
+ if (f_transmission > 0.0) {
134
+ let t_pbr = textureSample(texture_orm, texture_orm_sampler, uv);
135
+ // undo premultiplication; vert.color already carries the material's albedo colour
136
+ let base_color = (t_diffuse.rgb / max(t_diffuse.a, 1e-7)) * vert.color;
137
+ let f_metalness = t_pbr.b * material_info.metallic_factor;
138
+ let specular_f0 = dielectric_specular_color(material_info.ior_factor, f_metalness, base_color);
139
+
140
+ let view_position = mat4_extract_position(camera.transform);
141
+ let view_direction = normalize(view_position - vert.position_ws);
142
+ let nov = saturate(abs(dot(normalize(vert.normal), view_direction)));
143
+ let f_view = F_Hauber(specular_f0, 1.0, nov);
144
+ let f_scalar = max(f_view.r, max(f_view.g, f_view.b));
145
+
146
+ opacity = mix(surface_alpha, f_scalar, f_transmission);
147
+ // what the surface lets through is coloured by what it is made of, when the renderer says
148
+ // so (AVBOITSettings.transmission_tint_from_base_color, carried in the warp header)
149
+ tint = avboit_transmission_tint(base_color, f_transmission * f32(warp.tint_from_base_color));
150
+ }
151
+
152
+ let coverage = min(opacity, ${OIT_COVERAGE_MAX});
153
+ let transmittance = (1.0 - coverage) * tint;
154
+ let extinction = avboit_transmittance_to_extinction(transmittance);
155
+
156
+ // vert.position is @builtin(position): .z is device depth, .xy the low-resolution pixel
157
+ let z_view = get_view_space_depth(vert.position.z, camera);
158
+ let p = avboit_view_depth_to_physical(&warp, z_view);
159
+
160
+ let texel = vec2<u32>(vert.position.xy);
161
+ let column = (texel.y * warp.voxel_width + texel.x) * warp.physical_count;
162
+
163
+ // linear splat between the two slices around the fragment
164
+ let c = p - 0.5;
165
+ let slice = i32(floor(c));
166
+ let fraction = c - floor(c);
167
+
168
+ avboit_splat_slice(column, slice, extinction * (1.0 - fraction), texel);
169
+ avboit_splat_slice(column, slice + 1, extinction * fraction, texel);
170
+ }
171
+ `, [
172
+ FORWARD_VERTEX_SHADER_STRUCT.declaration_chunk,
173
+ chunk_get_view_space_depth,
174
+ chunk_mat4_extract_position,
175
+ chunk_dielectric_specular_color,
176
+ chunk_F_Hauber,
177
+ chunk_avboit_extinction_to_counts,
178
+ chunk_avboit_overflows,
179
+ chunk_avboit_pack_counts,
180
+ chunk_avboit_transmission_tint,
181
+ chunk_avboit_transmittance_to_extinction,
182
+ chunk_avboit_view_depth_to_physical,
183
+ ]
184
+ );
185
+
186
+ const shader_fragment = ShaderDescriptor.from({
187
+ label: "AVBOIT / splat",
188
+ resources,
189
+ body: fragment_body
190
+ });
191
+
192
+ /*
193
+ The pipeline layout is built group by group rather than with `generatePipelineLayout(stage)`, which
194
+ gives every group the same visibility: WebGPU refuses a read-write storage buffer that is visible to
195
+ the vertex stage, and the atomics group is fragment-only. The first three groups keep the
196
+ rasterization path's `VERTEX | FRAGMENT`, which is what the bind groups the orchestrator builds
197
+ against `SHADING_*_RESOURCE_GROUP` are laid out for.
198
+ */
199
+ const groups = resources.groups;
200
+ const layout = PipelineLayoutDescriptor.from([
201
+ groups[0].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
202
+ groups[1].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
203
+ groups[2].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
204
+ groups[AVBOIT_SPLAT_BIND_GROUP_VOLUME].generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT),
205
+ ], resources.immediateSize);
206
+
207
+ const pipeline = RenderPipelineDescriptor.from({
208
+ label: "AVBOIT / splat",
209
+ layout,
210
+ vertex: {
211
+ module: {
212
+ code: shader_vertex.source
213
+ }
214
+ },
215
+ fragment: {
216
+ module: {
217
+ code: shader_fragment.source
218
+ },
219
+ targets: [
220
+ // never written; see AVBOIT_SPLAT_DUMMY_FORMAT
221
+ {
222
+ format: AVBOIT_SPLAT_DUMMY_FORMAT,
223
+ writeMask: 0,
224
+ }
225
+ ]
226
+ },
227
+ primitive: rasterization_primitive_state,
228
+ });
229
+
230
+ export const shader_avboit_splat = new RenderPassDescriptor();
231
+ shader_avboit_splat.pipeline = pipeline;
232
+ shader_avboit_splat.resources = resources;
233
+ shader_avboit_splat.colorAttachments = [
234
+ RenderPassColorAttachmentDescriptor.from({
235
+ clearValue: [0, 0, 0, 0],
236
+ }),
237
+ ];
@@ -0,0 +1,22 @@
1
+ /**
2
+ * One indirect draw per material out of a command buffer built by
3
+ * `graph_prepare_meshlet_draw_commands_by_material`, with the material's bind group at slot 0.
4
+ * Materials whose GPU side is not built yet are skipped. Shared by the MBOIT and AVBOIT
5
+ * orchestrators, which call it once per render pass they record.
6
+ *
7
+ * @param {GPUMaterialManager} material_manager
8
+ * @param {number} material_count
9
+ * @param {ShadeMaterial[]} materials
10
+ * @param {RenderPassDescriptor} render_pass_descriptor its group 0 is the material group
11
+ * @param {BindGroupManager} bind_manager
12
+ * @param {ShadeGPURenderPassEncoder} pass_encoder
13
+ * @param {GPUBuffer} command_buffer_draw one `STRUCT_UNINDEXED_DRAW_COMMAND` per material, in order
14
+ */
15
+ export function material_draw_indirect(material_manager: GPUMaterialManager, material_count: number, materials: ShadeMaterial[], render_pass_descriptor: RenderPassDescriptor, bind_manager: BindGroupManager, pass_encoder: ShadeGPURenderPassEncoder, command_buffer_draw: GPUBuffer): void;
16
+ /**
17
+ * The material bind group layout every transparent draw binds at slot 0; hoisted so it is computed
18
+ * once and so the two transparency pipelines cannot disagree on it.
19
+ * @type {BindGroupLayoutDescriptor}
20
+ */
21
+ export const BIND_GROUP_LAYOUT_MATERIAL: BindGroupLayoutDescriptor;
22
+ //# sourceMappingURL=material_draw_indirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material_draw_indirect.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/rasterize/native/material_draw_indirect.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;GAaG;AACH,6FAPW,MAAM,aACN,eAAe,+JA8CzB;AA7DD;;;;GAIG;AACH,mEAA6J"}
@@ -0,0 +1,69 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { STRUCT_UNINDEXED_DRAW_COMMAND } from "../../gpu_primitive/indirect/STRUCT_UNINDEXED_DRAW_COMMAND.js";
3
+ import { BindGroupDescriptor } from "../../binding/BindGroupDescriptor.js";
4
+ import { SHADING_MATERIAL_RESOURCE_GROUP } from "../../material/standard/SHADING_MATERIAL_RESOURCE_GROUP.js";
5
+
6
+ const DRAW_COMMAND_BYTE_SIZE = STRUCT_UNINDEXED_DRAW_COMMAND.aligned_size;
7
+
8
+ /**
9
+ * The material bind group layout every transparent draw binds at slot 0; hoisted so it is computed
10
+ * once and so the two transparency pipelines cannot disagree on it.
11
+ * @type {BindGroupLayoutDescriptor}
12
+ */
13
+ export const BIND_GROUP_LAYOUT_MATERIAL = SHADING_MATERIAL_RESOURCE_GROUP.generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT | GPUShaderStage.VERTEX);
14
+
15
+ /**
16
+ * One indirect draw per material out of a command buffer built by
17
+ * `graph_prepare_meshlet_draw_commands_by_material`, with the material's bind group at slot 0.
18
+ * Materials whose GPU side is not built yet are skipped. Shared by the MBOIT and AVBOIT
19
+ * orchestrators, which call it once per render pass they record.
20
+ *
21
+ * @param {GPUMaterialManager} material_manager
22
+ * @param {number} material_count
23
+ * @param {ShadeMaterial[]} materials
24
+ * @param {RenderPassDescriptor} render_pass_descriptor its group 0 is the material group
25
+ * @param {BindGroupManager} bind_manager
26
+ * @param {ShadeGPURenderPassEncoder} pass_encoder
27
+ * @param {GPUBuffer} command_buffer_draw one `STRUCT_UNINDEXED_DRAW_COMMAND` per material, in order
28
+ */
29
+ export function material_draw_indirect(
30
+ material_manager,
31
+ material_count,
32
+ materials,
33
+ render_pass_descriptor,
34
+ bind_manager,
35
+ pass_encoder,
36
+ command_buffer_draw
37
+ ) {
38
+
39
+ assert.defined(material_manager, 'material_manager');
40
+ assert.isNonNegativeInteger(material_count, 'material_count');
41
+ assert.isArray(materials, 'materials');
42
+
43
+ for (let i = 0; i < material_count; i++) {
44
+
45
+ const material = materials[i];
46
+ const gpu_material = material_manager.obtain(material);
47
+
48
+ if (!gpu_material.is_built) {
49
+ // skip, not ready for rendering
50
+ continue;
51
+ }
52
+
53
+ const material_resource_group = render_pass_descriptor.resources.groups[0];
54
+ const binding_entries = material_resource_group.generateBindings(gpu_material.binding_data);
55
+ const material_bindings = bind_manager.obtain(BindGroupDescriptor.from(
56
+ BIND_GROUP_LAYOUT_MATERIAL,
57
+ binding_entries
58
+ ));
59
+
60
+ // set material-specific bind group at 0
61
+ pass_encoder.setBindGroup(0, material_bindings)
62
+
63
+ pass_encoder.drawIndirect(
64
+ command_buffer_draw,
65
+ i * DRAW_COMMAND_BYTE_SIZE,
66
+ );
67
+
68
+ }
69
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"graph_rasterize_meshes_transparent_oit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js"],"names":[],"mappings":"AA6dA;;;;;;;;;;;;;;;;GAgBG;AACH,uSAFa,MAAM,CAsOlB"}
1
+ {"version":3,"file":"graph_rasterize_meshes_transparent_oit.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js"],"names":[],"mappings":"AAoaA;;;;;;;;;;;;;;;;GAgBG;AACH,uSAFa,MAAM,CAsOlB"}