@plasius/gpu-shared 0.1.13 → 0.1.15
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/CHANGELOG.md +26 -0
- package/README.md +70 -3
- package/dist/{chunk-NCPJWLX3.js → chunk-2GM64LB6.js} +1 -9
- package/dist/{chunk-NCPJWLX3.js.map → chunk-2GM64LB6.js.map} +1 -1
- package/dist/chunk-6SOHFUOE.js +403 -0
- package/dist/chunk-6SOHFUOE.js.map +1 -0
- package/dist/{chunk-DABW627O.js → chunk-CH3ZS5TQ.js} +7 -1
- package/dist/chunk-CH3ZS5TQ.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-DQX4DXBR.js → chunk-QVNRTWHB.js} +82 -6
- package/dist/chunk-QVNRTWHB.js.map +1 -0
- package/dist/dist-B5R2GZQR.js +1433 -0
- package/dist/dist-B5R2GZQR.js.map +1 -0
- package/dist/gltf-loader-B6VOWGBV.js +9 -0
- package/dist/index.cjs +2408 -5913
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +55 -5
- package/dist/index.js.map +1 -1
- package/dist/product-studio-runtime-BYVBUWIN.js +12 -0
- package/dist/product-studio-runtime-BYVBUWIN.js.map +1 -0
- package/dist/showcase-inline-assets-QRQKXGVX.js +8 -0
- package/dist/showcase-inline-assets-QRQKXGVX.js.map +1 -0
- package/dist/showcase-runtime-M6TEUYOG.js +3786 -0
- package/dist/showcase-runtime-M6TEUYOG.js.map +1 -0
- package/package.json +7 -10
- package/src/feature-flags.js +1 -0
- package/src/gltf-loader.js +14 -2
- package/src/index.d.ts +73 -1
- package/src/index.js +67 -0
- package/src/product-studio-runtime.js +466 -0
- package/src/showcase-runtime.js +875 -72
- package/dist/chunk-2FIFSBB4.js +0 -74
- package/dist/chunk-2FIFSBB4.js.map +0 -1
- package/dist/chunk-DABW627O.js.map +0 -1
- package/dist/chunk-DQX4DXBR.js.map +0 -1
- package/dist/gltf-loader-WAM23F37.js +0 -9
- package/dist/showcase-inline-assets-B7U7VX5H.js +0 -7
- package/dist/showcase-runtime-PN7N3FZY.js +0 -9164
- package/dist/showcase-runtime-PN7N3FZY.js.map +0 -1
- /package/dist/{gltf-loader-WAM23F37.js.map → chunk-DGUM43GV.js.map} +0 -0
- /package/dist/{showcase-inline-assets-B7U7VX5H.js.map → gltf-loader-B6VOWGBV.js.map} +0 -0
|
@@ -0,0 +1,1433 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require
|
|
3
|
+
} from "./chunk-DGUM43GV.js";
|
|
4
|
+
|
|
5
|
+
// node_modules/@plasius/gpu-lighting/dist/index.js
|
|
6
|
+
var __require2 = /* @__PURE__ */ ((x) => typeof __require !== "undefined" ? __require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
7
|
+
get: (a, b) => (typeof __require !== "undefined" ? __require : a)[b]
|
|
8
|
+
}) : x)(function(x) {
|
|
9
|
+
if (typeof __require !== "undefined") return __require.apply(this, arguments);
|
|
10
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
11
|
+
});
|
|
12
|
+
function createModuleBaseUrl(metaUrl) {
|
|
13
|
+
return Reflect.construct(URL, [String(metaUrl)]);
|
|
14
|
+
}
|
|
15
|
+
var baseUrl = (() => {
|
|
16
|
+
if (typeof import.meta.url !== "undefined") {
|
|
17
|
+
return createModuleBaseUrl(import.meta.url);
|
|
18
|
+
}
|
|
19
|
+
if (typeof __filename !== "undefined" && typeof __require2 !== "undefined") {
|
|
20
|
+
const { pathToFileURL } = __require2("url");
|
|
21
|
+
return pathToFileURL(__filename);
|
|
22
|
+
}
|
|
23
|
+
const base = typeof process !== "undefined" && process.cwd ? `file://${process.cwd()}/` : "file:///";
|
|
24
|
+
return new URL("./index.js", base);
|
|
25
|
+
})();
|
|
26
|
+
var techniqueSpecs = {
|
|
27
|
+
hybrid: {
|
|
28
|
+
description: "Lumen-inspired hybrid realtime GI and reflections with radiance cache final gather.",
|
|
29
|
+
prelude: "prelude.wgsl",
|
|
30
|
+
jobs: {
|
|
31
|
+
directLighting: "direct-lighting.job.wgsl",
|
|
32
|
+
screenTrace: "screen-trace.job.wgsl",
|
|
33
|
+
radianceCache: "radiance-cache.job.wgsl",
|
|
34
|
+
finalGather: "final-gather.job.wgsl",
|
|
35
|
+
reflectionResolve: "reflection-resolve.job.wgsl"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
pathtracer: {
|
|
39
|
+
description: "Monte Carlo path-traced reference mode with progressive accumulation and denoise stage.",
|
|
40
|
+
prelude: "prelude.wgsl",
|
|
41
|
+
jobs: {
|
|
42
|
+
pathTrace: "pathtrace.job.wgsl",
|
|
43
|
+
accumulate: "accumulate.job.wgsl",
|
|
44
|
+
denoise: "denoise.job.wgsl"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
volumetrics: {
|
|
48
|
+
description: "Froxel volumetric lighting for fog, shafts, and participating media shadows.",
|
|
49
|
+
prelude: "prelude.wgsl",
|
|
50
|
+
jobs: {
|
|
51
|
+
froxelIntegrate: "froxel-integrate.job.wgsl",
|
|
52
|
+
volumetricShadow: "volumetric-shadow.job.wgsl"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
hdri: {
|
|
56
|
+
description: "HDRI and IBL precompute passes including irradiance, specular prefilter, and BRDF LUT.",
|
|
57
|
+
prelude: "prelude.wgsl",
|
|
58
|
+
jobs: {
|
|
59
|
+
irradianceConvolution: "irradiance-convolution.job.wgsl",
|
|
60
|
+
specularPrefilter: "specular-prefilter.job.wgsl",
|
|
61
|
+
brdfLut: "brdf-lut.job.wgsl"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
function buildTechnique(name, spec) {
|
|
66
|
+
const preludeUrl = new URL(`./techniques/${name}/${spec.prelude}`, baseUrl);
|
|
67
|
+
const jobs = Object.entries(spec.jobs).map(([key, file]) => {
|
|
68
|
+
const label = `lighting.${name}.${key}`;
|
|
69
|
+
return {
|
|
70
|
+
key,
|
|
71
|
+
label,
|
|
72
|
+
url: new URL(`./techniques/${name}/${file}`, baseUrl),
|
|
73
|
+
sourceName: label
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
name,
|
|
78
|
+
description: spec.description,
|
|
79
|
+
preludeUrl,
|
|
80
|
+
jobs
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
var lightingTechniques = Object.freeze(
|
|
84
|
+
Object.fromEntries(
|
|
85
|
+
Object.entries(techniqueSpecs).map(([name, spec]) => [
|
|
86
|
+
name,
|
|
87
|
+
buildTechnique(name, spec)
|
|
88
|
+
])
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
var lightingTechniqueNames = Object.freeze(Object.keys(lightingTechniques));
|
|
92
|
+
var defaultLightingTechnique = "hybrid";
|
|
93
|
+
var profileSpecs = {
|
|
94
|
+
realtime: {
|
|
95
|
+
description: "Primary runtime profile: hybrid GI/reflections with volumetrics and HDRI/IBL.",
|
|
96
|
+
techniques: ["hybrid", "volumetrics", "hdri"]
|
|
97
|
+
},
|
|
98
|
+
hybrid: {
|
|
99
|
+
description: "Hybrid-focused profile for direct tuning of Lumen-inspired realtime passes.",
|
|
100
|
+
techniques: ["hybrid", "hdri"]
|
|
101
|
+
},
|
|
102
|
+
reference: {
|
|
103
|
+
description: "Reference quality profile: path tracing plus volumetrics and HDRI/IBL validation.",
|
|
104
|
+
techniques: ["pathtracer", "volumetrics", "hdri"]
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
function buildProfile(name, spec) {
|
|
108
|
+
return {
|
|
109
|
+
name,
|
|
110
|
+
description: spec.description,
|
|
111
|
+
techniques: [...spec.techniques]
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
var lightingProfiles = Object.freeze(
|
|
115
|
+
Object.fromEntries(
|
|
116
|
+
Object.entries(profileSpecs).map(([name, spec]) => [
|
|
117
|
+
name,
|
|
118
|
+
buildProfile(name, spec)
|
|
119
|
+
])
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
var lightingProfileNames = Object.freeze(Object.keys(lightingProfiles));
|
|
123
|
+
var defaultLightingProfile = "realtime";
|
|
124
|
+
var lightingProfileModeOrder = Object.freeze([
|
|
125
|
+
"realtime",
|
|
126
|
+
"hybrid",
|
|
127
|
+
"reference"
|
|
128
|
+
]);
|
|
129
|
+
var lightingEnvironmentPresetNames = Object.freeze([
|
|
130
|
+
"moonlit-harbor",
|
|
131
|
+
"product-studio",
|
|
132
|
+
"neutral-studio"
|
|
133
|
+
]);
|
|
134
|
+
var defaultAdaptiveLightingProfilePolicy = Object.freeze({
|
|
135
|
+
preferredProfile: "reference",
|
|
136
|
+
minimumFrameRate: 30,
|
|
137
|
+
sampleWindowSize: 4
|
|
138
|
+
});
|
|
139
|
+
var lightingDistanceBands = Object.freeze([
|
|
140
|
+
"near",
|
|
141
|
+
"mid",
|
|
142
|
+
"far",
|
|
143
|
+
"horizon"
|
|
144
|
+
]);
|
|
145
|
+
var lightingWorkerQueueClass = "lighting";
|
|
146
|
+
var lightingDebugOwner = "lighting";
|
|
147
|
+
function freezeVec4(value) {
|
|
148
|
+
return Object.freeze([value[0], value[1], value[2], value[3] ?? 1]);
|
|
149
|
+
}
|
|
150
|
+
function normalizeVector3(value, fallback) {
|
|
151
|
+
if (!Array.isArray(value) || value.length < 3) {
|
|
152
|
+
return [...fallback];
|
|
153
|
+
}
|
|
154
|
+
const vector = [
|
|
155
|
+
Number.isFinite(value[0]) ? value[0] : fallback[0],
|
|
156
|
+
Number.isFinite(value[1]) ? value[1] : fallback[1],
|
|
157
|
+
Number.isFinite(value[2]) ? value[2] : fallback[2]
|
|
158
|
+
];
|
|
159
|
+
const length = Math.hypot(vector[0], vector[1], vector[2]);
|
|
160
|
+
if (!Number.isFinite(length) || length <= 1e-6) {
|
|
161
|
+
return [...fallback];
|
|
162
|
+
}
|
|
163
|
+
return vector.map((component) => component / length);
|
|
164
|
+
}
|
|
165
|
+
function readColor(value, fallback) {
|
|
166
|
+
if (!Array.isArray(value) || value.length < 3) {
|
|
167
|
+
return freezeVec4(fallback);
|
|
168
|
+
}
|
|
169
|
+
return freezeVec4([
|
|
170
|
+
Number.isFinite(value[0]) ? Math.max(0, value[0]) : fallback[0],
|
|
171
|
+
Number.isFinite(value[1]) ? Math.max(0, value[1]) : fallback[1],
|
|
172
|
+
Number.isFinite(value[2]) ? Math.max(0, value[2]) : fallback[2],
|
|
173
|
+
Number.isFinite(value[3]) ? Math.max(0, Math.min(1, value[3])) : fallback[3] ?? 1
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
function readFinite(value, fallback) {
|
|
177
|
+
return Number.isFinite(value) ? value : fallback;
|
|
178
|
+
}
|
|
179
|
+
var environmentLightingPresets = Object.freeze({
|
|
180
|
+
"moonlit-harbor": Object.freeze({
|
|
181
|
+
preset: "moonlit-harbor",
|
|
182
|
+
environmentMode: 0,
|
|
183
|
+
environmentIntensity: 0.86,
|
|
184
|
+
exposure: 1,
|
|
185
|
+
horizonColor: freezeVec4([0.33, 0.43, 0.53, 1]),
|
|
186
|
+
zenithColor: freezeVec4([0.035, 0.07, 0.14, 1]),
|
|
187
|
+
sunDirection: Object.freeze(normalizeVector3([0.22, 0.88, 0.42], [0, 1, 0])),
|
|
188
|
+
sunColor: freezeVec4([2.1, 2.25, 2.65, 1]),
|
|
189
|
+
ambientColor: freezeVec4([0.018, 0.023, 0.03, 1])
|
|
190
|
+
}),
|
|
191
|
+
"product-studio": Object.freeze({
|
|
192
|
+
preset: "product-studio",
|
|
193
|
+
environmentMode: 1,
|
|
194
|
+
environmentIntensity: 1.05,
|
|
195
|
+
exposure: 1,
|
|
196
|
+
horizonColor: freezeVec4([0.52, 0.61, 0.65, 1]),
|
|
197
|
+
zenithColor: freezeVec4([0.18, 0.22, 0.26, 1]),
|
|
198
|
+
sunDirection: Object.freeze(normalizeVector3([0.18, 0.93, 0.24], [0, 1, 0])),
|
|
199
|
+
sunColor: freezeVec4([3.8, 3.55, 2.85, 1]),
|
|
200
|
+
ambientColor: freezeVec4([0.024, 0.027, 0.03, 1])
|
|
201
|
+
}),
|
|
202
|
+
"neutral-studio": Object.freeze({
|
|
203
|
+
preset: "neutral-studio",
|
|
204
|
+
environmentMode: 2,
|
|
205
|
+
environmentIntensity: 0.95,
|
|
206
|
+
exposure: 1,
|
|
207
|
+
horizonColor: freezeVec4([0.48, 0.53, 0.55, 1]),
|
|
208
|
+
zenithColor: freezeVec4([0.24, 0.26, 0.29, 1]),
|
|
209
|
+
sunDirection: Object.freeze(normalizeVector3([-0.24, 0.86, 0.36], [0, 1, 0])),
|
|
210
|
+
sunColor: freezeVec4([2.4, 2.35, 2.2, 1]),
|
|
211
|
+
ambientColor: freezeVec4([0.028, 0.029, 0.03, 1])
|
|
212
|
+
})
|
|
213
|
+
});
|
|
214
|
+
function resolveEnvironmentPreset(name) {
|
|
215
|
+
const presetName = typeof name === "string" && name.length > 0 ? name : "product-studio";
|
|
216
|
+
const preset = environmentLightingPresets[presetName];
|
|
217
|
+
if (!preset) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Unknown lighting environment preset "${presetName}". Expected one of: ${lightingEnvironmentPresetNames.join(", ")}.`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
return preset;
|
|
223
|
+
}
|
|
224
|
+
function estimateEnvironmentColor(config) {
|
|
225
|
+
const horizonWeight = 0.58;
|
|
226
|
+
const zenithWeight = 1 - horizonWeight;
|
|
227
|
+
const glowWeight = 0.055;
|
|
228
|
+
const intensity = Math.max(config.environmentIntensity, 1e-4);
|
|
229
|
+
return freezeVec4([
|
|
230
|
+
(config.horizonColor[0] * horizonWeight + config.zenithColor[0] * zenithWeight + config.sunColor[0] * glowWeight) * intensity,
|
|
231
|
+
(config.horizonColor[1] * horizonWeight + config.zenithColor[1] * zenithWeight + config.sunColor[1] * glowWeight) * intensity,
|
|
232
|
+
(config.horizonColor[2] * horizonWeight + config.zenithColor[2] * zenithWeight + config.sunColor[2] * glowWeight) * intensity,
|
|
233
|
+
1
|
|
234
|
+
]);
|
|
235
|
+
}
|
|
236
|
+
function createEnvironmentLightingConfig(options = {}) {
|
|
237
|
+
const preset = resolveEnvironmentPreset(options.preset ?? options.name);
|
|
238
|
+
const environmentIntensity = Math.max(
|
|
239
|
+
readFinite(options.environmentIntensity ?? options.intensity, preset.environmentIntensity),
|
|
240
|
+
1e-4
|
|
241
|
+
);
|
|
242
|
+
const config = {
|
|
243
|
+
preset: preset.preset,
|
|
244
|
+
profile: typeof options.profile === "string" ? options.profile : defaultLightingProfile,
|
|
245
|
+
environmentMode: Math.max(0, Math.trunc(readFinite(options.environmentMode, preset.environmentMode))),
|
|
246
|
+
environmentIntensity,
|
|
247
|
+
exposure: Math.max(1e-4, readFinite(options.exposure, preset.exposure)),
|
|
248
|
+
horizonColor: readColor(options.horizonColor, preset.horizonColor),
|
|
249
|
+
zenithColor: readColor(options.zenithColor, preset.zenithColor),
|
|
250
|
+
sunDirection: Object.freeze(
|
|
251
|
+
normalizeVector3(options.sunDirection, preset.sunDirection)
|
|
252
|
+
),
|
|
253
|
+
sunColor: readColor(options.sunColor, preset.sunColor),
|
|
254
|
+
ambientColor: readColor(options.ambientColor, preset.ambientColor)
|
|
255
|
+
};
|
|
256
|
+
const environmentColor = estimateEnvironmentColor(config);
|
|
257
|
+
return Object.freeze({
|
|
258
|
+
...config,
|
|
259
|
+
environmentColor,
|
|
260
|
+
wavefront: Object.freeze({
|
|
261
|
+
environmentColor,
|
|
262
|
+
ambientColor: config.ambientColor,
|
|
263
|
+
environmentLighting: Object.freeze({
|
|
264
|
+
horizonColor: config.horizonColor,
|
|
265
|
+
zenithColor: config.zenithColor,
|
|
266
|
+
sunDirection: Object.freeze([...config.sunDirection]),
|
|
267
|
+
sunColor: config.sunColor,
|
|
268
|
+
intensity: config.environmentIntensity,
|
|
269
|
+
mode: config.environmentMode,
|
|
270
|
+
exposure: config.exposure
|
|
271
|
+
})
|
|
272
|
+
})
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
function createWavefrontEnvironmentLightingOptions(options = {}) {
|
|
276
|
+
const config = createEnvironmentLightingConfig(options);
|
|
277
|
+
return Object.freeze({
|
|
278
|
+
environmentColor: config.wavefront.environmentColor,
|
|
279
|
+
ambientColor: config.wavefront.ambientColor,
|
|
280
|
+
environmentLighting: config.wavefront.environmentLighting,
|
|
281
|
+
lightingEnvironment: config
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
var lightingImportanceLevels = Object.freeze([
|
|
285
|
+
"low",
|
|
286
|
+
"medium",
|
|
287
|
+
"high",
|
|
288
|
+
"critical"
|
|
289
|
+
]);
|
|
290
|
+
var lightingBandPolicySpecs = Object.freeze({
|
|
291
|
+
near: Object.freeze({
|
|
292
|
+
primaryShadowSource: "ray-traced-primary",
|
|
293
|
+
assistShadowSources: Object.freeze(["visibility-raster", "shadow-map-assist"]),
|
|
294
|
+
temporalReuse: "balanced",
|
|
295
|
+
updateCadenceDivisor: 1,
|
|
296
|
+
liveObjectShadows: true,
|
|
297
|
+
impressionOnly: false
|
|
298
|
+
}),
|
|
299
|
+
mid: Object.freeze({
|
|
300
|
+
primaryShadowSource: "selective-raster-and-proxy",
|
|
301
|
+
assistShadowSources: Object.freeze([
|
|
302
|
+
"regional-shadow-map",
|
|
303
|
+
"proxy-caster",
|
|
304
|
+
"temporal-history"
|
|
305
|
+
]),
|
|
306
|
+
temporalReuse: "aggressive",
|
|
307
|
+
updateCadenceDivisor: 2,
|
|
308
|
+
liveObjectShadows: true,
|
|
309
|
+
impressionOnly: false
|
|
310
|
+
}),
|
|
311
|
+
far: Object.freeze({
|
|
312
|
+
primaryShadowSource: "merged-proxy-casters",
|
|
313
|
+
assistShadowSources: Object.freeze([
|
|
314
|
+
"coarse-directional",
|
|
315
|
+
"semi-static-occlusion"
|
|
316
|
+
]),
|
|
317
|
+
temporalReuse: "high",
|
|
318
|
+
updateCadenceDivisor: 8,
|
|
319
|
+
liveObjectShadows: false,
|
|
320
|
+
impressionOnly: false
|
|
321
|
+
}),
|
|
322
|
+
horizon: Object.freeze({
|
|
323
|
+
primaryShadowSource: "baked-impression",
|
|
324
|
+
assistShadowSources: Object.freeze(["atmospheric-gradient", "skyline-darkening"]),
|
|
325
|
+
temporalReuse: "baked",
|
|
326
|
+
updateCadenceDivisor: 60,
|
|
327
|
+
liveObjectShadows: false,
|
|
328
|
+
impressionOnly: true
|
|
329
|
+
})
|
|
330
|
+
});
|
|
331
|
+
function assertLightingImportance(name, value) {
|
|
332
|
+
if (!lightingImportanceLevels.includes(value)) {
|
|
333
|
+
throw new Error(
|
|
334
|
+
`${name} must be one of: ${lightingImportanceLevels.join(", ")}.`
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
return value;
|
|
338
|
+
}
|
|
339
|
+
function readPositiveIntegerOption(name, value, fallback) {
|
|
340
|
+
if (value === void 0) {
|
|
341
|
+
return fallback;
|
|
342
|
+
}
|
|
343
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0 || Math.round(value) !== value) {
|
|
344
|
+
throw new Error(`${name} must be a positive integer.`);
|
|
345
|
+
}
|
|
346
|
+
return value;
|
|
347
|
+
}
|
|
348
|
+
function resolveBandParticipation(profileName, band, importance) {
|
|
349
|
+
const referenceProfile = profileName === "reference";
|
|
350
|
+
const premiumImportance = importance === "critical" || importance === "high";
|
|
351
|
+
if (band === "near") {
|
|
352
|
+
return Object.freeze({
|
|
353
|
+
directShadows: premiumImportance ? "premium" : "selective",
|
|
354
|
+
reflections: premiumImportance ? "premium" : "selective",
|
|
355
|
+
globalIllumination: referenceProfile || importance === "critical" ? "premium" : "selective"
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
if (band === "mid") {
|
|
359
|
+
return Object.freeze({
|
|
360
|
+
directShadows: premiumImportance ? "selective" : "proxy",
|
|
361
|
+
reflections: referenceProfile && premiumImportance ? "selective" : "proxy",
|
|
362
|
+
globalIllumination: referenceProfile && importance === "critical" ? "selective" : "disabled"
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
if (band === "far") {
|
|
366
|
+
return Object.freeze({
|
|
367
|
+
directShadows: "proxy",
|
|
368
|
+
reflections: referenceProfile && importance === "critical" ? "proxy" : "disabled",
|
|
369
|
+
globalIllumination: "disabled"
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
return Object.freeze({
|
|
373
|
+
directShadows: "disabled",
|
|
374
|
+
reflections: "disabled",
|
|
375
|
+
globalIllumination: "disabled"
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
function createLightingBandPlan(options = {}) {
|
|
379
|
+
const profileName = options.profile ?? defaultLightingProfile;
|
|
380
|
+
const profile = getLightingProfile(profileName);
|
|
381
|
+
const importance = assertLightingImportance(
|
|
382
|
+
"importance",
|
|
383
|
+
options.importance ?? "high"
|
|
384
|
+
);
|
|
385
|
+
const bands = Object.freeze(
|
|
386
|
+
lightingDistanceBands.map(
|
|
387
|
+
(band) => Object.freeze({
|
|
388
|
+
band,
|
|
389
|
+
profile: profile.name,
|
|
390
|
+
importance,
|
|
391
|
+
primaryShadowSource: lightingBandPolicySpecs[band].primaryShadowSource,
|
|
392
|
+
assistShadowSources: Object.freeze([
|
|
393
|
+
...lightingBandPolicySpecs[band].assistShadowSources
|
|
394
|
+
]),
|
|
395
|
+
rtParticipation: resolveBandParticipation(profile.name, band, importance),
|
|
396
|
+
temporalReuse: lightingBandPolicySpecs[band].temporalReuse,
|
|
397
|
+
updateCadenceDivisor: lightingBandPolicySpecs[band].updateCadenceDivisor,
|
|
398
|
+
liveObjectShadows: lightingBandPolicySpecs[band].liveObjectShadows,
|
|
399
|
+
impressionOnly: lightingBandPolicySpecs[band].impressionOnly
|
|
400
|
+
})
|
|
401
|
+
)
|
|
402
|
+
);
|
|
403
|
+
return Object.freeze({
|
|
404
|
+
schemaVersion: 1,
|
|
405
|
+
owner: lightingDebugOwner,
|
|
406
|
+
profile: profile.name,
|
|
407
|
+
importance,
|
|
408
|
+
techniques: Object.freeze([...profile.techniques]),
|
|
409
|
+
bands
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
var lightingProfileModeEstimatedCostMs = Object.freeze({
|
|
413
|
+
realtime: 4.5,
|
|
414
|
+
hybrid: 7.5,
|
|
415
|
+
reference: 12.5
|
|
416
|
+
});
|
|
417
|
+
function createLightingProfileModeLadder(options = {}) {
|
|
418
|
+
const moduleId = typeof options.id === "string" && options.id.trim().length > 0 ? options.id.trim() : "lighting-profile-mode";
|
|
419
|
+
const preferredProfile = getLightingProfile(
|
|
420
|
+
options.preferredProfile ?? defaultAdaptiveLightingProfilePolicy.preferredProfile
|
|
421
|
+
).name;
|
|
422
|
+
const initialProfile = getLightingProfile(
|
|
423
|
+
options.initialProfile ?? preferredProfile
|
|
424
|
+
).name;
|
|
425
|
+
const minimumFrameRate = readPositiveIntegerOption(
|
|
426
|
+
"minimumFrameRate",
|
|
427
|
+
options.minimumFrameRate,
|
|
428
|
+
defaultAdaptiveLightingProfilePolicy.minimumFrameRate
|
|
429
|
+
);
|
|
430
|
+
const sampleWindowSize = readPositiveIntegerOption(
|
|
431
|
+
"sampleWindowSize",
|
|
432
|
+
options.sampleWindowSize,
|
|
433
|
+
defaultAdaptiveLightingProfilePolicy.sampleWindowSize
|
|
434
|
+
);
|
|
435
|
+
const importance = assertLightingImportance(
|
|
436
|
+
"importance",
|
|
437
|
+
options.importance ?? "high"
|
|
438
|
+
);
|
|
439
|
+
const moduleImportance = assertLightingImportance(
|
|
440
|
+
"moduleImportance",
|
|
441
|
+
options.moduleImportance ?? "critical"
|
|
442
|
+
);
|
|
443
|
+
const levels = Object.freeze(
|
|
444
|
+
lightingProfileModeOrder.map((profileName) => {
|
|
445
|
+
const profile = getLightingProfile(profileName);
|
|
446
|
+
return Object.freeze({
|
|
447
|
+
id: profile.name,
|
|
448
|
+
estimatedCostMs: lightingProfileModeEstimatedCostMs[profile.name],
|
|
449
|
+
config: Object.freeze({
|
|
450
|
+
profile: profile.name,
|
|
451
|
+
description: profile.description,
|
|
452
|
+
techniques: Object.freeze([...profile.techniques]),
|
|
453
|
+
lightingBandPlan: createLightingBandPlan({
|
|
454
|
+
profile: profile.name,
|
|
455
|
+
importance
|
|
456
|
+
}),
|
|
457
|
+
policy: Object.freeze({
|
|
458
|
+
preferredProfile,
|
|
459
|
+
minimumFrameRate,
|
|
460
|
+
sampleWindowSize
|
|
461
|
+
})
|
|
462
|
+
})
|
|
463
|
+
});
|
|
464
|
+
})
|
|
465
|
+
);
|
|
466
|
+
return Object.freeze({
|
|
467
|
+
id: moduleId,
|
|
468
|
+
domain: "lighting",
|
|
469
|
+
authority: "visual",
|
|
470
|
+
importance: moduleImportance,
|
|
471
|
+
initialLevel: initialProfile,
|
|
472
|
+
levels,
|
|
473
|
+
target: Object.freeze({
|
|
474
|
+
minimumFrameRate,
|
|
475
|
+
maximumFrameRate: minimumFrameRate,
|
|
476
|
+
preferredFrameRates: Object.freeze([minimumFrameRate])
|
|
477
|
+
}),
|
|
478
|
+
adaptation: Object.freeze({
|
|
479
|
+
sampleWindowSize,
|
|
480
|
+
minimumSamplesBeforeAdjustment: sampleWindowSize,
|
|
481
|
+
degradeCooldownFrames: 1,
|
|
482
|
+
upgradeCooldownFrames: sampleWindowSize,
|
|
483
|
+
minStableFramesForRecovery: sampleWindowSize
|
|
484
|
+
}),
|
|
485
|
+
policy: Object.freeze({
|
|
486
|
+
preferredProfile,
|
|
487
|
+
minimumFrameRate,
|
|
488
|
+
sampleWindowSize
|
|
489
|
+
})
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
function buildWorkerBudgetLevels(jobType, queueClass, presets) {
|
|
493
|
+
return Object.freeze([
|
|
494
|
+
Object.freeze({
|
|
495
|
+
id: "low",
|
|
496
|
+
estimatedCostMs: presets.low.estimatedCostMs,
|
|
497
|
+
config: Object.freeze({
|
|
498
|
+
maxDispatchesPerFrame: presets.low.maxDispatchesPerFrame,
|
|
499
|
+
maxJobsPerDispatch: presets.low.maxJobsPerDispatch,
|
|
500
|
+
cadenceDivisor: presets.low.cadenceDivisor,
|
|
501
|
+
workgroupScale: presets.low.workgroupScale,
|
|
502
|
+
maxQueueDepth: presets.low.maxQueueDepth,
|
|
503
|
+
metadata: Object.freeze({
|
|
504
|
+
owner: lightingDebugOwner,
|
|
505
|
+
queueClass,
|
|
506
|
+
jobType,
|
|
507
|
+
quality: "low"
|
|
508
|
+
})
|
|
509
|
+
})
|
|
510
|
+
}),
|
|
511
|
+
Object.freeze({
|
|
512
|
+
id: "medium",
|
|
513
|
+
estimatedCostMs: presets.medium.estimatedCostMs,
|
|
514
|
+
config: Object.freeze({
|
|
515
|
+
maxDispatchesPerFrame: presets.medium.maxDispatchesPerFrame,
|
|
516
|
+
maxJobsPerDispatch: presets.medium.maxJobsPerDispatch,
|
|
517
|
+
cadenceDivisor: presets.medium.cadenceDivisor,
|
|
518
|
+
workgroupScale: presets.medium.workgroupScale,
|
|
519
|
+
maxQueueDepth: presets.medium.maxQueueDepth,
|
|
520
|
+
metadata: Object.freeze({
|
|
521
|
+
owner: lightingDebugOwner,
|
|
522
|
+
queueClass,
|
|
523
|
+
jobType,
|
|
524
|
+
quality: "medium"
|
|
525
|
+
})
|
|
526
|
+
})
|
|
527
|
+
}),
|
|
528
|
+
Object.freeze({
|
|
529
|
+
id: "high",
|
|
530
|
+
estimatedCostMs: presets.high.estimatedCostMs,
|
|
531
|
+
config: Object.freeze({
|
|
532
|
+
maxDispatchesPerFrame: presets.high.maxDispatchesPerFrame,
|
|
533
|
+
maxJobsPerDispatch: presets.high.maxJobsPerDispatch,
|
|
534
|
+
cadenceDivisor: presets.high.cadenceDivisor,
|
|
535
|
+
workgroupScale: presets.high.workgroupScale,
|
|
536
|
+
maxQueueDepth: presets.high.maxQueueDepth,
|
|
537
|
+
metadata: Object.freeze({
|
|
538
|
+
owner: lightingDebugOwner,
|
|
539
|
+
queueClass,
|
|
540
|
+
jobType,
|
|
541
|
+
quality: "high"
|
|
542
|
+
})
|
|
543
|
+
})
|
|
544
|
+
})
|
|
545
|
+
]);
|
|
546
|
+
}
|
|
547
|
+
var lightingWorkerSpecPresets = {
|
|
548
|
+
hybrid: {
|
|
549
|
+
suggestedAllocationIds: [
|
|
550
|
+
"lighting.hybrid.radiance-cache",
|
|
551
|
+
"lighting.hybrid.reflection-history",
|
|
552
|
+
"lighting.hybrid.shadow-atlas"
|
|
553
|
+
],
|
|
554
|
+
jobs: {
|
|
555
|
+
directLighting: {
|
|
556
|
+
domain: "lighting",
|
|
557
|
+
importance: "high",
|
|
558
|
+
levels: buildWorkerBudgetLevels(
|
|
559
|
+
"lighting.hybrid.directLighting",
|
|
560
|
+
lightingWorkerQueueClass,
|
|
561
|
+
{
|
|
562
|
+
low: {
|
|
563
|
+
estimatedCostMs: 0.5,
|
|
564
|
+
maxDispatchesPerFrame: 1,
|
|
565
|
+
maxJobsPerDispatch: 64,
|
|
566
|
+
cadenceDivisor: 2,
|
|
567
|
+
workgroupScale: 0.5,
|
|
568
|
+
maxQueueDepth: 128
|
|
569
|
+
},
|
|
570
|
+
medium: {
|
|
571
|
+
estimatedCostMs: 0.9,
|
|
572
|
+
maxDispatchesPerFrame: 1,
|
|
573
|
+
maxJobsPerDispatch: 128,
|
|
574
|
+
cadenceDivisor: 1,
|
|
575
|
+
workgroupScale: 0.75,
|
|
576
|
+
maxQueueDepth: 256
|
|
577
|
+
},
|
|
578
|
+
high: {
|
|
579
|
+
estimatedCostMs: 1.2,
|
|
580
|
+
maxDispatchesPerFrame: 2,
|
|
581
|
+
maxJobsPerDispatch: 256,
|
|
582
|
+
cadenceDivisor: 1,
|
|
583
|
+
workgroupScale: 1,
|
|
584
|
+
maxQueueDepth: 512
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
),
|
|
588
|
+
suggestedAllocationIds: ["lighting.hybrid.shadow-atlas"]
|
|
589
|
+
},
|
|
590
|
+
screenTrace: {
|
|
591
|
+
domain: "reflections",
|
|
592
|
+
importance: "high",
|
|
593
|
+
levels: buildWorkerBudgetLevels(
|
|
594
|
+
"lighting.hybrid.screenTrace",
|
|
595
|
+
lightingWorkerQueueClass,
|
|
596
|
+
{
|
|
597
|
+
low: {
|
|
598
|
+
estimatedCostMs: 0.8,
|
|
599
|
+
maxDispatchesPerFrame: 1,
|
|
600
|
+
maxJobsPerDispatch: 32,
|
|
601
|
+
cadenceDivisor: 3,
|
|
602
|
+
workgroupScale: 0.4,
|
|
603
|
+
maxQueueDepth: 96
|
|
604
|
+
},
|
|
605
|
+
medium: {
|
|
606
|
+
estimatedCostMs: 1.5,
|
|
607
|
+
maxDispatchesPerFrame: 1,
|
|
608
|
+
maxJobsPerDispatch: 96,
|
|
609
|
+
cadenceDivisor: 2,
|
|
610
|
+
workgroupScale: 0.7,
|
|
611
|
+
maxQueueDepth: 192
|
|
612
|
+
},
|
|
613
|
+
high: {
|
|
614
|
+
estimatedCostMs: 2.2,
|
|
615
|
+
maxDispatchesPerFrame: 2,
|
|
616
|
+
maxJobsPerDispatch: 192,
|
|
617
|
+
cadenceDivisor: 1,
|
|
618
|
+
workgroupScale: 1,
|
|
619
|
+
maxQueueDepth: 384
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
),
|
|
623
|
+
suggestedAllocationIds: ["lighting.hybrid.reflection-history"]
|
|
624
|
+
},
|
|
625
|
+
radianceCache: {
|
|
626
|
+
domain: "lighting",
|
|
627
|
+
importance: "high",
|
|
628
|
+
levels: buildWorkerBudgetLevels(
|
|
629
|
+
"lighting.hybrid.radianceCache",
|
|
630
|
+
lightingWorkerQueueClass,
|
|
631
|
+
{
|
|
632
|
+
low: {
|
|
633
|
+
estimatedCostMs: 0.7,
|
|
634
|
+
maxDispatchesPerFrame: 1,
|
|
635
|
+
maxJobsPerDispatch: 32,
|
|
636
|
+
cadenceDivisor: 2,
|
|
637
|
+
workgroupScale: 0.5,
|
|
638
|
+
maxQueueDepth: 96
|
|
639
|
+
},
|
|
640
|
+
medium: {
|
|
641
|
+
estimatedCostMs: 1.2,
|
|
642
|
+
maxDispatchesPerFrame: 1,
|
|
643
|
+
maxJobsPerDispatch: 64,
|
|
644
|
+
cadenceDivisor: 1,
|
|
645
|
+
workgroupScale: 0.75,
|
|
646
|
+
maxQueueDepth: 192
|
|
647
|
+
},
|
|
648
|
+
high: {
|
|
649
|
+
estimatedCostMs: 1.8,
|
|
650
|
+
maxDispatchesPerFrame: 2,
|
|
651
|
+
maxJobsPerDispatch: 128,
|
|
652
|
+
cadenceDivisor: 1,
|
|
653
|
+
workgroupScale: 1,
|
|
654
|
+
maxQueueDepth: 256
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
),
|
|
658
|
+
suggestedAllocationIds: ["lighting.hybrid.radiance-cache"]
|
|
659
|
+
},
|
|
660
|
+
finalGather: {
|
|
661
|
+
domain: "lighting",
|
|
662
|
+
importance: "critical",
|
|
663
|
+
levels: buildWorkerBudgetLevels(
|
|
664
|
+
"lighting.hybrid.finalGather",
|
|
665
|
+
lightingWorkerQueueClass,
|
|
666
|
+
{
|
|
667
|
+
low: {
|
|
668
|
+
estimatedCostMs: 1,
|
|
669
|
+
maxDispatchesPerFrame: 1,
|
|
670
|
+
maxJobsPerDispatch: 48,
|
|
671
|
+
cadenceDivisor: 2,
|
|
672
|
+
workgroupScale: 0.5,
|
|
673
|
+
maxQueueDepth: 128
|
|
674
|
+
},
|
|
675
|
+
medium: {
|
|
676
|
+
estimatedCostMs: 1.8,
|
|
677
|
+
maxDispatchesPerFrame: 1,
|
|
678
|
+
maxJobsPerDispatch: 96,
|
|
679
|
+
cadenceDivisor: 1,
|
|
680
|
+
workgroupScale: 0.75,
|
|
681
|
+
maxQueueDepth: 256
|
|
682
|
+
},
|
|
683
|
+
high: {
|
|
684
|
+
estimatedCostMs: 2.6,
|
|
685
|
+
maxDispatchesPerFrame: 2,
|
|
686
|
+
maxJobsPerDispatch: 192,
|
|
687
|
+
cadenceDivisor: 1,
|
|
688
|
+
workgroupScale: 1,
|
|
689
|
+
maxQueueDepth: 384
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
),
|
|
693
|
+
suggestedAllocationIds: [
|
|
694
|
+
"lighting.hybrid.radiance-cache",
|
|
695
|
+
"lighting.hybrid.reflection-history"
|
|
696
|
+
]
|
|
697
|
+
},
|
|
698
|
+
reflectionResolve: {
|
|
699
|
+
domain: "reflections",
|
|
700
|
+
importance: "high",
|
|
701
|
+
levels: buildWorkerBudgetLevels(
|
|
702
|
+
"lighting.hybrid.reflectionResolve",
|
|
703
|
+
lightingWorkerQueueClass,
|
|
704
|
+
{
|
|
705
|
+
low: {
|
|
706
|
+
estimatedCostMs: 0.4,
|
|
707
|
+
maxDispatchesPerFrame: 1,
|
|
708
|
+
maxJobsPerDispatch: 32,
|
|
709
|
+
cadenceDivisor: 2,
|
|
710
|
+
workgroupScale: 0.5,
|
|
711
|
+
maxQueueDepth: 96
|
|
712
|
+
},
|
|
713
|
+
medium: {
|
|
714
|
+
estimatedCostMs: 0.8,
|
|
715
|
+
maxDispatchesPerFrame: 1,
|
|
716
|
+
maxJobsPerDispatch: 64,
|
|
717
|
+
cadenceDivisor: 1,
|
|
718
|
+
workgroupScale: 0.75,
|
|
719
|
+
maxQueueDepth: 192
|
|
720
|
+
},
|
|
721
|
+
high: {
|
|
722
|
+
estimatedCostMs: 1.2,
|
|
723
|
+
maxDispatchesPerFrame: 1,
|
|
724
|
+
maxJobsPerDispatch: 128,
|
|
725
|
+
cadenceDivisor: 1,
|
|
726
|
+
workgroupScale: 1,
|
|
727
|
+
maxQueueDepth: 256
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
),
|
|
731
|
+
suggestedAllocationIds: ["lighting.hybrid.reflection-history"]
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
pathtracer: {
|
|
736
|
+
suggestedAllocationIds: [
|
|
737
|
+
"lighting.pathtracer.path-state",
|
|
738
|
+
"lighting.pathtracer.accumulation",
|
|
739
|
+
"lighting.pathtracer.denoise-history"
|
|
740
|
+
],
|
|
741
|
+
jobs: {
|
|
742
|
+
pathTrace: {
|
|
743
|
+
domain: "lighting",
|
|
744
|
+
importance: "critical",
|
|
745
|
+
levels: buildWorkerBudgetLevels(
|
|
746
|
+
"lighting.pathtracer.pathTrace",
|
|
747
|
+
lightingWorkerQueueClass,
|
|
748
|
+
{
|
|
749
|
+
low: {
|
|
750
|
+
estimatedCostMs: 1.2,
|
|
751
|
+
maxDispatchesPerFrame: 1,
|
|
752
|
+
maxJobsPerDispatch: 16,
|
|
753
|
+
cadenceDivisor: 3,
|
|
754
|
+
workgroupScale: 0.45,
|
|
755
|
+
maxQueueDepth: 48
|
|
756
|
+
},
|
|
757
|
+
medium: {
|
|
758
|
+
estimatedCostMs: 2.3,
|
|
759
|
+
maxDispatchesPerFrame: 1,
|
|
760
|
+
maxJobsPerDispatch: 32,
|
|
761
|
+
cadenceDivisor: 2,
|
|
762
|
+
workgroupScale: 0.7,
|
|
763
|
+
maxQueueDepth: 96
|
|
764
|
+
},
|
|
765
|
+
high: {
|
|
766
|
+
estimatedCostMs: 3.8,
|
|
767
|
+
maxDispatchesPerFrame: 2,
|
|
768
|
+
maxJobsPerDispatch: 64,
|
|
769
|
+
cadenceDivisor: 1,
|
|
770
|
+
workgroupScale: 1,
|
|
771
|
+
maxQueueDepth: 128
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
),
|
|
775
|
+
suggestedAllocationIds: ["lighting.pathtracer.path-state"]
|
|
776
|
+
},
|
|
777
|
+
accumulate: {
|
|
778
|
+
domain: "lighting",
|
|
779
|
+
importance: "medium",
|
|
780
|
+
levels: buildWorkerBudgetLevels(
|
|
781
|
+
"lighting.pathtracer.accumulate",
|
|
782
|
+
lightingWorkerQueueClass,
|
|
783
|
+
{
|
|
784
|
+
low: {
|
|
785
|
+
estimatedCostMs: 0.4,
|
|
786
|
+
maxDispatchesPerFrame: 1,
|
|
787
|
+
maxJobsPerDispatch: 16,
|
|
788
|
+
cadenceDivisor: 2,
|
|
789
|
+
workgroupScale: 0.5,
|
|
790
|
+
maxQueueDepth: 32
|
|
791
|
+
},
|
|
792
|
+
medium: {
|
|
793
|
+
estimatedCostMs: 0.8,
|
|
794
|
+
maxDispatchesPerFrame: 1,
|
|
795
|
+
maxJobsPerDispatch: 32,
|
|
796
|
+
cadenceDivisor: 1,
|
|
797
|
+
workgroupScale: 0.75,
|
|
798
|
+
maxQueueDepth: 64
|
|
799
|
+
},
|
|
800
|
+
high: {
|
|
801
|
+
estimatedCostMs: 1.1,
|
|
802
|
+
maxDispatchesPerFrame: 1,
|
|
803
|
+
maxJobsPerDispatch: 64,
|
|
804
|
+
cadenceDivisor: 1,
|
|
805
|
+
workgroupScale: 1,
|
|
806
|
+
maxQueueDepth: 96
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
),
|
|
810
|
+
suggestedAllocationIds: ["lighting.pathtracer.accumulation"]
|
|
811
|
+
},
|
|
812
|
+
denoise: {
|
|
813
|
+
domain: "post-processing",
|
|
814
|
+
importance: "high",
|
|
815
|
+
levels: buildWorkerBudgetLevels(
|
|
816
|
+
"lighting.pathtracer.denoise",
|
|
817
|
+
lightingWorkerQueueClass,
|
|
818
|
+
{
|
|
819
|
+
low: {
|
|
820
|
+
estimatedCostMs: 0.4,
|
|
821
|
+
maxDispatchesPerFrame: 1,
|
|
822
|
+
maxJobsPerDispatch: 16,
|
|
823
|
+
cadenceDivisor: 2,
|
|
824
|
+
workgroupScale: 0.5,
|
|
825
|
+
maxQueueDepth: 32
|
|
826
|
+
},
|
|
827
|
+
medium: {
|
|
828
|
+
estimatedCostMs: 0.9,
|
|
829
|
+
maxDispatchesPerFrame: 1,
|
|
830
|
+
maxJobsPerDispatch: 32,
|
|
831
|
+
cadenceDivisor: 1,
|
|
832
|
+
workgroupScale: 0.75,
|
|
833
|
+
maxQueueDepth: 64
|
|
834
|
+
},
|
|
835
|
+
high: {
|
|
836
|
+
estimatedCostMs: 1.4,
|
|
837
|
+
maxDispatchesPerFrame: 1,
|
|
838
|
+
maxJobsPerDispatch: 64,
|
|
839
|
+
cadenceDivisor: 1,
|
|
840
|
+
workgroupScale: 1,
|
|
841
|
+
maxQueueDepth: 96
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
),
|
|
845
|
+
suggestedAllocationIds: ["lighting.pathtracer.denoise-history"]
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
},
|
|
849
|
+
volumetrics: {
|
|
850
|
+
suggestedAllocationIds: [
|
|
851
|
+
"lighting.volumetrics.froxel-grid",
|
|
852
|
+
"lighting.volumetrics.shadow-history"
|
|
853
|
+
],
|
|
854
|
+
jobs: {
|
|
855
|
+
froxelIntegrate: {
|
|
856
|
+
domain: "volumetrics",
|
|
857
|
+
importance: "high",
|
|
858
|
+
levels: buildWorkerBudgetLevels(
|
|
859
|
+
"lighting.volumetrics.froxelIntegrate",
|
|
860
|
+
lightingWorkerQueueClass,
|
|
861
|
+
{
|
|
862
|
+
low: {
|
|
863
|
+
estimatedCostMs: 0.6,
|
|
864
|
+
maxDispatchesPerFrame: 1,
|
|
865
|
+
maxJobsPerDispatch: 32,
|
|
866
|
+
cadenceDivisor: 2,
|
|
867
|
+
workgroupScale: 0.5,
|
|
868
|
+
maxQueueDepth: 96
|
|
869
|
+
},
|
|
870
|
+
medium: {
|
|
871
|
+
estimatedCostMs: 1.1,
|
|
872
|
+
maxDispatchesPerFrame: 1,
|
|
873
|
+
maxJobsPerDispatch: 64,
|
|
874
|
+
cadenceDivisor: 1,
|
|
875
|
+
workgroupScale: 0.75,
|
|
876
|
+
maxQueueDepth: 192
|
|
877
|
+
},
|
|
878
|
+
high: {
|
|
879
|
+
estimatedCostMs: 1.7,
|
|
880
|
+
maxDispatchesPerFrame: 2,
|
|
881
|
+
maxJobsPerDispatch: 128,
|
|
882
|
+
cadenceDivisor: 1,
|
|
883
|
+
workgroupScale: 1,
|
|
884
|
+
maxQueueDepth: 256
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
),
|
|
888
|
+
suggestedAllocationIds: ["lighting.volumetrics.froxel-grid"]
|
|
889
|
+
},
|
|
890
|
+
volumetricShadow: {
|
|
891
|
+
domain: "volumetrics",
|
|
892
|
+
importance: "high",
|
|
893
|
+
levels: buildWorkerBudgetLevels(
|
|
894
|
+
"lighting.volumetrics.volumetricShadow",
|
|
895
|
+
lightingWorkerQueueClass,
|
|
896
|
+
{
|
|
897
|
+
low: {
|
|
898
|
+
estimatedCostMs: 0.5,
|
|
899
|
+
maxDispatchesPerFrame: 1,
|
|
900
|
+
maxJobsPerDispatch: 24,
|
|
901
|
+
cadenceDivisor: 2,
|
|
902
|
+
workgroupScale: 0.5,
|
|
903
|
+
maxQueueDepth: 64
|
|
904
|
+
},
|
|
905
|
+
medium: {
|
|
906
|
+
estimatedCostMs: 0.9,
|
|
907
|
+
maxDispatchesPerFrame: 1,
|
|
908
|
+
maxJobsPerDispatch: 48,
|
|
909
|
+
cadenceDivisor: 1,
|
|
910
|
+
workgroupScale: 0.75,
|
|
911
|
+
maxQueueDepth: 128
|
|
912
|
+
},
|
|
913
|
+
high: {
|
|
914
|
+
estimatedCostMs: 1.3,
|
|
915
|
+
maxDispatchesPerFrame: 1,
|
|
916
|
+
maxJobsPerDispatch: 96,
|
|
917
|
+
cadenceDivisor: 1,
|
|
918
|
+
workgroupScale: 1,
|
|
919
|
+
maxQueueDepth: 192
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
),
|
|
923
|
+
suggestedAllocationIds: ["lighting.volumetrics.shadow-history"]
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
},
|
|
927
|
+
hdri: {
|
|
928
|
+
suggestedAllocationIds: [
|
|
929
|
+
"lighting.hdri.cubemap",
|
|
930
|
+
"lighting.hdri.prefilter",
|
|
931
|
+
"lighting.hdri.brdf-lut"
|
|
932
|
+
],
|
|
933
|
+
jobs: {
|
|
934
|
+
irradianceConvolution: {
|
|
935
|
+
domain: "lighting",
|
|
936
|
+
importance: "medium",
|
|
937
|
+
levels: buildWorkerBudgetLevels(
|
|
938
|
+
"lighting.hdri.irradianceConvolution",
|
|
939
|
+
lightingWorkerQueueClass,
|
|
940
|
+
{
|
|
941
|
+
low: {
|
|
942
|
+
estimatedCostMs: 0.3,
|
|
943
|
+
maxDispatchesPerFrame: 1,
|
|
944
|
+
maxJobsPerDispatch: 8,
|
|
945
|
+
cadenceDivisor: 3,
|
|
946
|
+
workgroupScale: 0.5,
|
|
947
|
+
maxQueueDepth: 16
|
|
948
|
+
},
|
|
949
|
+
medium: {
|
|
950
|
+
estimatedCostMs: 0.5,
|
|
951
|
+
maxDispatchesPerFrame: 1,
|
|
952
|
+
maxJobsPerDispatch: 16,
|
|
953
|
+
cadenceDivisor: 2,
|
|
954
|
+
workgroupScale: 0.75,
|
|
955
|
+
maxQueueDepth: 32
|
|
956
|
+
},
|
|
957
|
+
high: {
|
|
958
|
+
estimatedCostMs: 0.8,
|
|
959
|
+
maxDispatchesPerFrame: 1,
|
|
960
|
+
maxJobsPerDispatch: 32,
|
|
961
|
+
cadenceDivisor: 1,
|
|
962
|
+
workgroupScale: 1,
|
|
963
|
+
maxQueueDepth: 48
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
),
|
|
967
|
+
suggestedAllocationIds: ["lighting.hdri.cubemap"]
|
|
968
|
+
},
|
|
969
|
+
specularPrefilter: {
|
|
970
|
+
domain: "lighting",
|
|
971
|
+
importance: "medium",
|
|
972
|
+
levels: buildWorkerBudgetLevels(
|
|
973
|
+
"lighting.hdri.specularPrefilter",
|
|
974
|
+
lightingWorkerQueueClass,
|
|
975
|
+
{
|
|
976
|
+
low: {
|
|
977
|
+
estimatedCostMs: 0.4,
|
|
978
|
+
maxDispatchesPerFrame: 1,
|
|
979
|
+
maxJobsPerDispatch: 8,
|
|
980
|
+
cadenceDivisor: 3,
|
|
981
|
+
workgroupScale: 0.5,
|
|
982
|
+
maxQueueDepth: 16
|
|
983
|
+
},
|
|
984
|
+
medium: {
|
|
985
|
+
estimatedCostMs: 0.7,
|
|
986
|
+
maxDispatchesPerFrame: 1,
|
|
987
|
+
maxJobsPerDispatch: 16,
|
|
988
|
+
cadenceDivisor: 2,
|
|
989
|
+
workgroupScale: 0.75,
|
|
990
|
+
maxQueueDepth: 32
|
|
991
|
+
},
|
|
992
|
+
high: {
|
|
993
|
+
estimatedCostMs: 1,
|
|
994
|
+
maxDispatchesPerFrame: 1,
|
|
995
|
+
maxJobsPerDispatch: 32,
|
|
996
|
+
cadenceDivisor: 1,
|
|
997
|
+
workgroupScale: 1,
|
|
998
|
+
maxQueueDepth: 48
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
),
|
|
1002
|
+
suggestedAllocationIds: ["lighting.hdri.prefilter"]
|
|
1003
|
+
},
|
|
1004
|
+
brdfLut: {
|
|
1005
|
+
domain: "lighting",
|
|
1006
|
+
importance: "low",
|
|
1007
|
+
levels: buildWorkerBudgetLevels(
|
|
1008
|
+
"lighting.hdri.brdfLut",
|
|
1009
|
+
lightingWorkerQueueClass,
|
|
1010
|
+
{
|
|
1011
|
+
low: {
|
|
1012
|
+
estimatedCostMs: 0.2,
|
|
1013
|
+
maxDispatchesPerFrame: 1,
|
|
1014
|
+
maxJobsPerDispatch: 4,
|
|
1015
|
+
cadenceDivisor: 3,
|
|
1016
|
+
workgroupScale: 0.5,
|
|
1017
|
+
maxQueueDepth: 8
|
|
1018
|
+
},
|
|
1019
|
+
medium: {
|
|
1020
|
+
estimatedCostMs: 0.4,
|
|
1021
|
+
maxDispatchesPerFrame: 1,
|
|
1022
|
+
maxJobsPerDispatch: 8,
|
|
1023
|
+
cadenceDivisor: 2,
|
|
1024
|
+
workgroupScale: 0.75,
|
|
1025
|
+
maxQueueDepth: 16
|
|
1026
|
+
},
|
|
1027
|
+
high: {
|
|
1028
|
+
estimatedCostMs: 0.6,
|
|
1029
|
+
maxDispatchesPerFrame: 1,
|
|
1030
|
+
maxJobsPerDispatch: 16,
|
|
1031
|
+
cadenceDivisor: 1,
|
|
1032
|
+
workgroupScale: 1,
|
|
1033
|
+
maxQueueDepth: 24
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
),
|
|
1037
|
+
suggestedAllocationIds: ["lighting.hdri.brdf-lut"]
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
var lightingWorkerDagSpecs = {
|
|
1043
|
+
hybrid: {
|
|
1044
|
+
directLighting: { priority: 4, dependencies: [] },
|
|
1045
|
+
screenTrace: { priority: 3, dependencies: [] },
|
|
1046
|
+
radianceCache: { priority: 4, dependencies: ["directLighting"] },
|
|
1047
|
+
finalGather: { priority: 2, dependencies: ["radianceCache", "screenTrace"] },
|
|
1048
|
+
reflectionResolve: {
|
|
1049
|
+
priority: 1,
|
|
1050
|
+
dependencies: ["screenTrace", "finalGather"]
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
pathtracer: {
|
|
1054
|
+
pathTrace: { priority: 4, dependencies: [] },
|
|
1055
|
+
accumulate: { priority: 3, dependencies: ["pathTrace"] },
|
|
1056
|
+
denoise: { priority: 2, dependencies: ["accumulate"] }
|
|
1057
|
+
},
|
|
1058
|
+
volumetrics: {
|
|
1059
|
+
volumetricShadow: { priority: 3, dependencies: [] },
|
|
1060
|
+
froxelIntegrate: { priority: 2, dependencies: ["volumetricShadow"] }
|
|
1061
|
+
},
|
|
1062
|
+
hdri: {
|
|
1063
|
+
irradianceConvolution: { priority: 3, dependencies: [] },
|
|
1064
|
+
specularPrefilter: { priority: 3, dependencies: [] },
|
|
1065
|
+
brdfLut: {
|
|
1066
|
+
priority: 2,
|
|
1067
|
+
dependencies: ["irradianceConvolution", "specularPrefilter"]
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
function resolveLightingQualityDimensions(techniqueName, jobKey) {
|
|
1072
|
+
const key = `${techniqueName}.${jobKey}`;
|
|
1073
|
+
return Object.freeze(
|
|
1074
|
+
{
|
|
1075
|
+
"hybrid.directLighting": { shadows: 1, lightingSamples: 0.7 },
|
|
1076
|
+
"hybrid.screenTrace": { rayTracing: 1, temporalReuse: 0.4 },
|
|
1077
|
+
"hybrid.radianceCache": {
|
|
1078
|
+
lightingSamples: 0.8,
|
|
1079
|
+
updateCadence: 0.7,
|
|
1080
|
+
temporalReuse: 1
|
|
1081
|
+
},
|
|
1082
|
+
"hybrid.finalGather": { lightingSamples: 1, rayTracing: 0.6 },
|
|
1083
|
+
"hybrid.reflectionResolve": {
|
|
1084
|
+
rayTracing: 0.5,
|
|
1085
|
+
temporalReuse: 1,
|
|
1086
|
+
shading: 0.3
|
|
1087
|
+
},
|
|
1088
|
+
"pathtracer.pathTrace": { rayTracing: 1, lightingSamples: 1 },
|
|
1089
|
+
"pathtracer.accumulate": { temporalReuse: 1, updateCadence: 0.4 },
|
|
1090
|
+
"pathtracer.denoise": { temporalReuse: 1, shading: 0.4 },
|
|
1091
|
+
"volumetrics.froxelIntegrate": {
|
|
1092
|
+
lightingSamples: 0.6,
|
|
1093
|
+
shading: 0.4,
|
|
1094
|
+
updateCadence: 0.3
|
|
1095
|
+
},
|
|
1096
|
+
"volumetrics.volumetricShadow": { shadows: 0.8, updateCadence: 0.5 },
|
|
1097
|
+
"hdri.irradianceConvolution": {
|
|
1098
|
+
lightingSamples: 0.4,
|
|
1099
|
+
temporalReuse: 1,
|
|
1100
|
+
updateCadence: 1
|
|
1101
|
+
},
|
|
1102
|
+
"hdri.specularPrefilter": {
|
|
1103
|
+
lightingSamples: 0.5,
|
|
1104
|
+
temporalReuse: 1,
|
|
1105
|
+
updateCadence: 1
|
|
1106
|
+
},
|
|
1107
|
+
"hdri.brdfLut": {
|
|
1108
|
+
shading: 0.4,
|
|
1109
|
+
temporalReuse: 1,
|
|
1110
|
+
updateCadence: 1
|
|
1111
|
+
}
|
|
1112
|
+
}[key] ?? {}
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
function resolveLightingImportanceSignals(techniqueName, jobKey) {
|
|
1116
|
+
const key = `${techniqueName}.${jobKey}`;
|
|
1117
|
+
return Object.freeze(
|
|
1118
|
+
{
|
|
1119
|
+
"hybrid.directLighting": { visible: true, shadowSignificance: "high" },
|
|
1120
|
+
"hybrid.screenTrace": { visible: true, reflectionSignificance: "high" },
|
|
1121
|
+
"hybrid.radianceCache": { visible: true },
|
|
1122
|
+
"hybrid.finalGather": {
|
|
1123
|
+
visible: true,
|
|
1124
|
+
shadowSignificance: "critical",
|
|
1125
|
+
reflectionSignificance: "high"
|
|
1126
|
+
},
|
|
1127
|
+
"hybrid.reflectionResolve": { visible: true, reflectionSignificance: "high" },
|
|
1128
|
+
"pathtracer.pathTrace": {
|
|
1129
|
+
visible: true,
|
|
1130
|
+
shadowSignificance: "high",
|
|
1131
|
+
reflectionSignificance: "high"
|
|
1132
|
+
},
|
|
1133
|
+
"pathtracer.accumulate": { visible: true },
|
|
1134
|
+
"pathtracer.denoise": { visible: true },
|
|
1135
|
+
"volumetrics.froxelIntegrate": { visible: true },
|
|
1136
|
+
"volumetrics.volumetricShadow": { visible: true, shadowSignificance: "high" },
|
|
1137
|
+
"hdri.irradianceConvolution": { visible: false },
|
|
1138
|
+
"hdri.specularPrefilter": { visible: false, reflectionSignificance: "medium" },
|
|
1139
|
+
"hdri.brdfLut": { visible: false }
|
|
1140
|
+
}[key] ?? {}
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
function buildWorkerManifestJob(techniqueName, job) {
|
|
1144
|
+
const spec = lightingWorkerSpecPresets[techniqueName].jobs[job.key];
|
|
1145
|
+
const dag = lightingWorkerDagSpecs[techniqueName][job.key];
|
|
1146
|
+
const dependencies = dag.dependencies.map(
|
|
1147
|
+
(dependency) => `lighting.${techniqueName}.${dependency}`
|
|
1148
|
+
);
|
|
1149
|
+
return Object.freeze({
|
|
1150
|
+
key: job.key,
|
|
1151
|
+
label: job.label,
|
|
1152
|
+
worker: Object.freeze({
|
|
1153
|
+
jobType: job.label,
|
|
1154
|
+
queueClass: lightingWorkerQueueClass,
|
|
1155
|
+
priority: dag.priority,
|
|
1156
|
+
dependencies: Object.freeze(dependencies),
|
|
1157
|
+
schedulerMode: "dag"
|
|
1158
|
+
}),
|
|
1159
|
+
performance: Object.freeze({
|
|
1160
|
+
id: job.label,
|
|
1161
|
+
jobType: job.label,
|
|
1162
|
+
queueClass: lightingWorkerQueueClass,
|
|
1163
|
+
domain: spec.domain,
|
|
1164
|
+
authority: "visual",
|
|
1165
|
+
importance: spec.importance,
|
|
1166
|
+
qualityDimensions: resolveLightingQualityDimensions(techniqueName, job.key),
|
|
1167
|
+
importanceSignals: resolveLightingImportanceSignals(techniqueName, job.key),
|
|
1168
|
+
levels: spec.levels
|
|
1169
|
+
}),
|
|
1170
|
+
debug: Object.freeze({
|
|
1171
|
+
owner: lightingDebugOwner,
|
|
1172
|
+
queueClass: lightingWorkerQueueClass,
|
|
1173
|
+
jobType: job.label,
|
|
1174
|
+
tags: Object.freeze([
|
|
1175
|
+
"lighting",
|
|
1176
|
+
techniqueName,
|
|
1177
|
+
job.key,
|
|
1178
|
+
spec.domain
|
|
1179
|
+
]),
|
|
1180
|
+
suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds])
|
|
1181
|
+
})
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
function buildLightingWorkerManifest(name, technique) {
|
|
1185
|
+
const spec = lightingWorkerSpecPresets[name];
|
|
1186
|
+
return Object.freeze({
|
|
1187
|
+
schemaVersion: 1,
|
|
1188
|
+
owner: lightingDebugOwner,
|
|
1189
|
+
technique: name,
|
|
1190
|
+
description: technique.description,
|
|
1191
|
+
queueClass: lightingWorkerQueueClass,
|
|
1192
|
+
schedulerMode: "dag",
|
|
1193
|
+
suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),
|
|
1194
|
+
jobs: Object.freeze(
|
|
1195
|
+
technique.jobs.map((job) => buildWorkerManifestJob(name, job))
|
|
1196
|
+
)
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
var lightingWorkerManifests = Object.freeze(
|
|
1200
|
+
Object.fromEntries(
|
|
1201
|
+
Object.entries(lightingTechniques).map(([name, technique]) => [
|
|
1202
|
+
name,
|
|
1203
|
+
buildLightingWorkerManifest(name, technique)
|
|
1204
|
+
])
|
|
1205
|
+
)
|
|
1206
|
+
);
|
|
1207
|
+
function getTechniqueJob(technique, key) {
|
|
1208
|
+
const job = technique.jobs.find((entry) => entry.key === key);
|
|
1209
|
+
if (!job) {
|
|
1210
|
+
const available = technique.jobs.map((entry) => entry.key).join(", ");
|
|
1211
|
+
throw new Error(
|
|
1212
|
+
`Unknown job "${key}" for technique "${technique.name}". Available: ${available}.`
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
return job;
|
|
1216
|
+
}
|
|
1217
|
+
function getLightingTechnique(name = defaultLightingTechnique) {
|
|
1218
|
+
const technique = lightingTechniques[name];
|
|
1219
|
+
if (!technique) {
|
|
1220
|
+
const available = lightingTechniqueNames.join(", ");
|
|
1221
|
+
throw new Error(`Unknown lighting technique "${name}". Available: ${available}.`);
|
|
1222
|
+
}
|
|
1223
|
+
return technique;
|
|
1224
|
+
}
|
|
1225
|
+
function getLightingProfile(name = defaultLightingProfile) {
|
|
1226
|
+
const profile = lightingProfiles[name];
|
|
1227
|
+
if (!profile) {
|
|
1228
|
+
const available = lightingProfileNames.join(", ");
|
|
1229
|
+
throw new Error(`Unknown lighting profile "${name}". Available: ${available}.`);
|
|
1230
|
+
}
|
|
1231
|
+
return profile;
|
|
1232
|
+
}
|
|
1233
|
+
function getLightingTechniqueWorkerManifest(name = defaultLightingTechnique) {
|
|
1234
|
+
const manifest = lightingWorkerManifests[name];
|
|
1235
|
+
if (!manifest) {
|
|
1236
|
+
const available = lightingTechniqueNames.join(", ");
|
|
1237
|
+
throw new Error(
|
|
1238
|
+
`Unknown lighting technique "${name}". Available: ${available}.`
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
return manifest;
|
|
1242
|
+
}
|
|
1243
|
+
function getLightingProfileWorkerManifest(name = defaultLightingProfile) {
|
|
1244
|
+
const profile = getLightingProfile(name);
|
|
1245
|
+
const techniques = profile.techniques.map(
|
|
1246
|
+
(techniqueName) => getLightingTechniqueWorkerManifest(techniqueName)
|
|
1247
|
+
);
|
|
1248
|
+
const lightingBandPlan = createLightingBandPlan({ profile: profile.name });
|
|
1249
|
+
return Object.freeze({
|
|
1250
|
+
schemaVersion: 1,
|
|
1251
|
+
owner: lightingDebugOwner,
|
|
1252
|
+
profile: profile.name,
|
|
1253
|
+
description: profile.description,
|
|
1254
|
+
schedulerMode: "dag",
|
|
1255
|
+
techniques: Object.freeze(techniques),
|
|
1256
|
+
lightingBands: lightingBandPlan.bands,
|
|
1257
|
+
jobs: Object.freeze(techniques.flatMap((technique) => technique.jobs))
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
var defaultTechnique = getLightingTechnique(defaultLightingTechnique);
|
|
1261
|
+
var lightingPreludeWgslUrl = defaultTechnique.preludeUrl;
|
|
1262
|
+
var lightingJobLabels = Object.freeze(
|
|
1263
|
+
Object.fromEntries(defaultTechnique.jobs.map((job) => [job.key, job.label]))
|
|
1264
|
+
);
|
|
1265
|
+
var lightingJobs = defaultTechnique.jobs.map((job) => ({
|
|
1266
|
+
label: job.label,
|
|
1267
|
+
url: job.url,
|
|
1268
|
+
sourceName: job.sourceName
|
|
1269
|
+
}));
|
|
1270
|
+
function assertNotHtmlWgsl(source, context) {
|
|
1271
|
+
const sample = source.slice(0, 200).toLowerCase();
|
|
1272
|
+
if (sample.includes("<!doctype") || sample.includes("<html") || sample.includes("<meta")) {
|
|
1273
|
+
const label = context ? ` for ${context}` : "";
|
|
1274
|
+
throw new Error(
|
|
1275
|
+
`Expected WGSL${label} but received HTML. Check the URL or server root.`
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
async function loadWgslSource(options = {}) {
|
|
1280
|
+
const { wgsl, url, fetcher = globalThis.fetch, base } = options ?? {};
|
|
1281
|
+
if (typeof wgsl === "string") {
|
|
1282
|
+
assertNotHtmlWgsl(wgsl, "inline WGSL");
|
|
1283
|
+
return wgsl;
|
|
1284
|
+
}
|
|
1285
|
+
if (!url) {
|
|
1286
|
+
return null;
|
|
1287
|
+
}
|
|
1288
|
+
const resolved = url instanceof URL ? url : new URL(url, base ?? baseUrl);
|
|
1289
|
+
if (!fetcher || resolved.protocol === "file:") {
|
|
1290
|
+
const { readFile } = await import("fs/promises");
|
|
1291
|
+
const { fileURLToPath } = await import("url");
|
|
1292
|
+
const source2 = await readFile(fileURLToPath(resolved), "utf8");
|
|
1293
|
+
assertNotHtmlWgsl(source2, resolved.href);
|
|
1294
|
+
return source2;
|
|
1295
|
+
}
|
|
1296
|
+
const response = await fetcher(resolved);
|
|
1297
|
+
if (!response.ok) {
|
|
1298
|
+
const status = "status" in response ? response.status : "unknown";
|
|
1299
|
+
const statusText = "statusText" in response ? response.statusText : "";
|
|
1300
|
+
const detail = statusText ? `${status} ${statusText}` : `${status}`;
|
|
1301
|
+
throw new Error(`Failed to load WGSL (${detail})`);
|
|
1302
|
+
}
|
|
1303
|
+
const source = await response.text();
|
|
1304
|
+
assertNotHtmlWgsl(source, resolved.href);
|
|
1305
|
+
return source;
|
|
1306
|
+
}
|
|
1307
|
+
async function loadTechniquePrelude(technique, fetcher) {
|
|
1308
|
+
const source = await loadWgslSource({ url: technique.preludeUrl, fetcher });
|
|
1309
|
+
if (typeof source !== "string") {
|
|
1310
|
+
throw new Error(`Failed to load ${technique.name} prelude WGSL source.`);
|
|
1311
|
+
}
|
|
1312
|
+
return source;
|
|
1313
|
+
}
|
|
1314
|
+
async function loadTechniqueJob(technique, job, fetcher) {
|
|
1315
|
+
const source = await loadWgslSource({ url: job.url, fetcher });
|
|
1316
|
+
if (typeof source !== "string") {
|
|
1317
|
+
throw new Error(
|
|
1318
|
+
`Failed to load ${technique.name} job "${job.key}" WGSL source.`
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
return source;
|
|
1322
|
+
}
|
|
1323
|
+
async function loadLightingTechniquePreludeWgsl(techniqueName, options = {}) {
|
|
1324
|
+
const { fetcher } = options ?? {};
|
|
1325
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1326
|
+
return loadTechniquePrelude(technique, fetcher);
|
|
1327
|
+
}
|
|
1328
|
+
async function loadLightingTechniqueJobWgsl(techniqueName, jobKey, options = {}) {
|
|
1329
|
+
const { fetcher } = options ?? {};
|
|
1330
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1331
|
+
const job = getTechniqueJob(technique, jobKey);
|
|
1332
|
+
return loadTechniqueJob(technique, job, fetcher);
|
|
1333
|
+
}
|
|
1334
|
+
async function loadLightingTechniqueJobs(techniqueName, options = {}) {
|
|
1335
|
+
const { fetcher } = options ?? {};
|
|
1336
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1337
|
+
const preludeWgsl = await loadTechniquePrelude(technique, fetcher);
|
|
1338
|
+
const jobSources = await Promise.all(
|
|
1339
|
+
technique.jobs.map((job) => loadTechniqueJob(technique, job, fetcher))
|
|
1340
|
+
);
|
|
1341
|
+
const jobs = technique.jobs.map((job, index) => ({
|
|
1342
|
+
wgsl: jobSources[index],
|
|
1343
|
+
label: job.label,
|
|
1344
|
+
sourceName: job.sourceName
|
|
1345
|
+
}));
|
|
1346
|
+
return { preludeWgsl, jobs };
|
|
1347
|
+
}
|
|
1348
|
+
async function loadLightingTechniqueWorkerBundle(techniqueName = defaultLightingTechnique, options = {}) {
|
|
1349
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1350
|
+
const { preludeWgsl, jobs } = await loadLightingTechniqueJobs(
|
|
1351
|
+
technique.name,
|
|
1352
|
+
options
|
|
1353
|
+
);
|
|
1354
|
+
return {
|
|
1355
|
+
technique: technique.name,
|
|
1356
|
+
preludeWgsl,
|
|
1357
|
+
jobs,
|
|
1358
|
+
workerManifest: getLightingTechniqueWorkerManifest(technique.name)
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
async function loadLightingPreludeWgsl(options = {}) {
|
|
1362
|
+
const { fetcher } = options ?? {};
|
|
1363
|
+
return loadTechniquePrelude(defaultTechnique, fetcher);
|
|
1364
|
+
}
|
|
1365
|
+
async function loadLightingJobs(options = {}) {
|
|
1366
|
+
return loadLightingTechniqueJobs(defaultLightingTechnique, options);
|
|
1367
|
+
}
|
|
1368
|
+
async function loadLightingProfile(profileName, options = {}) {
|
|
1369
|
+
const profile = getLightingProfile(profileName);
|
|
1370
|
+
const techniques = await Promise.all(
|
|
1371
|
+
profile.techniques.map(async (techniqueName) => {
|
|
1372
|
+
const { preludeWgsl, jobs } = await loadLightingTechniqueJobs(
|
|
1373
|
+
techniqueName,
|
|
1374
|
+
options
|
|
1375
|
+
);
|
|
1376
|
+
return {
|
|
1377
|
+
technique: techniqueName,
|
|
1378
|
+
preludeWgsl,
|
|
1379
|
+
jobs
|
|
1380
|
+
};
|
|
1381
|
+
})
|
|
1382
|
+
);
|
|
1383
|
+
return { profile, techniques };
|
|
1384
|
+
}
|
|
1385
|
+
async function loadLightingProfileWorkerPlan(profileName = defaultLightingProfile, options = {}) {
|
|
1386
|
+
const profile = getLightingProfile(profileName);
|
|
1387
|
+
const techniques = await Promise.all(
|
|
1388
|
+
profile.techniques.map(
|
|
1389
|
+
(techniqueName) => loadLightingTechniqueWorkerBundle(techniqueName, options)
|
|
1390
|
+
)
|
|
1391
|
+
);
|
|
1392
|
+
return {
|
|
1393
|
+
profile,
|
|
1394
|
+
techniques,
|
|
1395
|
+
lightingBandPlan: createLightingBandPlan({ profile: profile.name }),
|
|
1396
|
+
workerManifest: getLightingProfileWorkerManifest(profile.name)
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
export {
|
|
1400
|
+
createEnvironmentLightingConfig,
|
|
1401
|
+
createLightingBandPlan,
|
|
1402
|
+
createLightingProfileModeLadder,
|
|
1403
|
+
createWavefrontEnvironmentLightingOptions,
|
|
1404
|
+
defaultAdaptiveLightingProfilePolicy,
|
|
1405
|
+
defaultLightingProfile,
|
|
1406
|
+
defaultLightingTechnique,
|
|
1407
|
+
getLightingProfile,
|
|
1408
|
+
getLightingProfileWorkerManifest,
|
|
1409
|
+
getLightingTechnique,
|
|
1410
|
+
getLightingTechniqueWorkerManifest,
|
|
1411
|
+
lightingDebugOwner,
|
|
1412
|
+
lightingDistanceBands,
|
|
1413
|
+
lightingEnvironmentPresetNames,
|
|
1414
|
+
lightingJobLabels,
|
|
1415
|
+
lightingJobs,
|
|
1416
|
+
lightingPreludeWgslUrl,
|
|
1417
|
+
lightingProfileModeOrder,
|
|
1418
|
+
lightingProfileNames,
|
|
1419
|
+
lightingProfiles,
|
|
1420
|
+
lightingTechniqueNames,
|
|
1421
|
+
lightingTechniques,
|
|
1422
|
+
lightingWorkerManifests,
|
|
1423
|
+
lightingWorkerQueueClass,
|
|
1424
|
+
loadLightingJobs,
|
|
1425
|
+
loadLightingPreludeWgsl,
|
|
1426
|
+
loadLightingProfile,
|
|
1427
|
+
loadLightingProfileWorkerPlan,
|
|
1428
|
+
loadLightingTechniqueJobWgsl,
|
|
1429
|
+
loadLightingTechniqueJobs,
|
|
1430
|
+
loadLightingTechniquePreludeWgsl,
|
|
1431
|
+
loadLightingTechniqueWorkerBundle
|
|
1432
|
+
};
|
|
1433
|
+
//# sourceMappingURL=dist-B5R2GZQR.js.map
|