@aethervtt/shard-render 0.0.1 → 0.1.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 (134) hide show
  1. package/dist/assets.d.ts +3 -0
  2. package/dist/assets.js +43 -2
  3. package/dist/atmosphere-nodes.d.ts +9 -0
  4. package/dist/atmosphere-nodes.js +57 -18
  5. package/dist/atmosphere-plugin.js +8 -2
  6. package/dist/baseline/atmosphere.d.ts +16 -0
  7. package/dist/baseline/atmosphere.js +301 -0
  8. package/dist/baseline/data-texture.d.ts +36 -0
  9. package/dist/baseline/data-texture.js +181 -0
  10. package/dist/baseline/environment.d.ts +14 -0
  11. package/dist/baseline/environment.js +368 -0
  12. package/dist/baseline/exposure.d.ts +25 -0
  13. package/dist/baseline/exposure.js +120 -0
  14. package/dist/baseline/lights.d.ts +33 -0
  15. package/dist/baseline/lights.js +133 -0
  16. package/dist/baseline/textures.d.ts +97 -0
  17. package/dist/baseline/textures.js +203 -0
  18. package/dist/camera.d.ts +2 -0
  19. package/dist/camera.js +4 -0
  20. package/dist/culling-shaders.js +21 -2
  21. package/dist/culling.d.ts +11 -2
  22. package/dist/culling.js +44 -18
  23. package/dist/cutaway-plugin.d.ts +48 -0
  24. package/dist/cutaway-plugin.js +364 -0
  25. package/dist/cutaway.d.ts +27 -0
  26. package/dist/cutaway.js +49 -0
  27. package/dist/data-store.d.ts +69 -0
  28. package/dist/data-store.js +105 -0
  29. package/dist/debug-shaders.js +17 -3
  30. package/dist/debug-views.js +4 -2
  31. package/dist/deferred-shaders.js +2 -0
  32. package/dist/deferred.js +24 -3
  33. package/dist/deform.d.ts +5 -4
  34. package/dist/deform.js +4 -9
  35. package/dist/describe-plugin.d.ts +4 -2
  36. package/dist/describe-plugin.js +75 -3
  37. package/dist/display-nodes.js +15 -4
  38. package/dist/dynamic-resolution.d.ts +2 -0
  39. package/dist/dynamic-resolution.js +6 -1
  40. package/dist/environment-plugin.js +17 -2
  41. package/dist/environment-state.d.ts +7 -3
  42. package/dist/environment-state.js +20 -9
  43. package/dist/environment.js +7 -1
  44. package/dist/features.d.ts +49 -0
  45. package/dist/features.js +106 -0
  46. package/dist/forward.d.ts +38 -2
  47. package/dist/forward.js +582 -184
  48. package/dist/fxaa.js +12 -2
  49. package/dist/gizmos-plugin.js +7 -0
  50. package/dist/gizmos.d.ts +3 -3
  51. package/dist/gizmos.js +11 -13
  52. package/dist/gpu-assets.d.ts +58 -4
  53. package/dist/gpu-assets.js +191 -8
  54. package/dist/graph.d.ts +11 -0
  55. package/dist/graph.js +30 -5
  56. package/dist/health.d.ts +58 -0
  57. package/dist/health.js +112 -0
  58. package/dist/index.d.ts +30 -11
  59. package/dist/index.js +286 -9
  60. package/dist/instances.d.ts +119 -8
  61. package/dist/instances.js +387 -78
  62. package/dist/interior-plugin.d.ts +121 -0
  63. package/dist/interior-plugin.js +465 -0
  64. package/dist/interior.d.ts +24 -0
  65. package/dist/interior.js +13 -0
  66. package/dist/layers.d.ts +35 -0
  67. package/dist/layers.js +49 -0
  68. package/dist/lens-plugin.d.ts +43 -0
  69. package/dist/lens-plugin.js +304 -0
  70. package/dist/lens.d.ts +41 -0
  71. package/dist/lens.js +99 -0
  72. package/dist/lights.d.ts +50 -5
  73. package/dist/lights.js +101 -22
  74. package/dist/material-pipelines.d.ts +37 -4
  75. package/dist/material-pipelines.js +102 -5
  76. package/dist/materials.d.ts +23 -0
  77. package/dist/materials.js +44 -1
  78. package/dist/outline-plugin.d.ts +48 -0
  79. package/dist/outline-plugin.js +529 -0
  80. package/dist/outline.d.ts +15 -0
  81. package/dist/outline.js +42 -0
  82. package/dist/overlays.js +1 -0
  83. package/dist/picking.d.ts +17 -0
  84. package/dist/picking.js +40 -11
  85. package/dist/pixel-perfect-plugin.js +10 -2
  86. package/dist/plugin.d.ts +58 -6
  87. package/dist/plugin.js +191 -24
  88. package/dist/post-common.d.ts +2 -0
  89. package/dist/post-common.js +3 -0
  90. package/dist/post-nodes.d.ts +2 -1
  91. package/dist/post-nodes.js +111 -19
  92. package/dist/post-plugin.js +5 -3
  93. package/dist/post-shaders.js +51 -6
  94. package/dist/projection.d.ts +24 -0
  95. package/dist/projection.js +87 -0
  96. package/dist/readback.d.ts +1 -0
  97. package/dist/readback.js +1 -0
  98. package/dist/render-scale.js +1 -0
  99. package/dist/screen-effects.d.ts +97 -0
  100. package/dist/screen-effects.js +192 -0
  101. package/dist/shaders.d.ts +13 -0
  102. package/dist/shaders.js +131 -29
  103. package/dist/shadow-catcher.d.ts +9 -0
  104. package/dist/shadow-catcher.js +133 -0
  105. package/dist/shadows.d.ts +25 -1
  106. package/dist/shadows.js +97 -19
  107. package/dist/standard-fields.d.ts +1 -0
  108. package/dist/standard-fields.js +5 -0
  109. package/dist/standard.js +12 -0
  110. package/dist/stats.d.ts +45 -1
  111. package/dist/stats.js +91 -3
  112. package/dist/surface-model.d.ts +57 -0
  113. package/dist/surface-model.js +289 -0
  114. package/dist/surface-shaders.d.ts +3 -0
  115. package/dist/surface-shaders.js +160 -0
  116. package/dist/surface.d.ts +40 -0
  117. package/dist/surface.js +86 -0
  118. package/dist/target.d.ts +1 -13
  119. package/dist/target.js +1 -26
  120. package/dist/testing.d.ts +10 -0
  121. package/dist/testing.js +33 -1
  122. package/dist/tier.d.ts +13 -0
  123. package/dist/tier.js +14 -0
  124. package/dist/timer.d.ts +2 -0
  125. package/dist/timer.js +7 -1
  126. package/dist/variants.d.ts +37 -0
  127. package/dist/variants.js +104 -0
  128. package/dist/view-visibility-plugin.d.ts +61 -0
  129. package/dist/view-visibility-plugin.js +267 -0
  130. package/dist/view-visibility.d.ts +28 -0
  131. package/dist/view-visibility.js +46 -0
  132. package/dist/view.d.ts +29 -1
  133. package/dist/view.js +57 -34
  134. package/package.json +15 -11
package/dist/assets.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare const StandardMaterial: import("@aethervtt/shard-core").Component
12
12
  emissive: import("@aethervtt/shard-core").FieldType<import("@aethervtt/shard-core").Color, "f32">;
13
13
  emissiveLuminance: import("@aethervtt/shard-core").FieldType<number, "f32">;
14
14
  doubleSided: import("@aethervtt/shard-core").FieldType<boolean, "u8">;
15
+ deferUntilReady: import("@aethervtt/shard-core").FieldType<boolean, "u8">;
15
16
  alphaMode: import("@aethervtt/shard-core").FieldType<"additive" | "alpha" | "mask" | "opaque" | "premultiplied", "u8">;
16
17
  alphaCutoff: import("@aethervtt/shard-core").FieldType<number, "f32">;
17
18
  normalScale: import("@aethervtt/shard-core").FieldType<number, "f32">;
@@ -94,6 +95,8 @@ export declare const Materials: import("@aethervtt/shard-core").ResourceDef<Asse
94
95
  export declare const RenderTargets: import("@aethervtt/shard-core").ResourceDef<AssetStore<RenderTarget, "RenderTarget">>;
95
96
  /** Meshes load from binary artifacts (`encodeMesh`); a reload updates the mesh in place. */
96
97
  export declare const MeshAsset: import("@aethervtt/shard-assets").AssetTypeDef<Mesh>;
98
+ /** What a mesh that failed to load shows (0061): a 1 m beveled box, drawn with the missing material. */
99
+ export declare function missingMesh(): Mesh;
97
100
  /** Materials load from material JSON (any type); a reload bumps the material's version. */
98
101
  export declare const MaterialAssetType: import("@aethervtt/shard-assets").AssetTypeDef<MaterialAsset>;
99
102
  /**
package/dist/assets.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  defineSchema,
6
6
  ShardError
7
7
  } from "@aethervtt/shard-core";
8
- import { decodeMesh } from "@aethervtt/shard-mesh";
8
+ import { bevelBox, decodeMesh } from "@aethervtt/shard-mesh";
9
9
  import {
10
10
  allMaterialTypes,
11
11
  findMaterialType,
@@ -103,8 +103,20 @@ const RenderTargets = defineResource(
103
103
  const MeshAsset = defineAssetType("Mesh", {
104
104
  store: Meshes,
105
105
  load: (artifact) => decodeMesh(artifact.bytes),
106
- update: (existing, next) => existing.update(next.data())
106
+ update: (existing, next) => existing.update(next.data()),
107
+ fallback: () => missingMesh(),
108
+ cost: (mesh) => ({ triangles: Math.floor(mesh.drawCount / 3), bytes: meshBytes(mesh) })
107
109
  });
110
+ function missingMesh() {
111
+ const mesh = bevelBox({ x: 1, y: 1, z: 1 });
112
+ mesh.missing = true;
113
+ return mesh;
114
+ }
115
+ function meshBytes(mesh) {
116
+ let bytes = mesh.positions.byteLength + (mesh.indices?.byteLength ?? 0);
117
+ for (const a of [mesh.normals, mesh.uvs, mesh.uvs1, mesh.tangents]) bytes += a?.byteLength ?? 0;
118
+ return bytes;
119
+ }
108
120
  const MaterialAssetType = defineAssetType("Material", {
109
121
  store: Materials,
110
122
  // Texture paths resolve to guids here, so the renderer can look them up directly.
@@ -115,6 +127,8 @@ const MaterialAssetType = defineAssetType("Material", {
115
127
  };
116
128
  const errors = validateMaterial(artifact.json, { resolveAsset });
117
129
  if (errors.length > 0) {
130
+ const color = readableBaseColor(artifact.json);
131
+ if (color) readableColors.set(ctx.guid, color);
118
132
  const first = errors[0];
119
133
  throw new ShardError("assets/load-failed", `${ctx.path}: ${first.message}`, {
120
134
  path: first.path,
@@ -127,8 +141,34 @@ const MaterialAssetType = defineAssetType("Material", {
127
141
  update: (existing, next) => {
128
142
  existing.type = next.type;
129
143
  existing.set(next.value);
144
+ },
145
+ references: (material) => handlesIn(material.value),
146
+ // A material that failed to load draws as the standard one, in its own base color if readable.
147
+ fallback: ({ guid }) => {
148
+ const baseColor = readableColors.get(guid);
149
+ readableColors.delete(guid);
150
+ return new MaterialAsset(baseColor ? { baseColor } : {});
130
151
  }
131
152
  });
153
+ function* handlesIn(value) {
154
+ if (value === null || typeof value !== "object" || ArrayBuffer.isView(value)) return;
155
+ if (Array.isArray(value)) {
156
+ for (const v of value) yield* handlesIn(v);
157
+ return;
158
+ }
159
+ if (typeof value.guid === "string") yield value;
160
+ for (const v of Object.values(value)) yield* handlesIn(v);
161
+ }
162
+ const readableColors = /* @__PURE__ */ new Map();
163
+ function readableBaseColor(json) {
164
+ const raw = json?.baseColor;
165
+ if (raw === void 0) return void 0;
166
+ try {
167
+ return [...StandardMaterial.deserialize({ baseColor: raw }).baseColor];
168
+ } catch {
169
+ return void 0;
170
+ }
171
+ }
132
172
  const MaterialImporter = defineImporter({
133
173
  name: "data/material",
134
174
  version: 2,
@@ -209,5 +249,6 @@ export {
209
249
  materialFields,
210
250
  materialFromJson,
211
251
  materialTypeOf,
252
+ missingMesh,
212
253
  validateMaterial
213
254
  };
@@ -12,6 +12,11 @@ interface CameraGpu {
12
12
  transmittance: GPUTexture | undefined;
13
13
  /** The frame the sky-view and froxels were last computed. */
14
14
  computed: number;
15
+ /**
16
+ * Whether this frame's uniform holds the atmospheres (it's zeros until their LUTs exist): a bake
17
+ * waits for it, or the LUTs computed this frame would bake a black sky.
18
+ */
19
+ packed: boolean;
15
20
  generation: number;
16
21
  seen: number;
17
22
  }
@@ -34,6 +39,8 @@ export declare class AtmosphereGpu {
34
39
  frame: number;
35
40
  readonly pipelines: Map<string, GPUComputePipeline | GPURenderPipeline>;
36
41
  layouts: Record<string, GPUBindGroupLayout> | undefined;
42
+ /** The baseline tier's passes (0064): fragment passes, loaded only on a baseline device. */
43
+ baseline: typeof import('./baseline/atmosphere.js') | undefined;
37
44
  private readonly groups;
38
45
  ensure(gpu: GpuContext): void;
39
46
  /** A layer for a record: its own, a free one, or the least recently used. */
@@ -42,6 +49,8 @@ export declare class AtmosphereGpu {
42
49
  group(gpu: GpuContext, slot: string, key: string, layout: GPUBindGroupLayout, entries: () => GPUBindGroupEntry[]): GPUBindGroup;
43
50
  }
44
51
  export declare const AtmosphereGpuResource: import("@aethervtt/shard-core").ResourceDef<AtmosphereGpu>;
52
+ /** Writes a record's parameters (and the camera's origin in it) at `o`. */
53
+ export declare function packParams(rec: AtmosphereRecord, out: Float32Array, o: number, origin: Float64Array | undefined, oi: number): void;
45
54
  /**
46
55
  * Gives every listed atmosphere a LUT layer and uploads each camera's AtmosphereView uniform, and
47
56
  * its sky-view and froxel textures at the right sizes.
@@ -6,10 +6,12 @@ import {
6
6
  Environments,
7
7
  environmentBakers
8
8
  } from "./environment.js";
9
+ import { addRenderFeatures } from "./features.js";
9
10
  import { ForwardStateResource, sceneColor } from "./forward.js";
10
11
  import { RenderPhase } from "./graph.js";
11
12
  import { Gpu, Graph, Shaders, Views } from "./plugin.js";
12
13
  import { hasEffect, PostEffect } from "./post.js";
14
+ import { bindingDimension, depthReadEntry } from "./tier.js";
13
15
  import { cameraOf } from "./view.js";
14
16
  const LUT_LAYERS = 8;
15
17
  const PARAMS_FLOATS = 32;
@@ -39,22 +41,26 @@ class AtmosphereGpu {
39
41
  frame = 0;
40
42
  pipelines = /* @__PURE__ */ new Map();
41
43
  layouts;
44
+ /** The baseline tier's passes (0064): fragment passes, loaded only on a baseline device. */
45
+ baseline;
42
46
  groups = /* @__PURE__ */ new Map();
43
47
  ensure(gpu) {
44
48
  if (this.generation === gpu.generation) return;
45
49
  this.generation = gpu.generation;
46
- const usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_SRC;
50
+ const usage = GPUTextureUsage.TEXTURE_BINDING | written(gpu) | GPUTextureUsage.COPY_SRC;
47
51
  this.transmittance = gpu.device.createTexture({
48
52
  label: "atmosphere/transmittance",
49
53
  size: [TRANSMITTANCE_W, TRANSMITTANCE_H, LUT_LAYERS],
50
54
  format: "rgba16float",
51
- usage
55
+ usage,
56
+ ...bindingDimension(gpu, "2d-array")
52
57
  });
53
58
  this.multiscatter = gpu.device.createTexture({
54
59
  label: "atmosphere/multiscatter",
55
60
  size: [MULTISCATTER_SIZE, MULTISCATTER_SIZE, LUT_LAYERS],
56
61
  format: "rgba16float",
57
- usage
62
+ usage,
63
+ ...bindingDimension(gpu, "2d-array")
58
64
  });
59
65
  this.transmittanceArray = this.transmittance.createView({ dimension: "2d-array" });
60
66
  this.multiscatterArray = this.multiscatter.createView({ dimension: "2d-array" });
@@ -124,6 +130,7 @@ class AtmosphereGpu {
124
130
  scatter: void 0,
125
131
  transmittance: void 0,
126
132
  computed: -1,
133
+ packed: false,
127
134
  generation: gpu.generation,
128
135
  seen: 0
129
136
  };
@@ -141,6 +148,9 @@ class AtmosphereGpu {
141
148
  return g.group;
142
149
  }
143
150
  }
151
+ function written(gpu) {
152
+ return gpu.tier === "full" ? GPUTextureUsage.STORAGE_BINDING : GPUTextureUsage.RENDER_ATTACHMENT;
153
+ }
144
154
  const AtmosphereGpuResource = defineResource("render/AtmosphereGpu", {
145
155
  description: "Atmosphere LUTs, per-camera sky-view LUTs and froxels, and their pipelines.",
146
156
  init: () => new AtmosphereGpu()
@@ -194,6 +204,7 @@ function relativeInverse(cam, out) {
194
204
  }
195
205
  function packView(ca, cam, c, out) {
196
206
  out.fill(0);
207
+ c.packed = false;
197
208
  for (const rec of ca.list) if (rec.layerVersion < 0) return;
198
209
  const n = Math.min(ca.list.length, 4);
199
210
  for (let i = 0; i < n; i++) packParams(ca.list[i], out, i * PARAMS_FLOATS, ca.origins, i * 4);
@@ -219,6 +230,7 @@ function packView(ca, cam, c, out) {
219
230
  out[O_CAMERA + 1] = cam.position[1];
220
231
  out[O_CAMERA + 2] = cam.position[2];
221
232
  out[O_CAMERA + 3] = cam.exposure;
233
+ c.packed = true;
222
234
  }
223
235
  const uploadAtmospheres = defineSystem({
224
236
  name: "render/atmosphere-upload",
@@ -259,7 +271,7 @@ function ensureViewTextures(gpu, c, ca) {
259
271
  label: "atmosphere/sky-view",
260
272
  size: [sw, sh],
261
273
  format: "rgba16float",
262
- usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING
274
+ usage: GPUTextureUsage.TEXTURE_BINDING | written(gpu)
263
275
  });
264
276
  }
265
277
  const [fx, fy, fz] = ca.froxels;
@@ -271,7 +283,7 @@ function ensureViewTextures(gpu, c, ca) {
271
283
  size: [fx, fy, fz],
272
284
  dimension: "3d",
273
285
  format: "rgba16float",
274
- usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING
286
+ usage: GPUTextureUsage.TEXTURE_BINDING | written(gpu)
275
287
  };
276
288
  c.scatter = gpu.device.createTexture(desc);
277
289
  c.transmittance = gpu.device.createTexture({
@@ -309,7 +321,7 @@ function layouts(gpu, s) {
309
321
  viewDimension
310
322
  }
311
323
  });
312
- s.layouts = {
324
+ const computeLayouts = gpu.tier === "full" ? {
313
325
  transmittance: gpu.layouts.bindGroupLayout({
314
326
  label: "atmosphere/transmittance",
315
327
  entries: [uniform(0, C), storage(1, "2d")]
@@ -335,13 +347,22 @@ function layouts(gpu, s) {
335
347
  }),
336
348
  bake: gpu.layouts.bindGroupLayout({
337
349
  label: "atmosphere/bake",
338
- entries: [uniform(0, C), array(1, C), array(2, C), filtering(3, C), storage(4, "2d-array")]
339
- }),
350
+ entries: [
351
+ uniform(0, C),
352
+ array(1, C),
353
+ array(2, C),
354
+ filtering(3, C),
355
+ storage(4, "2d-array")
356
+ ]
357
+ })
358
+ } : {};
359
+ s.layouts = {
360
+ ...computeLayouts,
340
361
  composite: gpu.layouts.bindGroupLayout({
341
362
  label: "atmosphere/composite",
342
363
  entries: [
343
364
  { binding: 0, visibility: F, texture: { sampleType: "unfilterable-float" } },
344
- { binding: 1, visibility: F, texture: { sampleType: "depth" } },
365
+ depthReadEntry(gpu, 1, F),
345
366
  uniform(2, F),
346
367
  array(3, F),
347
368
  array(4, F),
@@ -404,6 +425,10 @@ function lutNode() {
404
425
  s.lutFrame = s.frame;
405
426
  return;
406
427
  }
428
+ if (s.baseline) {
429
+ if (s.baseline.runLuts(ctx, s)) s.lutFrame = s.frame;
430
+ return;
431
+ }
407
432
  const t = compute(ctx, s, "transmittance", "shard::atmosphere::transmittance_lut");
408
433
  const m = compute(ctx, s, "multiscatter", "shard::atmosphere::multiscatter_lut");
409
434
  if (!t || !m) return;
@@ -471,6 +496,16 @@ function viewNode() {
471
496
  const c = s.cameras.get(cam.entity);
472
497
  if (!c?.skyView || !c.scatter || !c.transmittance) return;
473
498
  if (ca.primary.layerVersion !== ca.primary.version) return;
499
+ if (s.baseline) {
500
+ const view = {
501
+ uniform: c.uniform,
502
+ skyView: c.skyView,
503
+ scatter: c.scatter,
504
+ transmittance: c.transmittance
505
+ };
506
+ if (s.baseline.runView(ctx, s, ca, view)) c.computed = s.frame;
507
+ return;
508
+ }
474
509
  const sky = compute(ctx, s, "skyView", "shard::atmosphere::sky_view");
475
510
  const aerial = compute(ctx, s, "aerial", "shard::atmosphere::aerial");
476
511
  if (!sky || !aerial) return;
@@ -534,19 +569,17 @@ function idOf(o) {
534
569
  }
535
570
  return id;
536
571
  }
537
- let empty;
538
572
  function emptyTextures(gpu) {
539
- if (!empty || empty.generation !== gpu.generation) {
573
+ return gpu.shared("atmosphere/empty", (device) => {
540
574
  const usage = GPUTextureUsage.TEXTURE_BINDING;
541
- empty = {
542
- generation: gpu.generation,
543
- d2: gpu.device.createTexture({
575
+ return {
576
+ d2: device.createTexture({
544
577
  label: "atmosphere/empty",
545
578
  size: [1, 1],
546
579
  format: "rgba16float",
547
580
  usage
548
581
  }),
549
- d3: gpu.device.createTexture({
582
+ d3: device.createTexture({
550
583
  label: "atmosphere/empty-3d",
551
584
  size: [1, 1, 1],
552
585
  dimension: "3d",
@@ -554,8 +587,7 @@ function emptyTextures(gpu) {
554
587
  usage
555
588
  })
556
589
  };
557
- }
558
- return empty;
590
+ });
559
591
  }
560
592
  function skyNode() {
561
593
  const bgData = new Float32Array(8);
@@ -741,7 +773,7 @@ function bakeAtmosphere(ctx, pass, env, level0) {
741
773
  const primary = ca?.primary;
742
774
  if (!ca || !primary || primary.layerVersion !== primary.version) return false;
743
775
  const c = s.cameras.get(ca.camera);
744
- if (!c) return false;
776
+ if (!c?.packed) return false;
745
777
  const pipeline = compute(ctx, s, "bake", "shard::atmosphere::bake");
746
778
  if (!pipeline) return false;
747
779
  const gpu = ctx.gpu;
@@ -766,6 +798,12 @@ function addAtmosphereNodes(world) {
766
798
  const graph = world.resource(Graph);
767
799
  world.initResource(AtmosphereGpuResource);
768
800
  environmentBakers.set("atmosphere", bakeAtmosphere);
801
+ addRenderFeatures(world, {
802
+ name: "render/atmosphere",
803
+ description: "Atmosphere scattering LUTs, sky-view and aerial-perspective froxels, sky, composite.",
804
+ nodes: ["atmosphere/luts", "atmosphere/view", "atmosphere/sky", "post/atmosphere"],
805
+ baseline: { strategy: "LUTs, sky-view and froxel slices as fragment passes" }
806
+ });
769
807
  graph.addNode("atmosphere/luts", lutNode());
770
808
  graph.addNode("atmosphere/view", viewNode());
771
809
  graph.addNode("atmosphere/sky", skyNode());
@@ -776,5 +814,6 @@ export {
776
814
  AtmosphereGpuResource,
777
815
  LUT_LAYERS,
778
816
  addAtmosphereNodes,
817
+ packParams,
779
818
  uploadAtmospheres
780
819
  };
@@ -11,7 +11,7 @@ import { AtmosphereGpuResource, addAtmosphereNodes, uploadAtmospheres } from "./
11
11
  import { ATMOSPHERE_SHADERS } from "./atmosphere-shaders.js";
12
12
  import { Atmospheres } from "./atmosphere-state.js";
13
13
  import { extractLights } from "./lights.js";
14
- import { RenderDescribers, RenderSet, Shaders } from "./plugin.js";
14
+ import { Gpu, RenderDescribers, RenderSet, Shaders } from "./plugin.js";
15
15
  import { registerShaders } from "./shaders.js";
16
16
  import { extractCameras } from "./view.js";
17
17
  const atmospherePlugin = definePlugin({
@@ -28,13 +28,19 @@ const atmospherePlugin = definePlugin({
28
28
  );
29
29
  app.addMethod(...atmosphereMethods);
30
30
  },
31
- ready(app) {
31
+ async ready(app) {
32
+ const baseline = app.world.resource(Gpu).tier === "baseline" ? await import("./baseline/atmosphere.js") : void 0;
32
33
  registerShaders(app.world.resource(Shaders), ATMOSPHERE_SHADERS);
34
+ if (baseline) registerShaders(app.world.resource(Shaders), baseline.BASELINE_ATMOSPHERE_SHADERS);
33
35
  app.world.initResource(RenderDescribers).set(
34
36
  "atmosphere",
35
37
  (world) => describeAtmospheres(world, world.tryResource(ProfilerResource)?.all())
36
38
  );
37
39
  addAtmosphereNodes(app.world);
40
+ if (baseline) {
41
+ app.world.resource(AtmosphereGpuResource).baseline = baseline;
42
+ baseline.installAtmosphereBaseline();
43
+ }
38
44
  }
39
45
  });
40
46
  export {
@@ -0,0 +1,16 @@
1
+ import { GpuBuffer } from '@aethervtt/shard-gpu';
2
+ import { type AtmosphereGpu } from '../atmosphere-nodes.js';
3
+ import type { CameraAtmosphere } from '../atmosphere-state.js';
4
+ import type { NodeContext } from '../graph.js';
5
+ export declare const BASELINE_ATMOSPHERE_SHADERS: Record<string, string>;
6
+ /** The transmittance and multiple-scattering LUTs of every layer whose atmosphere changed. */
7
+ export declare function runLuts(ctx: NodeContext, s: AtmosphereGpu): boolean;
8
+ /** A camera's sky-view LUT and (with aerial perspective) its froxels, slice by slice. */
9
+ export declare function runView(ctx: NodeContext, s: AtmosphereGpu, ca: CameraAtmosphere, c: {
10
+ uniform: GpuBuffer;
11
+ skyView: GPUTexture;
12
+ scatter: GPUTexture;
13
+ transmittance: GPUTexture;
14
+ }): boolean;
15
+ /** Registers the environment baker: atmosphere environments bake by fragment passes too. */
16
+ export declare function installAtmosphereBaseline(): void;