@woosh/meep-engine 3.60.5 → 3.60.6

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 (55) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +1 -1
  3. package/src/shade/renderer/Renderer.d.ts +11 -0
  4. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  5. package/src/shade/renderer/Renderer.js +43 -1
  6. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +26 -43
  7. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  8. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +109 -117
  9. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +20 -2
  10. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  11. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +66 -2
  12. package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.d.ts +19 -0
  13. package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.d.ts.map +1 -0
  14. package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.js +25 -0
  15. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +15 -0
  16. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -1
  17. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +38 -0
  18. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +28 -59
  19. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -1
  20. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +84 -789
  21. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +2 -1
  22. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  23. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +2 -1
  24. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -2
  25. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -2
  26. package/src/shade/renderer/material/GPUMaterialManager.d.ts +4 -1
  27. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  28. package/src/shade/renderer/material/GPUMaterialManager.js +5 -8
  29. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +7 -3
  30. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
  31. package/src/shade/renderer/postprocess/gtao/GTAO.js +26 -13
  32. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts +14 -0
  33. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts.map +1 -1
  34. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.js +196 -68
  35. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  36. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +42 -28
  37. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  38. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +429 -414
  39. package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.d.ts +16 -0
  40. package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.d.ts.map +1 -0
  41. package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.js +156 -0
  42. package/src/shade/renderer/scene/GPUSceneContext.d.ts +2 -2
  43. package/src/shade/renderer/scene/GPUSceneContext.js +5 -5
  44. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +0 -47
  45. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +0 -1
  46. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +0 -80
  47. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +0 -16
  48. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +0 -1
  49. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +0 -67
  50. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +0 -17
  51. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +0 -1
  52. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +0 -145
  53. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +0 -12
  54. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +0 -1
  55. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +0 -105
@@ -0,0 +1,16 @@
1
+ /**
2
+ * GTAO's own spatial filter: one 3x3 edge-stopped pass over visibility and the bend.
3
+ *
4
+ * Its input and output are `rgba16float`: visibility in `x`, and in `yzw` the world-space bend, the bent normal
5
+ * minus the shading normal. The bend is what is filtered, never the bent normal, so an unoccluded texel, whose
6
+ * bend is zero, keeps the normal map's detail exactly however much its neighbours are averaged in.
7
+ *
8
+ * Visibility is filtered as `fragment_shader_denoise_ao` filters it — the A-trous step, its edge-stopping
9
+ * weights and phi values — with the variance taken from visibility alone, since the input carries no second
10
+ * moment. That shader stays as it is: it is shared with denoisers that do keep moments.
11
+ *
12
+ * @type {ImageShader}
13
+ */
14
+ export const shader_gtao_spatial_denoise: ImageShader;
15
+ import { ImageShader } from "../../shader/ImageShader.js";
16
+ //# sourceMappingURL=shader_gtao_spatial_denoise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_gtao_spatial_denoise.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.js"],"names":[],"mappings":"AA+HA;;;;;;;;;;;;GAYG;AACH,0CAFU,WAAW,CAiBlB;4BAvJyB,6BAA6B"}
@@ -0,0 +1,156 @@
1
+ import { DEPTH_STENCIL_FOREGROUND_ONLY } from "../../depth/DEPTH_STENCIL_FOREGROUND_ONLY.js";
2
+ import { chunk_compute_edge_stopping_weight } from "../../shader/chunk/filter/chunk_compute_edge_stopping_weight.js";
3
+ import { chunk_decode_g_buffer_normal } from "../../shader/chunk/geometry/normal/chunk_decode_g_buffer_normal.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { ImageShader } from "../../shader/ImageShader.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
8
+
9
+ const resources = new ShaderResourceSetDescriptor();
10
+
11
+ resources.createGroup()
12
+ .addTexture("tInput")
13
+ .addTexture("tDepth")
14
+ .addTexture("tNormal", "uint");
15
+
16
+ const body = CodeChunk.from(
17
+ //language=WGSL
18
+ `
19
+ const phi_visibility = 4.0;
20
+ const phi_normal = 128.0;
21
+ const sigma_depth = 1.0;
22
+
23
+ const offsets = array< vec2<i32>, 8 >(
24
+ vec2( -1, -1 ),
25
+ vec2( 0, -1 ),
26
+ vec2( 1, -1 ),
27
+ vec2( -1, 0 ),
28
+ vec2( 1, 0 ),
29
+ vec2( -1, 1 ),
30
+ vec2( 0, 1 ),
31
+ vec2( 1, 1 ),
32
+ );
33
+
34
+ // Visibility's spatial variance over a 3x3 Gaussian. The input carries visibility alone, so its second moment
35
+ // is the square of each texel's.
36
+ fn gtao_visibility_variance(ipos: vec2<i32>) -> f32 {
37
+ let kernel = array<f32, 3>(0.25, 0.125, 0.0625);
38
+
39
+ var moments = vec2<f32>(0.0);
40
+
41
+ for (var yy = -1; yy <= 1; yy++) {
42
+ for (var xx = -1; xx <= 1; xx++) {
43
+ let v = textureLoad(tInput, ipos + vec2<i32>(xx, yy), 0).x;
44
+
45
+ moments += vec2(v, v * v) * kernel[ abs(xx) + abs(yy) ];
46
+ }
47
+ }
48
+
49
+ return max(moments.y - moments.x * moments.x, 0.0);
50
+ }
51
+
52
+ @fragment
53
+ fn main(
54
+ @builtin(position) coord: vec4<f32>,
55
+ ) -> @location(0) vec4<f32> {
56
+ let ipos = vec2<i32>(coord.xy);
57
+ let screen_size = vec2<i32>(textureDimensions(tInput));
58
+
59
+ const eps_variance = 1e-10;
60
+ const kernel_weights = array<f32,3>( 1.0, 2.0 / 3.0, 1.0 / 6.0 );
61
+
62
+ let center = textureLoad(tInput, ipos, 0);
63
+
64
+ let std_dev = sqrt(max(0.0, eps_variance + gtao_visibility_variance(ipos)));
65
+
66
+ let phi_luma = phi_visibility * std_dev;
67
+
68
+ let current_normal = decode_g_buffer_normal(textureLoad(tNormal, ipos, 0).xy);
69
+ let center_depth = textureLoad(tDepth, ipos, 0).r;
70
+
71
+ // the centre at weight 1, so the edge-stopping functions cannot leave nothing
72
+ var sum_w_visibility = 1.0;
73
+ var sum_visibility = center.x;
74
+
75
+ // The bend is averaged weighted by visibility as well. A bent normal stands for the visible directions;
76
+ // the bent normal of several texels together is the sum of each one's scaled by how much it sees,
77
+ // normalized, and with neighbours whose normals agree that is the shading normal plus this average.
78
+ var sum_w_bend = center.x;
79
+ var sum_bend = center.yzw * center.x;
80
+
81
+ for (var i = 0; i < 8; i++) {
82
+ let offset = offsets[i];
83
+
84
+ let p = ipos + offset;
85
+
86
+ if (any(p < vec2(0)) || any(p >= screen_size)) {
87
+ continue;
88
+ }
89
+
90
+ let kernel = kernel_weights[ abs(offset.x) ] * kernel_weights[ abs(offset.y) ];
91
+
92
+ let texel = textureLoad(tInput, p, 0);
93
+
94
+ let sample_normal = decode_g_buffer_normal(textureLoad(tNormal, p, 0).xy);
95
+ let sample_depth = textureLoad(tDepth, p, 0).r;
96
+
97
+ let w = compute_edge_stopping_weight(
98
+ center_depth,
99
+ sample_depth,
100
+ sigma_depth,
101
+
102
+ current_normal,
103
+ sample_normal,
104
+ phi_normal,
105
+
106
+ center.x,
107
+ texel.x,
108
+ phi_luma
109
+ ) * kernel;
110
+
111
+ sum_w_visibility += w;
112
+ sum_visibility += w * texel.x;
113
+
114
+ let w_bend = w * texel.x;
115
+
116
+ sum_w_bend += w_bend;
117
+ sum_bend += w_bend * texel.yzw;
118
+ }
119
+
120
+ return vec4(sum_visibility / sum_w_visibility, sum_bend / sum_w_bend);
121
+ }
122
+ `,
123
+ [
124
+ chunk_decode_g_buffer_normal,
125
+ chunk_compute_edge_stopping_weight,
126
+ ]);
127
+
128
+ /**
129
+ * GTAO's own spatial filter: one 3x3 edge-stopped pass over visibility and the bend.
130
+ *
131
+ * Its input and output are `rgba16float`: visibility in `x`, and in `yzw` the world-space bend, the bent normal
132
+ * minus the shading normal. The bend is what is filtered, never the bent normal, so an unoccluded texel, whose
133
+ * bend is zero, keeps the normal map's detail exactly however much its neighbours are averaged in.
134
+ *
135
+ * Visibility is filtered as `fragment_shader_denoise_ao` filters it — the A-trous step, its edge-stopping
136
+ * weights and phi values — with the variance taken from visibility alone, since the input carries no second
137
+ * moment. That shader stays as it is: it is shared with denoisers that do keep moments.
138
+ *
139
+ * @type {ImageShader}
140
+ */
141
+ export const shader_gtao_spatial_denoise = ImageShader.from({
142
+ descriptor: ShaderDescriptor.from({
143
+ label: "GTAO Spatial Denoise",
144
+ resources,
145
+ body
146
+ }),
147
+ depthStencil: DEPTH_STENCIL_FOREGROUND_ONLY,
148
+ targets: [
149
+ {
150
+ format: "rgba16float",
151
+ // Background is skipped, so it keeps the clear: not occluded, not bent. Downstream neighbourhoods
152
+ // read across silhouettes and must see background as unoccluded.
153
+ clearValue: [1, 0, 0, 0],
154
+ }
155
+ ]
156
+ });
@@ -105,8 +105,8 @@ export class GPUSceneContext {
105
105
  * (REVIEW_LEDGER U1): `register` a container with {@link virtual_geometry_residency}, and every
106
106
  * page after the root arrives because a cut asked for it. The renderer opens and closes each
107
107
  * frame and schedules each reading, and {@link destroy} releases all of it; a host touches none
108
- * of it. With them, the source of its geometries' caches ({@link VGeoSDFProxies}): a cache asked
109
- * of a virtual geometry is baked from a proxy cut from it.
108
+ * of it. With them, the source of its geometries' caches and cards ({@link VGeoSDFProxies}): a virtual
109
+ * geometry whose cache is asked for stands in through its proxy.
110
110
  *
111
111
  * @param {Object} [options] passed to {@link GPUVirtualGeometryPool} and
112
112
  * {@link GPUVirtualGeometryRuntime}, except for `residency`
@@ -399,8 +399,8 @@ export class GPUSceneContext {
399
399
  * (REVIEW_LEDGER U1): `register` a container with {@link virtual_geometry_residency}, and every
400
400
  * page after the root arrives because a cut asked for it. The renderer opens and closes each
401
401
  * frame and schedules each reading, and {@link destroy} releases all of it; a host touches none
402
- * of it. With them, the source of its geometries' caches ({@link VGeoSDFProxies}): a cache asked
403
- * of a virtual geometry is baked from a proxy cut from it.
402
+ * of it. With them, the source of its geometries' caches and cards ({@link VGeoSDFProxies}): a virtual
403
+ * geometry whose cache is asked for stands in through its proxy.
404
404
  *
405
405
  * @param {Object} [options] passed to {@link GPUVirtualGeometryPool} and
406
406
  * {@link GPUVirtualGeometryRuntime}, except for `residency`
@@ -448,8 +448,8 @@ export class GPUSceneContext {
448
448
 
449
449
  feedback = new VGeoFeedbackLoop({ runtime, residency: tiers });
450
450
 
451
- // last: it makes its buffers and subscribes to the caches as it is made
452
- proxies = new VGeoSDFProxies({ device: this.#device, runtime, geometries: this.geometries });
451
+ // last: it subscribes to the caches as it is made
452
+ proxies = new VGeoSDFProxies({ geometries: this.geometries });
453
453
  } catch (error) {
454
454
  // the pool is the only one holding anything yet: the fetcher spawns its workers on its
455
455
  // first fetch, and the runtime makes its buffer on its first frame
@@ -874,7 +874,7 @@ export class GPUSceneContext {
874
874
  return;
875
875
  }
876
876
 
877
- // its proxies out of the geometry manager, and its cut's buffers, ahead of the runtime's
877
+ // it hears no more of the caches; its proxies stay with the geometry manager, destroyed with it
878
878
  this.#virtual_geometry_proxies.destroy();
879
879
 
880
880
  this.#virtual_geometry_feedback.destroy();
@@ -1,47 +0,0 @@
1
- /**
2
- * Words of the payload's header for `job_count` jobs: their counters, then the cut's own counters from its feedback
3
- * slot (`VGEO_CUT_STAT`), which say whether the cut left a subtree undescended.
4
- *
5
- * @param {number} job_count
6
- * @returns {number}
7
- */
8
- export function vgeo_sdf_header_words(job_count: number): number;
9
- /**
10
- * The extraction's settings, an immediate of each of its passes.
11
- * @type {WebGPUStruct}
12
- */
13
- export const VGEO_SDF_SETTINGS: WebGPUStruct;
14
- /**
15
- * A job the frame cuts, as the host writes it: the vgeo geometry row it cuts and the projection constant that puts its
16
- * error against a τ of 1, `1 / (½ voxel)` in the geometry's own units. A job the frame writes out (`decode` 1) has its
17
- * room in the payload: `vertex_count` vertices from `vertex_base` and `triangle_count` triangles from `triangle_base`,
18
- * what its last complete cut held.
19
- * @type {WebGPUStruct}
20
- */
21
- export const VGEO_SDF_JOB_STRUCT: WebGPUStruct;
22
- /**
23
- * A job's counters, atomics the frame's passes add into: the clusters its cut took, the stand-ins among them (a
24
- * cluster taken for a page not resident or a group held), those dropped past the cluster list, the vertices and
25
- * triangles of its listed clusters, and of those, what the decode wrote into its room.
26
- */
27
- export const VGEO_SDF_COUNTER: Readonly<{
28
- TAKEN: 0;
29
- STAND_INS: 1;
30
- DROPPED: 2;
31
- VERTICES: 3;
32
- TRIANGLES: 4;
33
- VERTICES_WRITTEN: 5;
34
- TRIANGLES_WRITTEN: 6;
35
- }>;
36
- /**
37
- * Words of a job's counters.
38
- * @type {number}
39
- */
40
- export const VGEO_SDF_COUNTER_WORDS: number;
41
- /**
42
- * Words of a cluster list entry: its job, then its meshlet row.
43
- * @type {number}
44
- */
45
- export const VGEO_SDF_CLUSTER_WORDS: number;
46
- import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
47
- //# sourceMappingURL=VGEO_SDF.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"VGEO_SDF.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js"],"names":[],"mappings":"AAsEA;;;;;;GAMG;AACH,iDAHW,MAAM,GACJ,MAAM,CAIlB;AArED;;;GAGG;AACH,gCAFU,YAAY,CAWA;AAEtB;;;;;;GAMG;AACH,kCAFU,YAAY,CAWL;AAEjB;;;;GAIG;AACH;;;;;;;;GAQG;AAEH;;;GAGG;AACH,qCAFU,MAAM,CAEwB;AAExC;;;GAGG;AACH,qCAFU,MAAM,CAEwB;6BAnEX,sCAAsC"}
@@ -1,80 +0,0 @@
1
- import { f32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
- import { WebGPUStruct } from "../../../shader/type/WebGPUStruct.js";
3
- import { VGEO_CUT_STAT_COUNT } from "../runtime/layout/VGEO_CUT_STAT_COUNT.js";
4
-
5
- /*
6
- The layouts of a vgeo geometry's proxy extraction (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): each geometry
7
- whose cache is asked for is cut whole at half its cache's level-0 voxel, its cut's clusters listed, and, once a cut
8
- stands nothing in, its vertices and triangles written out and read back for the proxy the mesh bake bakes.
9
- */
10
-
11
- /**
12
- * The extraction's settings, an immediate of each of its passes.
13
- * @type {WebGPUStruct}
14
- */
15
- export const VGEO_SDF_SETTINGS = WebGPUStruct.from({
16
- /** jobs the frame cuts */
17
- job_count: u32,
18
- /** entries the cluster list holds */
19
- cluster_capacity: u32,
20
- /** the word of the payload its vertices start at, 3 floats a vertex */
21
- vertex_offset: u32,
22
- /** the word of the payload its triangles start at, 3 indices a triangle */
23
- index_offset: u32,
24
- }, "VGeoSDFSettings");
25
-
26
- /**
27
- * A job the frame cuts, as the host writes it: the vgeo geometry row it cuts and the projection constant that puts its
28
- * error against a τ of 1, `1 / (½ voxel)` in the geometry's own units. A job the frame writes out (`decode` 1) has its
29
- * room in the payload: `vertex_count` vertices from `vertex_base` and `triangle_count` triangles from `triangle_base`,
30
- * what its last complete cut held.
31
- * @type {WebGPUStruct}
32
- */
33
- export const VGEO_SDF_JOB_STRUCT = WebGPUStruct.from({
34
- vg_row: u32,
35
- projection_k: f32,
36
- decode: u32,
37
- vertex_base: u32,
38
- triangle_base: u32,
39
- vertex_count: u32,
40
- triangle_count: u32,
41
- pad: u32,
42
- }, "VGeoSDFJob");
43
-
44
- /**
45
- * A job's counters, atomics the frame's passes add into: the clusters its cut took, the stand-ins among them (a
46
- * cluster taken for a page not resident or a group held), those dropped past the cluster list, the vertices and
47
- * triangles of its listed clusters, and of those, what the decode wrote into its room.
48
- */
49
- export const VGEO_SDF_COUNTER = Object.freeze({
50
- TAKEN: 0,
51
- STAND_INS: 1,
52
- DROPPED: 2,
53
- VERTICES: 3,
54
- TRIANGLES: 4,
55
- VERTICES_WRITTEN: 5,
56
- TRIANGLES_WRITTEN: 6,
57
- });
58
-
59
- /**
60
- * Words of a job's counters.
61
- * @type {number}
62
- */
63
- export const VGEO_SDF_COUNTER_WORDS = 8;
64
-
65
- /**
66
- * Words of a cluster list entry: its job, then its meshlet row.
67
- * @type {number}
68
- */
69
- export const VGEO_SDF_CLUSTER_WORDS = 2;
70
-
71
- /**
72
- * Words of the payload's header for `job_count` jobs: their counters, then the cut's own counters from its feedback
73
- * slot (`VGEO_CUT_STAT`), which say whether the cut left a subtree undescended.
74
- *
75
- * @param {number} job_count
76
- * @returns {number}
77
- */
78
- export function vgeo_sdf_header_words(job_count) {
79
- return job_count * VGEO_SDF_COUNTER_WORDS + VGEO_CUT_STAT_COUNT;
80
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Lanes of the collect, a lane a job.
3
- * @type {number}
4
- */
5
- export const VGEO_SDF_COLLECT_WORKGROUP_SIZE: number;
6
- /**
7
- * The extraction's collect (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): a cut's instance record a job,
8
- * as every cut's collect writes one (`chunk_vgeo_cut_instance`), its geometry's root page, lookup and claim width from
9
- * the geometry's row. Cut in the geometry's own space, at a world error under half its cache's voxel: `k` the job's,
10
- * the distance weight 0.
11
- *
12
- * @type {ComputeShader}
13
- */
14
- export const shader_vgeo_sdf_collect: ComputeShader;
15
- import { ComputeShader } from "../../../shader/ComputeShader.js";
16
- //# sourceMappingURL=shader_vgeo_sdf_collect.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shader_vgeo_sdf_collect.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js"],"names":[],"mappings":"AAUA;;;GAGG;AACH,8CAFU,MAAM,CAEkC;AAwClD;;;;;;;GAOG;AACH,sCAFU,aAAa,CAMpB;8BAhE2B,kCAAkC"}
@@ -1,67 +0,0 @@
1
- import { COLLECTION_U32_STRUCT_WRITE } from "../../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
2
- import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
3
- import { ComputeShader } from "../../../shader/ComputeShader.js";
4
- import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
5
- import { u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
6
- import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
7
- import { chunk_vgeo_cut_instance } from "../runtime/cut/chunk_vgeo_cut_instance.js";
8
- import { VGEO_INSTANCE_OFFSET } from "../runtime/layout/VGEO_INSTANCE_OFFSET.js";
9
- import { VGEO_SDF_JOB_STRUCT, VGEO_SDF_SETTINGS } from "./VGEO_SDF.js";
10
-
11
- /**
12
- * Lanes of the collect, a lane a job.
13
- * @type {number}
14
- */
15
- export const VGEO_SDF_COLLECT_WORKGROUP_SIZE = 64;
16
-
17
- const resources = new ShaderResourceSetDescriptor();
18
-
19
- resources.setImmediate("settings", VGEO_SDF_SETTINGS);
20
-
21
- resources.createGroup()
22
- .addStorageBuffer("vgeo_sdf_jobs", WebGPUArray.from(VGEO_SDF_JOB_STRUCT))
23
- .addStorageBuffer("vg_geometries", WebGPUArray.from(u32))
24
- // a cut's instance records, and their claim widths for the scan
25
- .addStorageBuffer("instances", WebGPUArray.from(u32), true)
26
- .addStorageBuffer("claim_widths", COLLECTION_U32_STRUCT_WRITE, true);
27
-
28
- const body = CodeChunk.from(
29
- //language=WGSL
30
- `
31
- @compute @workgroup_size(${VGEO_SDF_COLLECT_WORKGROUP_SIZE})
32
- fn main(@builtin(global_invocation_id) id: vec3<u32>) {
33
- let job = id.x;
34
-
35
- if (job >= settings.job_count) {
36
- return;
37
- }
38
-
39
- // a job's record names its job where a view's names its mesh row: what its take lists the job's clusters under
40
- let base = vg_instance_record(job, vgeo_sdf_jobs[job].vg_row, settings.job_count);
41
-
42
- if (base == VG_INSTANCE_RECORD_NONE) {
43
- return;
44
- }
45
-
46
- // no eye: at a distance weight of 0 the projection is the error itself over half the voxel, wherever it is
47
- vg_store(base, ${VGEO_INSTANCE_OFFSET.EYE}u, 0.0);
48
- vg_store(base, ${VGEO_INSTANCE_OFFSET.EYE + 1}u, 0.0);
49
- vg_store(base, ${VGEO_INSTANCE_OFFSET.EYE + 2}u, 0.0);
50
- vg_store(base, ${VGEO_INSTANCE_OFFSET.PROJECTION_K}u, vgeo_sdf_jobs[job].projection_k);
51
- vg_store(base, ${VGEO_INSTANCE_OFFSET.DISTANCE_WEIGHT}u, 0.0);
52
- }
53
- `, [chunk_vgeo_cut_instance]);
54
-
55
- /**
56
- * The extraction's collect (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): a cut's instance record a job,
57
- * as every cut's collect writes one (`chunk_vgeo_cut_instance`), its geometry's root page, lookup and claim width from
58
- * the geometry's row. Cut in the geometry's own space, at a world error under half its cache's voxel: `k` the job's,
59
- * the distance weight 0.
60
- *
61
- * @type {ComputeShader}
62
- */
63
- export const shader_vgeo_sdf_collect = ComputeShader.from({
64
- label: "VGeo SDF Collect",
65
- resources,
66
- body,
67
- });
@@ -1,17 +0,0 @@
1
- /**
2
- * Lanes of the decode, a workgroup a listed cluster: a lane a vertex, and a lane a triangle.
3
- * @type {number}
4
- */
5
- export const VGEO_SDF_DECODE_WORKGROUP_SIZE: number;
6
- /**
7
- * The extraction's decode (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): a workgroup a cluster the cut
8
- * listed, dispatched by the list's count. Each adds its cluster's vertices and triangles to its job's counts, which
9
- * size the job's room in a later frame. A job the host gives room this frame (`decode`) takes each cluster's share of
10
- * it by atomic: the cluster's positions as they are stored, in the geometry's own space, and its triangles as indices
11
- * into its job's vertices, which the host reads back as the proxy's mesh.
12
- *
13
- * @type {ComputeShader}
14
- */
15
- export const shader_vgeo_sdf_decode: ComputeShader;
16
- import { ComputeShader } from "../../../shader/ComputeShader.js";
17
- //# sourceMappingURL=shader_vgeo_sdf_decode.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shader_vgeo_sdf_decode.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js"],"names":[],"mappings":"AAuBA;;;GAGG;AACH,6CAFU,MAAM,CAEuG;AAwGvH;;;;;;;;GAQG;AACH,qCAFU,aAAa,CAMpB;8BAzI2B,kCAAkC"}
@@ -1,145 +0,0 @@
1
- import { assert } from "../../../../../core/assert.js";
2
- import { COLLECTION_U32_STRUCT_READ } from "../../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
3
- import { chunk_meshlet_compute_attribute_section_offset } from "../../../shader/chunk/geometry/meshlet/chunk_meshlet_compute_attribute_section_offset.js";
4
- import { chunk_read_meshlet_attribute_vec3f } from "../../../shader/chunk/geometry/meshlet/chunk_read_meshlet_attribute_vec3f.js";
5
- import { chunk_read_meshlet_resolved_index } from "../../../shader/chunk/geometry/meshlet/chunk_read_meshlet_resolved_index.js";
6
- import { chunk_folded_workgroup_index } from "../../../shader/chunk/grid/chunk_folded_workgroup_index.js";
7
- import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
8
- import { ComputeShader } from "../../../shader/ComputeShader.js";
9
- import { ShaderResourceSetDescriptor } from "../../../shader/resource/ShaderResourceSetDescriptor.js";
10
- import { atomic_u32, u32 } from "../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
11
- import { WebGPUArray } from "../../../shader/type/WebGPUArray.js";
12
- import { GEOMETRY_ATTRIBUTE_DATA_TYPE } from "../../GEOMETRY_ATTRIBUTE_DATA_TYPE.js";
13
- import { MESHLET_METADATA_STRUCT } from "../../meshlet/encoding/MESHLET_METADATA_STRUCT.js";
14
- import { VGEO_MAX_CLUSTER_TRIANGLE_COUNT } from "../format/cluster/VGEO_MAX_CLUSTER_TRIANGLE_COUNT.js";
15
- import { VGEO_MAX_CLUSTER_VERTEX_COUNT } from "../format/cluster/VGEO_MAX_CLUSTER_VERTEX_COUNT.js";
16
- import {
17
- VGEO_SDF_CLUSTER_WORDS,
18
- VGEO_SDF_COUNTER,
19
- VGEO_SDF_COUNTER_WORDS,
20
- VGEO_SDF_JOB_STRUCT,
21
- VGEO_SDF_SETTINGS
22
- } from "./VGEO_SDF.js";
23
-
24
- /**
25
- * Lanes of the decode, a workgroup a listed cluster: a lane a vertex, and a lane a triangle.
26
- * @type {number}
27
- */
28
- export const VGEO_SDF_DECODE_WORKGROUP_SIZE = Math.max(VGEO_MAX_CLUSTER_VERTEX_COUNT, VGEO_MAX_CLUSTER_TRIANGLE_COUNT);
29
-
30
- assert.lessThanOrEqual(VGEO_SDF_DECODE_WORKGROUP_SIZE, 256, 'the decode\'s workgroup is within WebGPU\'s default invocation limit');
31
-
32
- const resources = new ShaderResourceSetDescriptor();
33
-
34
- resources.setImmediate("settings", VGEO_SDF_SETTINGS);
35
-
36
- resources.createGroup()
37
- .addStorageBuffer("vgeo_sdf_jobs", WebGPUArray.from(VGEO_SDF_JOB_STRUCT))
38
- .addStorageBuffer("vgeo_sdf_counters", WebGPUArray.from(atomic_u32), true)
39
- .addStorageBuffer("vgeo_sdf_clusters", COLLECTION_U32_STRUCT_READ)
40
- .addStorageBuffer("meshlet_metadata", WebGPUArray.from(MESHLET_METADATA_STRUCT))
41
- .addStorageBuffer("meshlet_data", GEOMETRY_ATTRIBUTE_DATA_TYPE)
42
- // the readback's: its header, then the jobs' vertices, then their triangles
43
- .addStorageBuffer("vgeo_sdf_payload", WebGPUArray.from(u32), true);
44
-
45
- const body = CodeChunk.from(
46
- //language=WGSL
47
- `
48
- var<workgroup> listed: u32;
49
- var<workgroup> writes: u32;
50
- var<workgroup> first_vertex: u32;
51
- var<workgroup> first_triangle: u32;
52
-
53
- @compute @workgroup_size(${VGEO_SDF_DECODE_WORKGROUP_SIZE})
54
- fn main(
55
- @builtin(workgroup_id) workgroup_id: vec3<u32>,
56
- @builtin(local_invocation_index) lane: u32,
57
- ) {
58
- let index = folded_workgroup_index(workgroup_id);
59
-
60
- if (lane == 0u) {
61
- listed = min(vgeo_sdf_clusters.count, settings.cluster_capacity);
62
- }
63
-
64
- // a folded dispatch's tail, and a count that ran past the list, leave whole
65
- if (index >= workgroupUniformLoad(&listed)) {
66
- return;
67
- }
68
-
69
- let entry = ${VGEO_SDF_CLUSTER_WORDS}u * index;
70
- let job = vgeo_sdf_clusters.elements[entry];
71
- let meshlet = vgeo_sdf_clusters.elements[entry + 1u];
72
- let header = meshlet_metadata[meshlet];
73
- let counters = job * ${VGEO_SDF_COUNTER_WORDS}u;
74
-
75
- // every job's size, what the host makes room by; a job written out this frame takes its cluster's room in it
76
- if (lane == 0u) {
77
- atomicAdd(&vgeo_sdf_counters[counters + ${VGEO_SDF_COUNTER.VERTICES}u], header.vertex_count);
78
- atomicAdd(&vgeo_sdf_counters[counters + ${VGEO_SDF_COUNTER.TRIANGLES}u], header.primitive_count);
79
-
80
- var write = 0u;
81
-
82
- if (vgeo_sdf_jobs[job].decode != 0u) {
83
- let vertex = atomicAdd(&vgeo_sdf_counters[counters + ${VGEO_SDF_COUNTER.VERTICES_WRITTEN}u], header.vertex_count);
84
- let triangle = atomicAdd(&vgeo_sdf_counters[counters + ${VGEO_SDF_COUNTER.TRIANGLES_WRITTEN}u], header.primitive_count);
85
-
86
- // a cut grown since the room was made writes nothing past it; the host sees the sizes disagree
87
- if (vertex + header.vertex_count <= vgeo_sdf_jobs[job].vertex_count
88
- && triangle + header.primitive_count <= vgeo_sdf_jobs[job].triangle_count) {
89
- first_vertex = vertex;
90
- first_triangle = triangle;
91
- write = 1u;
92
- }
93
- }
94
-
95
- writes = write;
96
- }
97
-
98
- if (workgroupUniformLoad(&writes) == 0u) {
99
- return;
100
- }
101
-
102
- let vertex_base = first_vertex;
103
-
104
- if (lane < header.vertex_count) {
105
- let position = read_meshlet_attribute_vec3f(meshlet_compute_attribute_section_offset(header) + 3u * lane);
106
- let word = settings.vertex_offset + 3u * (vgeo_sdf_jobs[job].vertex_base + vertex_base + lane);
107
-
108
- vgeo_sdf_payload[word] = bitcast<u32>(position.x);
109
- vgeo_sdf_payload[word + 1u] = bitcast<u32>(position.y);
110
- vgeo_sdf_payload[word + 2u] = bitcast<u32>(position.z);
111
- }
112
-
113
- // the cluster's corners as indices into its job's vertices, clamped to its own as every reader of it clamps
114
- if (lane < header.primitive_count) {
115
- let word = settings.index_offset + 3u * (vgeo_sdf_jobs[job].triangle_base + first_triangle + lane);
116
-
117
- for (var corner = 0u; corner < 3u; corner++) {
118
- let local = min(read_meshlet_resolved_index(header, 3u * lane + corner), header.vertex_count - 1u);
119
-
120
- vgeo_sdf_payload[word + corner] = vertex_base + local;
121
- }
122
- }
123
- }
124
- `, [
125
- MESHLET_METADATA_STRUCT.declaration_chunk,
126
- chunk_folded_workgroup_index,
127
- chunk_meshlet_compute_attribute_section_offset,
128
- chunk_read_meshlet_attribute_vec3f,
129
- chunk_read_meshlet_resolved_index,
130
- ]);
131
-
132
- /**
133
- * The extraction's decode (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): a workgroup a cluster the cut
134
- * listed, dispatched by the list's count. Each adds its cluster's vertices and triangles to its job's counts, which
135
- * size the job's room in a later frame. A job the host gives room this frame (`decode`) takes each cluster's share of
136
- * it by atomic: the cluster's positions as they are stored, in the geometry's own space, and its triangles as indices
137
- * into its job's vertices, which the host reads back as the proxy's mesh.
138
- *
139
- * @type {ComputeShader}
140
- */
141
- export const shader_vgeo_sdf_decode = ComputeShader.from({
142
- label: "VGeo SDF Decode",
143
- resources,
144
- body,
145
- });
@@ -1,12 +0,0 @@
1
- /**
2
- * The extraction's cut (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §7.8, as S8 built it): the camera cut's descent
3
- * (`chunk_vgeo_cut_descent`) over the jobs' records, each geometry whole, at the error its record's projection constant
4
- * sets against a τ of 1. Every cluster in the cut, a stand-in too, goes onto the cluster list under its job; a clamp
5
- * wants its page through the extraction's own feedback slot, as the camera's do, so a job cut again each frame keeps
6
- * its pages wanted until they arrive.
7
- *
8
- * @type {ComputeShader}
9
- */
10
- export const shader_vgeo_sdf_traverse: ComputeShader;
11
- import { ComputeShader } from "../../../shader/ComputeShader.js";
12
- //# sourceMappingURL=shader_vgeo_sdf_traverse.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shader_vgeo_sdf_traverse.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js"],"names":[],"mappings":"AA2FA;;;;;;;;GAQG;AACH,uCAFU,aAAa,CAMpB;8BApG2B,kCAAkC"}