@aethervtt/shard-render 0.0.1 → 0.2.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.
- package/dist/ablation.d.ts +74 -0
- package/dist/ablation.js +117 -0
- package/dist/assets.d.ts +3 -0
- package/dist/assets.js +43 -2
- package/dist/atmosphere-nodes.d.ts +9 -0
- package/dist/atmosphere-nodes.js +157 -30
- package/dist/atmosphere-plugin.js +8 -2
- package/dist/atmosphere-shaders.js +17 -5
- package/dist/baseline/atmosphere.d.ts +16 -0
- package/dist/baseline/atmosphere.js +301 -0
- package/dist/baseline/data-texture.d.ts +36 -0
- package/dist/baseline/data-texture.js +181 -0
- package/dist/baseline/environment.d.ts +14 -0
- package/dist/baseline/environment.js +368 -0
- package/dist/baseline/exposure.d.ts +25 -0
- package/dist/baseline/exposure.js +133 -0
- package/dist/baseline/lights.d.ts +33 -0
- package/dist/baseline/lights.js +133 -0
- package/dist/baseline/textures.d.ts +97 -0
- package/dist/baseline/textures.js +203 -0
- package/dist/camera.d.ts +2 -0
- package/dist/camera.js +4 -0
- package/dist/crowd.d.ts +21 -0
- package/dist/crowd.js +121 -0
- package/dist/culling-shaders.js +21 -2
- package/dist/culling.d.ts +11 -2
- package/dist/culling.js +44 -18
- package/dist/cutaway-plugin.d.ts +48 -0
- package/dist/cutaway-plugin.js +364 -0
- package/dist/cutaway.d.ts +27 -0
- package/dist/cutaway.js +49 -0
- package/dist/data-store.d.ts +69 -0
- package/dist/data-store.js +105 -0
- package/dist/debug-shaders.js +17 -3
- package/dist/debug-views.js +4 -2
- package/dist/decals-plugin.d.ts +5 -0
- package/dist/decals-plugin.js +54 -0
- package/dist/decals.d.ts +69 -0
- package/dist/decals.js +326 -0
- package/dist/deferred-shaders.js +2 -0
- package/dist/deferred.js +28 -4
- package/dist/deform.d.ts +5 -4
- package/dist/deform.js +4 -9
- package/dist/describe-plugin.d.ts +4 -2
- package/dist/describe-plugin.js +75 -3
- package/dist/display-nodes.js +37 -13
- package/dist/dynamic-resolution.d.ts +2 -0
- package/dist/dynamic-resolution.js +6 -1
- package/dist/environment-plugin.js +17 -2
- package/dist/environment-state.d.ts +7 -3
- package/dist/environment-state.js +20 -9
- package/dist/environment.js +7 -1
- package/dist/features.d.ts +49 -0
- package/dist/features.js +106 -0
- package/dist/foliage-budget.d.ts +64 -0
- package/dist/foliage-budget.js +108 -0
- package/dist/foliage-path.d.ts +19 -0
- package/dist/foliage-path.js +7 -0
- package/dist/foliage-shaders.d.ts +11 -0
- package/dist/foliage-shaders.js +504 -0
- package/dist/foliage.d.ts +194 -0
- package/dist/foliage.js +1027 -0
- package/dist/forward.d.ts +38 -2
- package/dist/forward.js +608 -186
- package/dist/fxaa.js +12 -2
- package/dist/gizmos-plugin.js +7 -0
- package/dist/gizmos.d.ts +3 -3
- package/dist/gizmos.js +11 -13
- package/dist/gpu-assets.d.ts +58 -4
- package/dist/gpu-assets.js +191 -8
- package/dist/graph.d.ts +45 -0
- package/dist/graph.js +169 -19
- package/dist/health.d.ts +58 -0
- package/dist/health.js +112 -0
- package/dist/index.d.ts +40 -11
- package/dist/index.js +343 -9
- package/dist/instances.d.ts +119 -8
- package/dist/instances.js +387 -78
- package/dist/interior-plugin.d.ts +121 -0
- package/dist/interior-plugin.js +465 -0
- package/dist/interior.d.ts +24 -0
- package/dist/interior.js +13 -0
- package/dist/layers.d.ts +35 -0
- package/dist/layers.js +49 -0
- package/dist/lens-plugin.d.ts +43 -0
- package/dist/lens-plugin.js +304 -0
- package/dist/lens.d.ts +41 -0
- package/dist/lens.js +99 -0
- package/dist/lights.d.ts +50 -5
- package/dist/lights.js +101 -22
- package/dist/material-pipelines.d.ts +37 -4
- package/dist/material-pipelines.js +102 -5
- package/dist/materials.d.ts +23 -0
- package/dist/materials.js +44 -1
- package/dist/outline-plugin.d.ts +48 -0
- package/dist/outline-plugin.js +529 -0
- package/dist/outline.d.ts +15 -0
- package/dist/outline.js +42 -0
- package/dist/overlay-registry.d.ts +3 -1
- package/dist/overlay-registry.js +3 -1
- package/dist/overlays.js +6 -2
- package/dist/perf-overlay.d.ts +9 -0
- package/dist/perf-overlay.js +125 -0
- package/dist/picking.d.ts +17 -0
- package/dist/picking.js +40 -11
- package/dist/pixel-perfect-plugin.js +10 -2
- package/dist/plugin.d.ts +69 -7
- package/dist/plugin.js +223 -25
- package/dist/post-common.d.ts +22 -2
- package/dist/post-common.js +82 -2
- package/dist/post-nodes.d.ts +7 -1
- package/dist/post-nodes.js +235 -111
- package/dist/post-plugin.js +5 -3
- package/dist/post-scene.d.ts +130 -0
- package/dist/post-scene.js +164 -0
- package/dist/post-shaders.js +85 -62
- package/dist/post.js +11 -1
- package/dist/projection.d.ts +24 -0
- package/dist/projection.js +87 -0
- package/dist/readback.d.ts +1 -0
- package/dist/readback.js +1 -0
- package/dist/render-scale.js +1 -0
- package/dist/ribbons-plugin.d.ts +5 -0
- package/dist/ribbons-plugin.js +59 -0
- package/dist/ribbons.d.ts +44 -0
- package/dist/ribbons.js +288 -0
- package/dist/scenario.d.ts +70 -0
- package/dist/scenario.js +125 -0
- package/dist/screen-effects.d.ts +97 -0
- package/dist/screen-effects.js +192 -0
- package/dist/shaders.d.ts +13 -0
- package/dist/shaders.js +189 -34
- package/dist/shadow-catcher.d.ts +9 -0
- package/dist/shadow-catcher.js +133 -0
- package/dist/shadows.d.ts +27 -2
- package/dist/shadows.js +100 -20
- package/dist/standard-fields.d.ts +1 -0
- package/dist/standard-fields.js +5 -0
- package/dist/standard.js +18 -0
- package/dist/stats.d.ts +45 -1
- package/dist/stats.js +91 -3
- package/dist/surface-model.d.ts +57 -0
- package/dist/surface-model.js +289 -0
- package/dist/surface-shaders.d.ts +3 -0
- package/dist/surface-shaders.js +160 -0
- package/dist/surface.d.ts +40 -0
- package/dist/surface.js +86 -0
- package/dist/target.d.ts +1 -13
- package/dist/target.js +1 -26
- package/dist/testing.d.ts +11 -0
- package/dist/testing.js +39 -1
- package/dist/tier.d.ts +13 -0
- package/dist/tier.js +14 -0
- package/dist/timer.d.ts +18 -1
- package/dist/timer.js +73 -20
- package/dist/variants.d.ts +37 -0
- package/dist/variants.js +104 -0
- package/dist/vfx-draw.d.ts +37 -0
- package/dist/vfx-draw.js +291 -0
- package/dist/vfx-state.d.ts +42 -0
- package/dist/vfx-state.js +81 -0
- package/dist/vfx.d.ts +69 -0
- package/dist/vfx.js +103 -0
- package/dist/view-visibility-plugin.d.ts +61 -0
- package/dist/view-visibility-plugin.js +267 -0
- package/dist/view-visibility.d.ts +28 -0
- package/dist/view-visibility.js +46 -0
- package/dist/view.d.ts +29 -1
- package/dist/view.js +57 -34
- package/package.json +23 -11
package/dist/atmosphere-nodes.js
CHANGED
|
@@ -6,10 +6,13 @@ import {
|
|
|
6
6
|
Environments,
|
|
7
7
|
environmentBakers
|
|
8
8
|
} from "./environment.js";
|
|
9
|
-
import {
|
|
9
|
+
import { addRenderFeatures } from "./features.js";
|
|
10
|
+
import { ForwardStateResource, sceneColor, viewBindGroup } 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 { roundsRg11, targetsFor } from "./post-common.js";
|
|
15
|
+
import { bindingDimension, depthReadEntry } from "./tier.js";
|
|
13
16
|
import { cameraOf } from "./view.js";
|
|
14
17
|
const LUT_LAYERS = 8;
|
|
15
18
|
const PARAMS_FLOATS = 32;
|
|
@@ -39,22 +42,26 @@ class AtmosphereGpu {
|
|
|
39
42
|
frame = 0;
|
|
40
43
|
pipelines = /* @__PURE__ */ new Map();
|
|
41
44
|
layouts;
|
|
45
|
+
/** The baseline tier's passes (0064): fragment passes, loaded only on a baseline device. */
|
|
46
|
+
baseline;
|
|
42
47
|
groups = /* @__PURE__ */ new Map();
|
|
43
48
|
ensure(gpu) {
|
|
44
49
|
if (this.generation === gpu.generation) return;
|
|
45
50
|
this.generation = gpu.generation;
|
|
46
|
-
const usage = GPUTextureUsage.TEXTURE_BINDING |
|
|
51
|
+
const usage = GPUTextureUsage.TEXTURE_BINDING | written(gpu) | GPUTextureUsage.COPY_SRC;
|
|
47
52
|
this.transmittance = gpu.device.createTexture({
|
|
48
53
|
label: "atmosphere/transmittance",
|
|
49
54
|
size: [TRANSMITTANCE_W, TRANSMITTANCE_H, LUT_LAYERS],
|
|
50
55
|
format: "rgba16float",
|
|
51
|
-
usage
|
|
56
|
+
usage,
|
|
57
|
+
...bindingDimension(gpu, "2d-array")
|
|
52
58
|
});
|
|
53
59
|
this.multiscatter = gpu.device.createTexture({
|
|
54
60
|
label: "atmosphere/multiscatter",
|
|
55
61
|
size: [MULTISCATTER_SIZE, MULTISCATTER_SIZE, LUT_LAYERS],
|
|
56
62
|
format: "rgba16float",
|
|
57
|
-
usage
|
|
63
|
+
usage,
|
|
64
|
+
...bindingDimension(gpu, "2d-array")
|
|
58
65
|
});
|
|
59
66
|
this.transmittanceArray = this.transmittance.createView({ dimension: "2d-array" });
|
|
60
67
|
this.multiscatterArray = this.multiscatter.createView({ dimension: "2d-array" });
|
|
@@ -124,6 +131,7 @@ class AtmosphereGpu {
|
|
|
124
131
|
scatter: void 0,
|
|
125
132
|
transmittance: void 0,
|
|
126
133
|
computed: -1,
|
|
134
|
+
packed: false,
|
|
127
135
|
generation: gpu.generation,
|
|
128
136
|
seen: 0
|
|
129
137
|
};
|
|
@@ -141,6 +149,9 @@ class AtmosphereGpu {
|
|
|
141
149
|
return g.group;
|
|
142
150
|
}
|
|
143
151
|
}
|
|
152
|
+
function written(gpu) {
|
|
153
|
+
return gpu.tier === "full" ? GPUTextureUsage.STORAGE_BINDING : GPUTextureUsage.RENDER_ATTACHMENT;
|
|
154
|
+
}
|
|
144
155
|
const AtmosphereGpuResource = defineResource("render/AtmosphereGpu", {
|
|
145
156
|
description: "Atmosphere LUTs, per-camera sky-view LUTs and froxels, and their pipelines.",
|
|
146
157
|
init: () => new AtmosphereGpu()
|
|
@@ -194,6 +205,7 @@ function relativeInverse(cam, out) {
|
|
|
194
205
|
}
|
|
195
206
|
function packView(ca, cam, c, out) {
|
|
196
207
|
out.fill(0);
|
|
208
|
+
c.packed = false;
|
|
197
209
|
for (const rec of ca.list) if (rec.layerVersion < 0) return;
|
|
198
210
|
const n = Math.min(ca.list.length, 4);
|
|
199
211
|
for (let i = 0; i < n; i++) packParams(ca.list[i], out, i * PARAMS_FLOATS, ca.origins, i * 4);
|
|
@@ -219,6 +231,7 @@ function packView(ca, cam, c, out) {
|
|
|
219
231
|
out[O_CAMERA + 1] = cam.position[1];
|
|
220
232
|
out[O_CAMERA + 2] = cam.position[2];
|
|
221
233
|
out[O_CAMERA + 3] = cam.exposure;
|
|
234
|
+
c.packed = true;
|
|
222
235
|
}
|
|
223
236
|
const uploadAtmospheres = defineSystem({
|
|
224
237
|
name: "render/atmosphere-upload",
|
|
@@ -259,7 +272,7 @@ function ensureViewTextures(gpu, c, ca) {
|
|
|
259
272
|
label: "atmosphere/sky-view",
|
|
260
273
|
size: [sw, sh],
|
|
261
274
|
format: "rgba16float",
|
|
262
|
-
usage: GPUTextureUsage.TEXTURE_BINDING |
|
|
275
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | written(gpu)
|
|
263
276
|
});
|
|
264
277
|
}
|
|
265
278
|
const [fx, fy, fz] = ca.froxels;
|
|
@@ -271,7 +284,7 @@ function ensureViewTextures(gpu, c, ca) {
|
|
|
271
284
|
size: [fx, fy, fz],
|
|
272
285
|
dimension: "3d",
|
|
273
286
|
format: "rgba16float",
|
|
274
|
-
usage: GPUTextureUsage.TEXTURE_BINDING |
|
|
287
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | written(gpu)
|
|
275
288
|
};
|
|
276
289
|
c.scatter = gpu.device.createTexture(desc);
|
|
277
290
|
c.transmittance = gpu.device.createTexture({
|
|
@@ -309,7 +322,7 @@ function layouts(gpu, s) {
|
|
|
309
322
|
viewDimension
|
|
310
323
|
}
|
|
311
324
|
});
|
|
312
|
-
|
|
325
|
+
const computeLayouts = gpu.tier === "full" ? {
|
|
313
326
|
transmittance: gpu.layouts.bindGroupLayout({
|
|
314
327
|
label: "atmosphere/transmittance",
|
|
315
328
|
entries: [uniform(0, C), storage(1, "2d")]
|
|
@@ -335,13 +348,22 @@ function layouts(gpu, s) {
|
|
|
335
348
|
}),
|
|
336
349
|
bake: gpu.layouts.bindGroupLayout({
|
|
337
350
|
label: "atmosphere/bake",
|
|
338
|
-
entries: [
|
|
339
|
-
|
|
351
|
+
entries: [
|
|
352
|
+
uniform(0, C),
|
|
353
|
+
array(1, C),
|
|
354
|
+
array(2, C),
|
|
355
|
+
filtering(3, C),
|
|
356
|
+
storage(4, "2d-array")
|
|
357
|
+
]
|
|
358
|
+
})
|
|
359
|
+
} : {};
|
|
360
|
+
s.layouts = {
|
|
361
|
+
...computeLayouts,
|
|
340
362
|
composite: gpu.layouts.bindGroupLayout({
|
|
341
363
|
label: "atmosphere/composite",
|
|
342
364
|
entries: [
|
|
343
365
|
{ binding: 0, visibility: F, texture: { sampleType: "unfilterable-float" } },
|
|
344
|
-
|
|
366
|
+
depthReadEntry(gpu, 1, F),
|
|
345
367
|
uniform(2, F),
|
|
346
368
|
array(3, F),
|
|
347
369
|
array(4, F),
|
|
@@ -350,6 +372,21 @@ function layouts(gpu, s) {
|
|
|
350
372
|
{ binding: 7, visibility: F, texture: { sampleType: "float", viewDimension: "3d" } }
|
|
351
373
|
]
|
|
352
374
|
}),
|
|
375
|
+
// The composite with fog folded in: fog's parameters after the haze's bindings.
|
|
376
|
+
compositeFog: gpu.layouts.bindGroupLayout({
|
|
377
|
+
label: "atmosphere/composite-fog",
|
|
378
|
+
entries: [
|
|
379
|
+
{ binding: 0, visibility: F, texture: { sampleType: "unfilterable-float" } },
|
|
380
|
+
depthReadEntry(gpu, 1, F),
|
|
381
|
+
uniform(2, F),
|
|
382
|
+
array(3, F),
|
|
383
|
+
array(4, F),
|
|
384
|
+
filtering(5, F),
|
|
385
|
+
{ binding: 6, visibility: F, texture: { sampleType: "float", viewDimension: "3d" } },
|
|
386
|
+
{ binding: 7, visibility: F, texture: { sampleType: "float", viewDimension: "3d" } },
|
|
387
|
+
uniform(8, F)
|
|
388
|
+
]
|
|
389
|
+
}),
|
|
353
390
|
viewOnly: gpu.layouts.bindGroupLayout({
|
|
354
391
|
label: "atmosphere/view",
|
|
355
392
|
entries: [uniform(0, GPUShaderStage.VERTEX | F)]
|
|
@@ -404,6 +441,10 @@ function lutNode() {
|
|
|
404
441
|
s.lutFrame = s.frame;
|
|
405
442
|
return;
|
|
406
443
|
}
|
|
444
|
+
if (s.baseline) {
|
|
445
|
+
if (s.baseline.runLuts(ctx, s)) s.lutFrame = s.frame;
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
407
448
|
const t = compute(ctx, s, "transmittance", "shard::atmosphere::transmittance_lut");
|
|
408
449
|
const m = compute(ctx, s, "multiscatter", "shard::atmosphere::multiscatter_lut");
|
|
409
450
|
if (!t || !m) return;
|
|
@@ -471,6 +512,16 @@ function viewNode() {
|
|
|
471
512
|
const c = s.cameras.get(cam.entity);
|
|
472
513
|
if (!c?.skyView || !c.scatter || !c.transmittance) return;
|
|
473
514
|
if (ca.primary.layerVersion !== ca.primary.version) return;
|
|
515
|
+
if (s.baseline) {
|
|
516
|
+
const view = {
|
|
517
|
+
uniform: c.uniform,
|
|
518
|
+
skyView: c.skyView,
|
|
519
|
+
scatter: c.scatter,
|
|
520
|
+
transmittance: c.transmittance
|
|
521
|
+
};
|
|
522
|
+
if (s.baseline.runView(ctx, s, ca, view)) c.computed = s.frame;
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
474
525
|
const sky = compute(ctx, s, "skyView", "shard::atmosphere::sky_view");
|
|
475
526
|
const aerial = compute(ctx, s, "aerial", "shard::atmosphere::aerial");
|
|
476
527
|
if (!sky || !aerial) return;
|
|
@@ -534,19 +585,17 @@ function idOf(o) {
|
|
|
534
585
|
}
|
|
535
586
|
return id;
|
|
536
587
|
}
|
|
537
|
-
let empty;
|
|
538
588
|
function emptyTextures(gpu) {
|
|
539
|
-
|
|
589
|
+
return gpu.shared("atmosphere/empty", (device) => {
|
|
540
590
|
const usage = GPUTextureUsage.TEXTURE_BINDING;
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
d2: gpu.device.createTexture({
|
|
591
|
+
return {
|
|
592
|
+
d2: device.createTexture({
|
|
544
593
|
label: "atmosphere/empty",
|
|
545
594
|
size: [1, 1],
|
|
546
595
|
format: "rgba16float",
|
|
547
596
|
usage
|
|
548
597
|
}),
|
|
549
|
-
d3:
|
|
598
|
+
d3: device.createTexture({
|
|
550
599
|
label: "atmosphere/empty-3d",
|
|
551
600
|
size: [1, 1, 1],
|
|
552
601
|
dimension: "3d",
|
|
@@ -554,8 +603,7 @@ function emptyTextures(gpu) {
|
|
|
554
603
|
usage
|
|
555
604
|
})
|
|
556
605
|
};
|
|
557
|
-
}
|
|
558
|
-
return empty;
|
|
606
|
+
});
|
|
559
607
|
}
|
|
560
608
|
function skyNode() {
|
|
561
609
|
const bgData = new Float32Array(8);
|
|
@@ -660,12 +708,31 @@ function skyNode() {
|
|
|
660
708
|
}
|
|
661
709
|
};
|
|
662
710
|
}
|
|
711
|
+
const fogScratch = new Float32Array(8);
|
|
712
|
+
const FOG_COMPOSITE_KEYS = [
|
|
713
|
+
"composite-fog",
|
|
714
|
+
"composite-fog/alpha",
|
|
715
|
+
"composite-fog/interior",
|
|
716
|
+
"composite-fog/alpha/interior",
|
|
717
|
+
"composite-fog/rg11",
|
|
718
|
+
"composite-fog/alpha/rg11",
|
|
719
|
+
"composite-fog/interior/rg11",
|
|
720
|
+
"composite-fog/alpha/interior/rg11"
|
|
721
|
+
];
|
|
663
722
|
function compositeNode() {
|
|
723
|
+
const fogBuffers = /* @__PURE__ */ new Map();
|
|
664
724
|
return {
|
|
665
725
|
kind: "render",
|
|
666
726
|
phase: RenderPhase.Post,
|
|
667
727
|
enabled: hasEffect(PostEffect.Atmosphere),
|
|
668
|
-
reads: [
|
|
728
|
+
reads: [
|
|
729
|
+
"atmosphere-in",
|
|
730
|
+
"depth",
|
|
731
|
+
"atmosphere-luts",
|
|
732
|
+
"atmosphere-view",
|
|
733
|
+
"environment",
|
|
734
|
+
"clusters"
|
|
735
|
+
],
|
|
669
736
|
writes: ["atmosphere-out"],
|
|
670
737
|
color: [{ resource: "atmosphere-out", clear: { r: 0, g: 0, b: 0, a: 1 } }],
|
|
671
738
|
run: (ctx) => {
|
|
@@ -673,30 +740,43 @@ function compositeNode() {
|
|
|
673
740
|
const ca = ctx.view.data.atmosphere;
|
|
674
741
|
const s = ctx.world.resource(AtmosphereGpuResource);
|
|
675
742
|
const c = cam ? s.cameras.get(cam.entity) : void 0;
|
|
676
|
-
const
|
|
743
|
+
const forward = ctx.world.resource(ForwardStateResource);
|
|
744
|
+
const pv = forward.views.get(ctx.view.name);
|
|
677
745
|
if (!cam || !ca || !c || !pv) return;
|
|
678
746
|
const gpu = ctx.gpu;
|
|
679
747
|
const l = layouts(gpu, s);
|
|
680
|
-
|
|
748
|
+
const fog = (cam.post.effects & PostEffect.Fog) !== 0;
|
|
749
|
+
const alpha = cam.alphaOutput;
|
|
750
|
+
const out = ctx.texture("atmosphere-out");
|
|
751
|
+
const rg11 = out.format === "rg11b10ufloat";
|
|
752
|
+
const name = fog ? FOG_COMPOSITE_KEYS[(alpha ? 1 : 0) + (forward.interiorMode !== 0 ? 2 : 0) + (rg11 ? 4 : 0)] : rg11 ? "composite/rg11" : "composite";
|
|
753
|
+
let pipeline = s.pipelines.get(name);
|
|
681
754
|
if (!pipeline) {
|
|
682
755
|
const shaders = ctx.world.resource(Shaders);
|
|
683
|
-
const fs = shaders.module(gpu, {
|
|
756
|
+
const fs = shaders.module(gpu, {
|
|
757
|
+
root: "shard::atmosphere::composite",
|
|
758
|
+
defines: { FOG: fog, TRANSPARENT: fog && alpha, RG11_ROUND: roundsRg11(gpu, out) }
|
|
759
|
+
});
|
|
684
760
|
const vs = shaders.module(gpu, { root: "shard::fullscreen" });
|
|
685
761
|
if (!fs || !vs) {
|
|
686
762
|
gpu.pipelines.skipped++;
|
|
687
763
|
return;
|
|
688
764
|
}
|
|
689
765
|
pipeline = gpu.pipelines.render({
|
|
690
|
-
label:
|
|
766
|
+
label: `atmosphere/${name}`,
|
|
691
767
|
layout: gpu.layouts.pipelineLayout({
|
|
692
|
-
label:
|
|
693
|
-
bindGroupLayouts: [l.viewOnly, l.composite]
|
|
768
|
+
label: `atmosphere/${name}`,
|
|
769
|
+
bindGroupLayouts: fog ? [forward.layouts.view, l.compositeFog] : [l.viewOnly, l.composite]
|
|
694
770
|
}),
|
|
695
771
|
vertex: { module: vs, entryPoint: "vs" },
|
|
696
|
-
fragment: {
|
|
772
|
+
fragment: {
|
|
773
|
+
module: fs,
|
|
774
|
+
entryPoint: fog ? "fs_fog" : "fs",
|
|
775
|
+
targets: targetsFor(out)
|
|
776
|
+
}
|
|
697
777
|
});
|
|
698
778
|
if (!pipeline) return;
|
|
699
|
-
s.pipelines.set(
|
|
779
|
+
s.pipelines.set(name, pipeline);
|
|
700
780
|
}
|
|
701
781
|
const input = ctx.texture("atmosphere-in");
|
|
702
782
|
const depth = ctx.texture("depth");
|
|
@@ -704,6 +784,48 @@ function compositeNode() {
|
|
|
704
784
|
const inside = ca.inside && c.computed === s.frame;
|
|
705
785
|
const scatter = inside && c.scatter ? c.scatter : e.d3;
|
|
706
786
|
const trans = inside && c.transmittance ? c.transmittance : e.d3;
|
|
787
|
+
const pass = ctx.renderPass;
|
|
788
|
+
pass.setPipeline(pipeline);
|
|
789
|
+
if (fog) {
|
|
790
|
+
let buffer = fogBuffers.get(cam.entity);
|
|
791
|
+
if (!buffer) {
|
|
792
|
+
buffer = gpu.device.createBuffer({
|
|
793
|
+
label: `${ctx.view.name}/composite-fog`,
|
|
794
|
+
size: 32,
|
|
795
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
796
|
+
});
|
|
797
|
+
fogBuffers.set(cam.entity, buffer);
|
|
798
|
+
}
|
|
799
|
+
const f = cam.post.fog;
|
|
800
|
+
fogScratch.set(f.color, 0);
|
|
801
|
+
fogScratch[4] = f.density;
|
|
802
|
+
fogScratch[5] = f.heightFalloff;
|
|
803
|
+
fogScratch[6] = f.start;
|
|
804
|
+
fogScratch[7] = f.sunScattering;
|
|
805
|
+
gpu.device.queue.writeBuffer(buffer, 0, fogScratch);
|
|
806
|
+
const fogBuffer = buffer;
|
|
807
|
+
const group2 = s.group(
|
|
808
|
+
gpu,
|
|
809
|
+
`${cam.entity}/composite-fog`,
|
|
810
|
+
`${gpu.generation}/${idOf(input)}/${idOf(depth)}/${c.uniform.version}/${idOf(scatter)}/${idOf(trans)}/${idOf(s.transmittance)}/${idOf(fogBuffer)}`,
|
|
811
|
+
l.compositeFog,
|
|
812
|
+
() => [
|
|
813
|
+
{ binding: 0, resource: input.createView() },
|
|
814
|
+
{ binding: 1, resource: depth.createView() },
|
|
815
|
+
{ binding: 2, resource: { buffer: c.uniform.buffer } },
|
|
816
|
+
{ binding: 3, resource: s.transmittanceArray },
|
|
817
|
+
{ binding: 4, resource: s.multiscatterArray },
|
|
818
|
+
{ binding: 5, resource: s.clamp },
|
|
819
|
+
{ binding: 6, resource: scatter.createView() },
|
|
820
|
+
{ binding: 7, resource: trans.createView() },
|
|
821
|
+
{ binding: 8, resource: { buffer: fogBuffer } }
|
|
822
|
+
]
|
|
823
|
+
);
|
|
824
|
+
pass.setBindGroup(0, viewBindGroup(gpu, ctx.world, pv, cam));
|
|
825
|
+
pass.setBindGroup(1, group2);
|
|
826
|
+
pass.draw(3);
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
707
829
|
const group = s.group(
|
|
708
830
|
gpu,
|
|
709
831
|
`${cam.entity}/composite`,
|
|
@@ -727,8 +849,6 @@ function compositeNode() {
|
|
|
727
849
|
l.viewOnly,
|
|
728
850
|
() => [{ binding: 0, resource: { buffer: pv.uniform.buffer } }]
|
|
729
851
|
);
|
|
730
|
-
const pass = ctx.renderPass;
|
|
731
|
-
pass.setPipeline(pipeline);
|
|
732
852
|
pass.setBindGroup(0, viewGroup);
|
|
733
853
|
pass.setBindGroup(1, group);
|
|
734
854
|
pass.draw(3);
|
|
@@ -741,7 +861,7 @@ function bakeAtmosphere(ctx, pass, env, level0) {
|
|
|
741
861
|
const primary = ca?.primary;
|
|
742
862
|
if (!ca || !primary || primary.layerVersion !== primary.version) return false;
|
|
743
863
|
const c = s.cameras.get(ca.camera);
|
|
744
|
-
if (!c) return false;
|
|
864
|
+
if (!c?.packed) return false;
|
|
745
865
|
const pipeline = compute(ctx, s, "bake", "shard::atmosphere::bake");
|
|
746
866
|
if (!pipeline) return false;
|
|
747
867
|
const gpu = ctx.gpu;
|
|
@@ -766,6 +886,12 @@ function addAtmosphereNodes(world) {
|
|
|
766
886
|
const graph = world.resource(Graph);
|
|
767
887
|
world.initResource(AtmosphereGpuResource);
|
|
768
888
|
environmentBakers.set("atmosphere", bakeAtmosphere);
|
|
889
|
+
addRenderFeatures(world, {
|
|
890
|
+
name: "render/atmosphere",
|
|
891
|
+
description: "Atmosphere scattering LUTs, sky-view and aerial-perspective froxels, sky, composite.",
|
|
892
|
+
nodes: ["atmosphere/luts", "atmosphere/view", "atmosphere/sky", "post/atmosphere"],
|
|
893
|
+
baseline: { strategy: "LUTs, sky-view and froxel slices as fragment passes" }
|
|
894
|
+
});
|
|
769
895
|
graph.addNode("atmosphere/luts", lutNode());
|
|
770
896
|
graph.addNode("atmosphere/view", viewNode());
|
|
771
897
|
graph.addNode("atmosphere/sky", skyNode());
|
|
@@ -776,5 +902,6 @@ export {
|
|
|
776
902
|
AtmosphereGpuResource,
|
|
777
903
|
LUT_LAYERS,
|
|
778
904
|
addAtmosphereNodes,
|
|
905
|
+
packParams,
|
|
779
906
|
uploadAtmospheres
|
|
780
907
|
};
|
|
@@ -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 {
|
|
@@ -518,8 +518,9 @@ struct SkyOutput {
|
|
|
518
518
|
}`,
|
|
519
519
|
"shard::atmosphere::composite": `
|
|
520
520
|
import shard::view::view;
|
|
521
|
-
import shard::post::common::uv_of;
|
|
521
|
+
import shard::post::common::{ uv_of, post_out };
|
|
522
522
|
import shard::atmosphere::{ AtmosphereView, KCD, integrate, froxel_slice, relative_at };
|
|
523
|
+
@if(FOG) import shard::post::fog::common::{ FogParams, fog_apply };
|
|
523
524
|
|
|
524
525
|
@group(1) @binding(0) var input: texture_2d<f32>;
|
|
525
526
|
@group(1) @binding(1) var depth_texture: texture_depth_2d;
|
|
@@ -529,16 +530,15 @@ import shard::atmosphere::{ AtmosphereView, KCD, integrate, froxel_slice, relati
|
|
|
529
530
|
@group(1) @binding(5) var lut_sampler: sampler;
|
|
530
531
|
@group(1) @binding(6) var ap_scatter: texture_3d<f32>;
|
|
531
532
|
@group(1) @binding(7) var ap_transmittance: texture_3d<f32>;
|
|
533
|
+
/** A view with fog too: fog follows in the same pass (\`fs_fog\`). */
|
|
534
|
+
@if(FOG) @group(1) @binding(8) var<uniform> fog: FogParams;
|
|
532
535
|
|
|
533
536
|
/**
|
|
534
537
|
* Aerial perspective on geometry: color \xD7 transmittance + in-scattering for every atmosphere the
|
|
535
538
|
* view ray crosses before the surface, far to near. The primary reads its froxels within their
|
|
536
539
|
* range; beyond it (terrain seen from orbit), and for the others, the ray is marched.
|
|
537
540
|
*/
|
|
538
|
-
|
|
539
|
-
let px = vec2i(frag.xy);
|
|
540
|
-
let c = textureLoad(input, px, 0);
|
|
541
|
-
let depth = textureLoad(depth_texture, px, 0);
|
|
541
|
+
fn haze(frag: vec4f, c: vec4f, depth: f32) -> vec4f {
|
|
542
542
|
let count = u32(atmo.info.x);
|
|
543
543
|
if (depth <= 0.0 || count == 0u) { return c; }
|
|
544
544
|
let uv = uv_of(frag.xy);
|
|
@@ -568,6 +568,18 @@ import shard::atmosphere::{ AtmosphereView, KCD, integrate, froxel_slice, relati
|
|
|
568
568
|
}
|
|
569
569
|
}
|
|
570
570
|
return vec4f(min(color, vec3f(60000.0)), c.a);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
@fragment fn fs(@builtin(position) frag: vec4f) -> @location(0) vec4f {
|
|
574
|
+
let px = vec2i(frag.xy);
|
|
575
|
+
return post_out(haze(frag, textureLoad(input, px, 0), textureLoad(depth_texture, px, 0)));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/** Aerial perspective, then height fog: the view's fog pass folded into this one. */
|
|
579
|
+
@if(FOG) @fragment fn fs_fog(@builtin(position) frag: vec4f) -> @location(0) vec4f {
|
|
580
|
+
let px = vec2i(frag.xy);
|
|
581
|
+
let depth = textureLoad(depth_texture, px, 0);
|
|
582
|
+
return post_out(fog_apply(haze(frag, textureLoad(input, px, 0), depth), uv_of(frag.xy), depth, fog));
|
|
571
583
|
}`,
|
|
572
584
|
"shard::atmosphere::bake": `
|
|
573
585
|
import shard::env::common::cube_dir;
|
|
@@ -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;
|