@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.
- 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 +57 -18
- package/dist/atmosphere-plugin.js +8 -2
- 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 +120 -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/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/deferred-shaders.js +2 -0
- package/dist/deferred.js +24 -3
- 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 +15 -4
- 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/forward.d.ts +38 -2
- package/dist/forward.js +582 -184
- 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 +11 -0
- package/dist/graph.js +30 -5
- package/dist/health.d.ts +58 -0
- package/dist/health.js +112 -0
- package/dist/index.d.ts +30 -11
- package/dist/index.js +286 -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/overlays.js +1 -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 +58 -6
- package/dist/plugin.js +191 -24
- package/dist/post-common.d.ts +2 -0
- package/dist/post-common.js +3 -0
- package/dist/post-nodes.d.ts +2 -1
- package/dist/post-nodes.js +111 -19
- package/dist/post-plugin.js +5 -3
- package/dist/post-shaders.js +51 -6
- 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/screen-effects.d.ts +97 -0
- package/dist/screen-effects.js +192 -0
- package/dist/shaders.d.ts +13 -0
- package/dist/shaders.js +131 -29
- package/dist/shadow-catcher.d.ts +9 -0
- package/dist/shadow-catcher.js +133 -0
- package/dist/shadows.d.ts +25 -1
- package/dist/shadows.js +97 -19
- package/dist/standard-fields.d.ts +1 -0
- package/dist/standard-fields.js +5 -0
- package/dist/standard.js +12 -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 +10 -0
- package/dist/testing.js +33 -1
- package/dist/tier.d.ts +13 -0
- package/dist/tier.js +14 -0
- package/dist/timer.d.ts +2 -0
- package/dist/timer.js +7 -1
- package/dist/variants.d.ts +37 -0
- package/dist/variants.js +104 -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 +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.
|
package/dist/atmosphere-nodes.js
CHANGED
|
@@ -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 |
|
|
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 |
|
|
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 |
|
|
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
|
-
|
|
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: [
|
|
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
|
-
|
|
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
|
-
|
|
573
|
+
return gpu.shared("atmosphere/empty", (device) => {
|
|
540
574
|
const usage = GPUTextureUsage.TEXTURE_BINDING;
|
|
541
|
-
|
|
542
|
-
|
|
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:
|
|
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;
|