@plasius/gpu-shared 0.1.14 → 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 +4 -0
- package/README.md +15 -0
- package/dist/{chunk-4ZJ24VRS.js → chunk-6SOHFUOE.js} +4 -3
- package/dist/{chunk-4ZJ24VRS.js.map → chunk-6SOHFUOE.js.map} +1 -1
- package/dist/{chunk-3ARPGHCQ.js → chunk-CH3ZS5TQ.js} +8 -8
- package/dist/chunk-CH3ZS5TQ.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-W5GA3VA6.js → chunk-QVNRTWHB.js} +8 -5
- 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 +1483 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +30 -6
- package/dist/index.js.map +1 -1
- package/dist/{product-studio-runtime-HDAUDWYO.js → product-studio-runtime-BYVBUWIN.js} +4 -3
- package/dist/{showcase-inline-assets-WT4PSNKI.js → showcase-inline-assets-QRQKXGVX.js} +2 -1
- package/dist/showcase-inline-assets-QRQKXGVX.js.map +1 -0
- package/dist/{showcase-runtime-SNCUFSSC.js → showcase-runtime-M6TEUYOG.js} +4 -3
- package/dist/{showcase-runtime-SNCUFSSC.js.map → showcase-runtime-M6TEUYOG.js.map} +1 -1
- package/package.json +3 -4
- package/src/gltf-loader.js +7 -3
- package/src/index.d.ts +1 -0
- package/src/index.js +35 -1
- package/src/product-studio-runtime.js +1 -0
- package/dist/chunk-3ARPGHCQ.js.map +0 -1
- package/dist/chunk-W5GA3VA6.js.map +0 -1
- package/dist/gltf-loader-YDPLZS5Q.js +0 -8
- /package/dist/{gltf-loader-YDPLZS5Q.js.map → chunk-DGUM43GV.js.map} +0 -0
- /package/dist/{product-studio-runtime-HDAUDWYO.js.map → gltf-loader-B6VOWGBV.js.map} +0 -0
- /package/dist/{showcase-inline-assets-WT4PSNKI.js.map → product-studio-runtime-BYVBUWIN.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
));
|
|
30
30
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
31
31
|
|
|
32
|
+
// src/feature-flags.js
|
|
33
|
+
var GPU_SHOWCASE_REALISTIC_MODELS_FEATURE, GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE;
|
|
34
|
+
var init_feature_flags = __esm({
|
|
35
|
+
"src/feature-flags.js"() {
|
|
36
|
+
GPU_SHOWCASE_REALISTIC_MODELS_FEATURE = "gpu_showcase_realistic_models_v1";
|
|
37
|
+
GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE = "gpu_showcase_product_studio_wavefront_v1";
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
32
41
|
// src/showcase-inline-assets.js
|
|
33
42
|
var showcase_inline_assets_exports = {};
|
|
34
43
|
__export(showcase_inline_assets_exports, {
|
|
@@ -231,15 +240,6 @@ var init_i18n = __esm({
|
|
|
231
240
|
}
|
|
232
241
|
});
|
|
233
242
|
|
|
234
|
-
// src/feature-flags.js
|
|
235
|
-
var GPU_SHOWCASE_REALISTIC_MODELS_FEATURE, GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE;
|
|
236
|
-
var init_feature_flags = __esm({
|
|
237
|
-
"src/feature-flags.js"() {
|
|
238
|
-
GPU_SHOWCASE_REALISTIC_MODELS_FEATURE = "gpu_showcase_realistic_models_v1";
|
|
239
|
-
GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE = "gpu_showcase_product_studio_wavefront_v1";
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
|
|
243
243
|
// src/gltf-loader.js
|
|
244
244
|
var gltf_loader_exports = {};
|
|
245
245
|
__export(gltf_loader_exports, {
|
|
@@ -367,6 +367,11 @@ function appendValues(target, values) {
|
|
|
367
367
|
target.push(values[index]);
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
|
+
function appendIndicesWithOffset(target, values, vertexOffset) {
|
|
371
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
372
|
+
target.push(values[index] + vertexOffset);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
370
375
|
function resolveBrowserRequestBaseUrl() {
|
|
371
376
|
if (typeof document !== "undefined" && typeof document.baseURI === "string" && document.baseURI.length > 0) {
|
|
372
377
|
return document.baseURI;
|
|
@@ -556,7 +561,7 @@ async function loadInlineShowcaseDocument() {
|
|
|
556
561
|
const module2 = await Promise.resolve().then(() => (init_showcase_inline_assets(), showcase_inline_assets_exports));
|
|
557
562
|
return loadGltfDocument(new URL(module2.INLINE_SHOWCASE_ASSET_URLS.brigantine));
|
|
558
563
|
}
|
|
559
|
-
async function buildGltfModel(document2,
|
|
564
|
+
async function buildGltfModel(document2, baseUrl2) {
|
|
560
565
|
const buffers = await Promise.all(
|
|
561
566
|
(document2.buffers ?? []).map(async (buffer) => {
|
|
562
567
|
if (typeof buffer.uri !== "string") {
|
|
@@ -565,7 +570,7 @@ async function buildGltfModel(document2, baseUrl) {
|
|
|
565
570
|
if (buffer.uri.startsWith("data:")) {
|
|
566
571
|
return decodeDataUri(buffer.uri);
|
|
567
572
|
}
|
|
568
|
-
const nested = await fetch(new URL(buffer.uri,
|
|
573
|
+
const nested = await fetch(new URL(buffer.uri, baseUrl2));
|
|
569
574
|
if (!nested.ok) {
|
|
570
575
|
throw new Error(`Failed to load glTF buffer: ${nested.status} ${nested.statusText}`);
|
|
571
576
|
}
|
|
@@ -578,9 +583,7 @@ async function buildGltfModel(document2, baseUrl) {
|
|
|
578
583
|
for (const primitive of scene.primitives) {
|
|
579
584
|
const vertexOffset = aggregatePositions.length / 3;
|
|
580
585
|
appendValues(aggregatePositions, primitive.positions);
|
|
581
|
-
|
|
582
|
-
aggregateIndices.push(index + vertexOffset);
|
|
583
|
-
}
|
|
586
|
+
appendIndicesWithOffset(aggregateIndices, primitive.indices, vertexOffset);
|
|
584
587
|
}
|
|
585
588
|
const color = scene.primitives[0]?.material?.color ?? { r: 0.56, g: 0.33, b: 0.22, a: 1 };
|
|
586
589
|
return Object.freeze({
|
|
@@ -601,14 +604,14 @@ function shouldRetryWithInlineShowcaseFallback(url, error) {
|
|
|
601
604
|
}
|
|
602
605
|
async function loadGltfModel(url) {
|
|
603
606
|
try {
|
|
604
|
-
const { document: document2, baseUrl } = await loadGltfDocument(url);
|
|
605
|
-
return buildGltfModel(document2,
|
|
607
|
+
const { document: document2, baseUrl: baseUrl2 } = await loadGltfDocument(url);
|
|
608
|
+
return buildGltfModel(document2, baseUrl2);
|
|
606
609
|
} catch (error) {
|
|
607
610
|
if (!shouldRetryWithInlineShowcaseFallback(url, error)) {
|
|
608
611
|
throw error;
|
|
609
612
|
}
|
|
610
|
-
const { document: document2, baseUrl } = await loadInlineShowcaseDocument();
|
|
611
|
-
return buildGltfModel(document2,
|
|
613
|
+
const { document: document2, baseUrl: baseUrl2 } = await loadInlineShowcaseDocument();
|
|
614
|
+
return buildGltfModel(document2, baseUrl2);
|
|
612
615
|
}
|
|
613
616
|
}
|
|
614
617
|
var init_gltf_loader = __esm({
|
|
@@ -617,6 +620,1442 @@ var init_gltf_loader = __esm({
|
|
|
617
620
|
}
|
|
618
621
|
});
|
|
619
622
|
|
|
623
|
+
// node_modules/@plasius/gpu-lighting/dist/index.js
|
|
624
|
+
var dist_exports = {};
|
|
625
|
+
__export(dist_exports, {
|
|
626
|
+
createEnvironmentLightingConfig: () => createEnvironmentLightingConfig,
|
|
627
|
+
createLightingBandPlan: () => createLightingBandPlan,
|
|
628
|
+
createLightingProfileModeLadder: () => createLightingProfileModeLadder,
|
|
629
|
+
createWavefrontEnvironmentLightingOptions: () => createWavefrontEnvironmentLightingOptions,
|
|
630
|
+
defaultAdaptiveLightingProfilePolicy: () => defaultAdaptiveLightingProfilePolicy,
|
|
631
|
+
defaultLightingProfile: () => defaultLightingProfile,
|
|
632
|
+
defaultLightingTechnique: () => defaultLightingTechnique,
|
|
633
|
+
getLightingProfile: () => getLightingProfile,
|
|
634
|
+
getLightingProfileWorkerManifest: () => getLightingProfileWorkerManifest,
|
|
635
|
+
getLightingTechnique: () => getLightingTechnique,
|
|
636
|
+
getLightingTechniqueWorkerManifest: () => getLightingTechniqueWorkerManifest,
|
|
637
|
+
lightingDebugOwner: () => lightingDebugOwner,
|
|
638
|
+
lightingDistanceBands: () => lightingDistanceBands,
|
|
639
|
+
lightingEnvironmentPresetNames: () => lightingEnvironmentPresetNames,
|
|
640
|
+
lightingJobLabels: () => lightingJobLabels,
|
|
641
|
+
lightingJobs: () => lightingJobs,
|
|
642
|
+
lightingPreludeWgslUrl: () => lightingPreludeWgslUrl,
|
|
643
|
+
lightingProfileModeOrder: () => lightingProfileModeOrder,
|
|
644
|
+
lightingProfileNames: () => lightingProfileNames,
|
|
645
|
+
lightingProfiles: () => lightingProfiles,
|
|
646
|
+
lightingTechniqueNames: () => lightingTechniqueNames,
|
|
647
|
+
lightingTechniques: () => lightingTechniques,
|
|
648
|
+
lightingWorkerManifests: () => lightingWorkerManifests,
|
|
649
|
+
lightingWorkerQueueClass: () => lightingWorkerQueueClass,
|
|
650
|
+
loadLightingJobs: () => loadLightingJobs,
|
|
651
|
+
loadLightingPreludeWgsl: () => loadLightingPreludeWgsl,
|
|
652
|
+
loadLightingProfile: () => loadLightingProfile,
|
|
653
|
+
loadLightingProfileWorkerPlan: () => loadLightingProfileWorkerPlan,
|
|
654
|
+
loadLightingTechniqueJobWgsl: () => loadLightingTechniqueJobWgsl,
|
|
655
|
+
loadLightingTechniqueJobs: () => loadLightingTechniqueJobs,
|
|
656
|
+
loadLightingTechniquePreludeWgsl: () => loadLightingTechniquePreludeWgsl,
|
|
657
|
+
loadLightingTechniqueWorkerBundle: () => loadLightingTechniqueWorkerBundle
|
|
658
|
+
});
|
|
659
|
+
function createModuleBaseUrl(metaUrl) {
|
|
660
|
+
return Reflect.construct(URL, [String(metaUrl)]);
|
|
661
|
+
}
|
|
662
|
+
function buildTechnique(name, spec) {
|
|
663
|
+
const preludeUrl = new URL(`./techniques/${name}/${spec.prelude}`, baseUrl);
|
|
664
|
+
const jobs = Object.entries(spec.jobs).map(([key, file]) => {
|
|
665
|
+
const label = `lighting.${name}.${key}`;
|
|
666
|
+
return {
|
|
667
|
+
key,
|
|
668
|
+
label,
|
|
669
|
+
url: new URL(`./techniques/${name}/${file}`, baseUrl),
|
|
670
|
+
sourceName: label
|
|
671
|
+
};
|
|
672
|
+
});
|
|
673
|
+
return {
|
|
674
|
+
name,
|
|
675
|
+
description: spec.description,
|
|
676
|
+
preludeUrl,
|
|
677
|
+
jobs
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
function buildProfile(name, spec) {
|
|
681
|
+
return {
|
|
682
|
+
name,
|
|
683
|
+
description: spec.description,
|
|
684
|
+
techniques: [...spec.techniques]
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
function freezeVec4(value) {
|
|
688
|
+
return Object.freeze([value[0], value[1], value[2], value[3] ?? 1]);
|
|
689
|
+
}
|
|
690
|
+
function normalizeVector3(value, fallback) {
|
|
691
|
+
if (!Array.isArray(value) || value.length < 3) {
|
|
692
|
+
return [...fallback];
|
|
693
|
+
}
|
|
694
|
+
const vector = [
|
|
695
|
+
Number.isFinite(value[0]) ? value[0] : fallback[0],
|
|
696
|
+
Number.isFinite(value[1]) ? value[1] : fallback[1],
|
|
697
|
+
Number.isFinite(value[2]) ? value[2] : fallback[2]
|
|
698
|
+
];
|
|
699
|
+
const length = Math.hypot(vector[0], vector[1], vector[2]);
|
|
700
|
+
if (!Number.isFinite(length) || length <= 1e-6) {
|
|
701
|
+
return [...fallback];
|
|
702
|
+
}
|
|
703
|
+
return vector.map((component) => component / length);
|
|
704
|
+
}
|
|
705
|
+
function readColor(value, fallback) {
|
|
706
|
+
if (!Array.isArray(value) || value.length < 3) {
|
|
707
|
+
return freezeVec4(fallback);
|
|
708
|
+
}
|
|
709
|
+
return freezeVec4([
|
|
710
|
+
Number.isFinite(value[0]) ? Math.max(0, value[0]) : fallback[0],
|
|
711
|
+
Number.isFinite(value[1]) ? Math.max(0, value[1]) : fallback[1],
|
|
712
|
+
Number.isFinite(value[2]) ? Math.max(0, value[2]) : fallback[2],
|
|
713
|
+
Number.isFinite(value[3]) ? Math.max(0, Math.min(1, value[3])) : fallback[3] ?? 1
|
|
714
|
+
]);
|
|
715
|
+
}
|
|
716
|
+
function readFinite(value, fallback) {
|
|
717
|
+
return Number.isFinite(value) ? value : fallback;
|
|
718
|
+
}
|
|
719
|
+
function resolveEnvironmentPreset(name) {
|
|
720
|
+
const presetName = typeof name === "string" && name.length > 0 ? name : "product-studio";
|
|
721
|
+
const preset = environmentLightingPresets[presetName];
|
|
722
|
+
if (!preset) {
|
|
723
|
+
throw new Error(
|
|
724
|
+
`Unknown lighting environment preset "${presetName}". Expected one of: ${lightingEnvironmentPresetNames.join(", ")}.`
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
return preset;
|
|
728
|
+
}
|
|
729
|
+
function estimateEnvironmentColor(config) {
|
|
730
|
+
const horizonWeight = 0.58;
|
|
731
|
+
const zenithWeight = 1 - horizonWeight;
|
|
732
|
+
const glowWeight = 0.055;
|
|
733
|
+
const intensity = Math.max(config.environmentIntensity, 1e-4);
|
|
734
|
+
return freezeVec4([
|
|
735
|
+
(config.horizonColor[0] * horizonWeight + config.zenithColor[0] * zenithWeight + config.sunColor[0] * glowWeight) * intensity,
|
|
736
|
+
(config.horizonColor[1] * horizonWeight + config.zenithColor[1] * zenithWeight + config.sunColor[1] * glowWeight) * intensity,
|
|
737
|
+
(config.horizonColor[2] * horizonWeight + config.zenithColor[2] * zenithWeight + config.sunColor[2] * glowWeight) * intensity,
|
|
738
|
+
1
|
|
739
|
+
]);
|
|
740
|
+
}
|
|
741
|
+
function createEnvironmentLightingConfig(options = {}) {
|
|
742
|
+
const preset = resolveEnvironmentPreset(options.preset ?? options.name);
|
|
743
|
+
const environmentIntensity = Math.max(
|
|
744
|
+
readFinite(options.environmentIntensity ?? options.intensity, preset.environmentIntensity),
|
|
745
|
+
1e-4
|
|
746
|
+
);
|
|
747
|
+
const config = {
|
|
748
|
+
preset: preset.preset,
|
|
749
|
+
profile: typeof options.profile === "string" ? options.profile : defaultLightingProfile,
|
|
750
|
+
environmentMode: Math.max(0, Math.trunc(readFinite(options.environmentMode, preset.environmentMode))),
|
|
751
|
+
environmentIntensity,
|
|
752
|
+
exposure: Math.max(1e-4, readFinite(options.exposure, preset.exposure)),
|
|
753
|
+
horizonColor: readColor(options.horizonColor, preset.horizonColor),
|
|
754
|
+
zenithColor: readColor(options.zenithColor, preset.zenithColor),
|
|
755
|
+
sunDirection: Object.freeze(
|
|
756
|
+
normalizeVector3(options.sunDirection, preset.sunDirection)
|
|
757
|
+
),
|
|
758
|
+
sunColor: readColor(options.sunColor, preset.sunColor),
|
|
759
|
+
ambientColor: readColor(options.ambientColor, preset.ambientColor)
|
|
760
|
+
};
|
|
761
|
+
const environmentColor = estimateEnvironmentColor(config);
|
|
762
|
+
return Object.freeze({
|
|
763
|
+
...config,
|
|
764
|
+
environmentColor,
|
|
765
|
+
wavefront: Object.freeze({
|
|
766
|
+
environmentColor,
|
|
767
|
+
ambientColor: config.ambientColor,
|
|
768
|
+
environmentLighting: Object.freeze({
|
|
769
|
+
horizonColor: config.horizonColor,
|
|
770
|
+
zenithColor: config.zenithColor,
|
|
771
|
+
sunDirection: Object.freeze([...config.sunDirection]),
|
|
772
|
+
sunColor: config.sunColor,
|
|
773
|
+
intensity: config.environmentIntensity,
|
|
774
|
+
mode: config.environmentMode,
|
|
775
|
+
exposure: config.exposure
|
|
776
|
+
})
|
|
777
|
+
})
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
function createWavefrontEnvironmentLightingOptions(options = {}) {
|
|
781
|
+
const config = createEnvironmentLightingConfig(options);
|
|
782
|
+
return Object.freeze({
|
|
783
|
+
environmentColor: config.wavefront.environmentColor,
|
|
784
|
+
ambientColor: config.wavefront.ambientColor,
|
|
785
|
+
environmentLighting: config.wavefront.environmentLighting,
|
|
786
|
+
lightingEnvironment: config
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
function assertLightingImportance(name, value) {
|
|
790
|
+
if (!lightingImportanceLevels.includes(value)) {
|
|
791
|
+
throw new Error(
|
|
792
|
+
`${name} must be one of: ${lightingImportanceLevels.join(", ")}.`
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
return value;
|
|
796
|
+
}
|
|
797
|
+
function readPositiveIntegerOption(name, value, fallback) {
|
|
798
|
+
if (value === void 0) {
|
|
799
|
+
return fallback;
|
|
800
|
+
}
|
|
801
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0 || Math.round(value) !== value) {
|
|
802
|
+
throw new Error(`${name} must be a positive integer.`);
|
|
803
|
+
}
|
|
804
|
+
return value;
|
|
805
|
+
}
|
|
806
|
+
function resolveBandParticipation(profileName, band, importance) {
|
|
807
|
+
const referenceProfile = profileName === "reference";
|
|
808
|
+
const premiumImportance = importance === "critical" || importance === "high";
|
|
809
|
+
if (band === "near") {
|
|
810
|
+
return Object.freeze({
|
|
811
|
+
directShadows: premiumImportance ? "premium" : "selective",
|
|
812
|
+
reflections: premiumImportance ? "premium" : "selective",
|
|
813
|
+
globalIllumination: referenceProfile || importance === "critical" ? "premium" : "selective"
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
if (band === "mid") {
|
|
817
|
+
return Object.freeze({
|
|
818
|
+
directShadows: premiumImportance ? "selective" : "proxy",
|
|
819
|
+
reflections: referenceProfile && premiumImportance ? "selective" : "proxy",
|
|
820
|
+
globalIllumination: referenceProfile && importance === "critical" ? "selective" : "disabled"
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
if (band === "far") {
|
|
824
|
+
return Object.freeze({
|
|
825
|
+
directShadows: "proxy",
|
|
826
|
+
reflections: referenceProfile && importance === "critical" ? "proxy" : "disabled",
|
|
827
|
+
globalIllumination: "disabled"
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
return Object.freeze({
|
|
831
|
+
directShadows: "disabled",
|
|
832
|
+
reflections: "disabled",
|
|
833
|
+
globalIllumination: "disabled"
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
function createLightingBandPlan(options = {}) {
|
|
837
|
+
const profileName = options.profile ?? defaultLightingProfile;
|
|
838
|
+
const profile = getLightingProfile(profileName);
|
|
839
|
+
const importance = assertLightingImportance(
|
|
840
|
+
"importance",
|
|
841
|
+
options.importance ?? "high"
|
|
842
|
+
);
|
|
843
|
+
const bands = Object.freeze(
|
|
844
|
+
lightingDistanceBands.map(
|
|
845
|
+
(band) => Object.freeze({
|
|
846
|
+
band,
|
|
847
|
+
profile: profile.name,
|
|
848
|
+
importance,
|
|
849
|
+
primaryShadowSource: lightingBandPolicySpecs[band].primaryShadowSource,
|
|
850
|
+
assistShadowSources: Object.freeze([
|
|
851
|
+
...lightingBandPolicySpecs[band].assistShadowSources
|
|
852
|
+
]),
|
|
853
|
+
rtParticipation: resolveBandParticipation(profile.name, band, importance),
|
|
854
|
+
temporalReuse: lightingBandPolicySpecs[band].temporalReuse,
|
|
855
|
+
updateCadenceDivisor: lightingBandPolicySpecs[band].updateCadenceDivisor,
|
|
856
|
+
liveObjectShadows: lightingBandPolicySpecs[band].liveObjectShadows,
|
|
857
|
+
impressionOnly: lightingBandPolicySpecs[band].impressionOnly
|
|
858
|
+
})
|
|
859
|
+
)
|
|
860
|
+
);
|
|
861
|
+
return Object.freeze({
|
|
862
|
+
schemaVersion: 1,
|
|
863
|
+
owner: lightingDebugOwner,
|
|
864
|
+
profile: profile.name,
|
|
865
|
+
importance,
|
|
866
|
+
techniques: Object.freeze([...profile.techniques]),
|
|
867
|
+
bands
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
function createLightingProfileModeLadder(options = {}) {
|
|
871
|
+
const moduleId = typeof options.id === "string" && options.id.trim().length > 0 ? options.id.trim() : "lighting-profile-mode";
|
|
872
|
+
const preferredProfile = getLightingProfile(
|
|
873
|
+
options.preferredProfile ?? defaultAdaptiveLightingProfilePolicy.preferredProfile
|
|
874
|
+
).name;
|
|
875
|
+
const initialProfile = getLightingProfile(
|
|
876
|
+
options.initialProfile ?? preferredProfile
|
|
877
|
+
).name;
|
|
878
|
+
const minimumFrameRate = readPositiveIntegerOption(
|
|
879
|
+
"minimumFrameRate",
|
|
880
|
+
options.minimumFrameRate,
|
|
881
|
+
defaultAdaptiveLightingProfilePolicy.minimumFrameRate
|
|
882
|
+
);
|
|
883
|
+
const sampleWindowSize = readPositiveIntegerOption(
|
|
884
|
+
"sampleWindowSize",
|
|
885
|
+
options.sampleWindowSize,
|
|
886
|
+
defaultAdaptiveLightingProfilePolicy.sampleWindowSize
|
|
887
|
+
);
|
|
888
|
+
const importance = assertLightingImportance(
|
|
889
|
+
"importance",
|
|
890
|
+
options.importance ?? "high"
|
|
891
|
+
);
|
|
892
|
+
const moduleImportance = assertLightingImportance(
|
|
893
|
+
"moduleImportance",
|
|
894
|
+
options.moduleImportance ?? "critical"
|
|
895
|
+
);
|
|
896
|
+
const levels = Object.freeze(
|
|
897
|
+
lightingProfileModeOrder.map((profileName) => {
|
|
898
|
+
const profile = getLightingProfile(profileName);
|
|
899
|
+
return Object.freeze({
|
|
900
|
+
id: profile.name,
|
|
901
|
+
estimatedCostMs: lightingProfileModeEstimatedCostMs[profile.name],
|
|
902
|
+
config: Object.freeze({
|
|
903
|
+
profile: profile.name,
|
|
904
|
+
description: profile.description,
|
|
905
|
+
techniques: Object.freeze([...profile.techniques]),
|
|
906
|
+
lightingBandPlan: createLightingBandPlan({
|
|
907
|
+
profile: profile.name,
|
|
908
|
+
importance
|
|
909
|
+
}),
|
|
910
|
+
policy: Object.freeze({
|
|
911
|
+
preferredProfile,
|
|
912
|
+
minimumFrameRate,
|
|
913
|
+
sampleWindowSize
|
|
914
|
+
})
|
|
915
|
+
})
|
|
916
|
+
});
|
|
917
|
+
})
|
|
918
|
+
);
|
|
919
|
+
return Object.freeze({
|
|
920
|
+
id: moduleId,
|
|
921
|
+
domain: "lighting",
|
|
922
|
+
authority: "visual",
|
|
923
|
+
importance: moduleImportance,
|
|
924
|
+
initialLevel: initialProfile,
|
|
925
|
+
levels,
|
|
926
|
+
target: Object.freeze({
|
|
927
|
+
minimumFrameRate,
|
|
928
|
+
maximumFrameRate: minimumFrameRate,
|
|
929
|
+
preferredFrameRates: Object.freeze([minimumFrameRate])
|
|
930
|
+
}),
|
|
931
|
+
adaptation: Object.freeze({
|
|
932
|
+
sampleWindowSize,
|
|
933
|
+
minimumSamplesBeforeAdjustment: sampleWindowSize,
|
|
934
|
+
degradeCooldownFrames: 1,
|
|
935
|
+
upgradeCooldownFrames: sampleWindowSize,
|
|
936
|
+
minStableFramesForRecovery: sampleWindowSize
|
|
937
|
+
}),
|
|
938
|
+
policy: Object.freeze({
|
|
939
|
+
preferredProfile,
|
|
940
|
+
minimumFrameRate,
|
|
941
|
+
sampleWindowSize
|
|
942
|
+
})
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
function buildWorkerBudgetLevels(jobType, queueClass, presets) {
|
|
946
|
+
return Object.freeze([
|
|
947
|
+
Object.freeze({
|
|
948
|
+
id: "low",
|
|
949
|
+
estimatedCostMs: presets.low.estimatedCostMs,
|
|
950
|
+
config: Object.freeze({
|
|
951
|
+
maxDispatchesPerFrame: presets.low.maxDispatchesPerFrame,
|
|
952
|
+
maxJobsPerDispatch: presets.low.maxJobsPerDispatch,
|
|
953
|
+
cadenceDivisor: presets.low.cadenceDivisor,
|
|
954
|
+
workgroupScale: presets.low.workgroupScale,
|
|
955
|
+
maxQueueDepth: presets.low.maxQueueDepth,
|
|
956
|
+
metadata: Object.freeze({
|
|
957
|
+
owner: lightingDebugOwner,
|
|
958
|
+
queueClass,
|
|
959
|
+
jobType,
|
|
960
|
+
quality: "low"
|
|
961
|
+
})
|
|
962
|
+
})
|
|
963
|
+
}),
|
|
964
|
+
Object.freeze({
|
|
965
|
+
id: "medium",
|
|
966
|
+
estimatedCostMs: presets.medium.estimatedCostMs,
|
|
967
|
+
config: Object.freeze({
|
|
968
|
+
maxDispatchesPerFrame: presets.medium.maxDispatchesPerFrame,
|
|
969
|
+
maxJobsPerDispatch: presets.medium.maxJobsPerDispatch,
|
|
970
|
+
cadenceDivisor: presets.medium.cadenceDivisor,
|
|
971
|
+
workgroupScale: presets.medium.workgroupScale,
|
|
972
|
+
maxQueueDepth: presets.medium.maxQueueDepth,
|
|
973
|
+
metadata: Object.freeze({
|
|
974
|
+
owner: lightingDebugOwner,
|
|
975
|
+
queueClass,
|
|
976
|
+
jobType,
|
|
977
|
+
quality: "medium"
|
|
978
|
+
})
|
|
979
|
+
})
|
|
980
|
+
}),
|
|
981
|
+
Object.freeze({
|
|
982
|
+
id: "high",
|
|
983
|
+
estimatedCostMs: presets.high.estimatedCostMs,
|
|
984
|
+
config: Object.freeze({
|
|
985
|
+
maxDispatchesPerFrame: presets.high.maxDispatchesPerFrame,
|
|
986
|
+
maxJobsPerDispatch: presets.high.maxJobsPerDispatch,
|
|
987
|
+
cadenceDivisor: presets.high.cadenceDivisor,
|
|
988
|
+
workgroupScale: presets.high.workgroupScale,
|
|
989
|
+
maxQueueDepth: presets.high.maxQueueDepth,
|
|
990
|
+
metadata: Object.freeze({
|
|
991
|
+
owner: lightingDebugOwner,
|
|
992
|
+
queueClass,
|
|
993
|
+
jobType,
|
|
994
|
+
quality: "high"
|
|
995
|
+
})
|
|
996
|
+
})
|
|
997
|
+
})
|
|
998
|
+
]);
|
|
999
|
+
}
|
|
1000
|
+
function resolveLightingQualityDimensions(techniqueName, jobKey) {
|
|
1001
|
+
const key = `${techniqueName}.${jobKey}`;
|
|
1002
|
+
return Object.freeze(
|
|
1003
|
+
{
|
|
1004
|
+
"hybrid.directLighting": { shadows: 1, lightingSamples: 0.7 },
|
|
1005
|
+
"hybrid.screenTrace": { rayTracing: 1, temporalReuse: 0.4 },
|
|
1006
|
+
"hybrid.radianceCache": {
|
|
1007
|
+
lightingSamples: 0.8,
|
|
1008
|
+
updateCadence: 0.7,
|
|
1009
|
+
temporalReuse: 1
|
|
1010
|
+
},
|
|
1011
|
+
"hybrid.finalGather": { lightingSamples: 1, rayTracing: 0.6 },
|
|
1012
|
+
"hybrid.reflectionResolve": {
|
|
1013
|
+
rayTracing: 0.5,
|
|
1014
|
+
temporalReuse: 1,
|
|
1015
|
+
shading: 0.3
|
|
1016
|
+
},
|
|
1017
|
+
"pathtracer.pathTrace": { rayTracing: 1, lightingSamples: 1 },
|
|
1018
|
+
"pathtracer.accumulate": { temporalReuse: 1, updateCadence: 0.4 },
|
|
1019
|
+
"pathtracer.denoise": { temporalReuse: 1, shading: 0.4 },
|
|
1020
|
+
"volumetrics.froxelIntegrate": {
|
|
1021
|
+
lightingSamples: 0.6,
|
|
1022
|
+
shading: 0.4,
|
|
1023
|
+
updateCadence: 0.3
|
|
1024
|
+
},
|
|
1025
|
+
"volumetrics.volumetricShadow": { shadows: 0.8, updateCadence: 0.5 },
|
|
1026
|
+
"hdri.irradianceConvolution": {
|
|
1027
|
+
lightingSamples: 0.4,
|
|
1028
|
+
temporalReuse: 1,
|
|
1029
|
+
updateCadence: 1
|
|
1030
|
+
},
|
|
1031
|
+
"hdri.specularPrefilter": {
|
|
1032
|
+
lightingSamples: 0.5,
|
|
1033
|
+
temporalReuse: 1,
|
|
1034
|
+
updateCadence: 1
|
|
1035
|
+
},
|
|
1036
|
+
"hdri.brdfLut": {
|
|
1037
|
+
shading: 0.4,
|
|
1038
|
+
temporalReuse: 1,
|
|
1039
|
+
updateCadence: 1
|
|
1040
|
+
}
|
|
1041
|
+
}[key] ?? {}
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
1044
|
+
function resolveLightingImportanceSignals(techniqueName, jobKey) {
|
|
1045
|
+
const key = `${techniqueName}.${jobKey}`;
|
|
1046
|
+
return Object.freeze(
|
|
1047
|
+
{
|
|
1048
|
+
"hybrid.directLighting": { visible: true, shadowSignificance: "high" },
|
|
1049
|
+
"hybrid.screenTrace": { visible: true, reflectionSignificance: "high" },
|
|
1050
|
+
"hybrid.radianceCache": { visible: true },
|
|
1051
|
+
"hybrid.finalGather": {
|
|
1052
|
+
visible: true,
|
|
1053
|
+
shadowSignificance: "critical",
|
|
1054
|
+
reflectionSignificance: "high"
|
|
1055
|
+
},
|
|
1056
|
+
"hybrid.reflectionResolve": { visible: true, reflectionSignificance: "high" },
|
|
1057
|
+
"pathtracer.pathTrace": {
|
|
1058
|
+
visible: true,
|
|
1059
|
+
shadowSignificance: "high",
|
|
1060
|
+
reflectionSignificance: "high"
|
|
1061
|
+
},
|
|
1062
|
+
"pathtracer.accumulate": { visible: true },
|
|
1063
|
+
"pathtracer.denoise": { visible: true },
|
|
1064
|
+
"volumetrics.froxelIntegrate": { visible: true },
|
|
1065
|
+
"volumetrics.volumetricShadow": { visible: true, shadowSignificance: "high" },
|
|
1066
|
+
"hdri.irradianceConvolution": { visible: false },
|
|
1067
|
+
"hdri.specularPrefilter": { visible: false, reflectionSignificance: "medium" },
|
|
1068
|
+
"hdri.brdfLut": { visible: false }
|
|
1069
|
+
}[key] ?? {}
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
function buildWorkerManifestJob(techniqueName, job) {
|
|
1073
|
+
const spec = lightingWorkerSpecPresets[techniqueName].jobs[job.key];
|
|
1074
|
+
const dag = lightingWorkerDagSpecs[techniqueName][job.key];
|
|
1075
|
+
const dependencies = dag.dependencies.map(
|
|
1076
|
+
(dependency) => `lighting.${techniqueName}.${dependency}`
|
|
1077
|
+
);
|
|
1078
|
+
return Object.freeze({
|
|
1079
|
+
key: job.key,
|
|
1080
|
+
label: job.label,
|
|
1081
|
+
worker: Object.freeze({
|
|
1082
|
+
jobType: job.label,
|
|
1083
|
+
queueClass: lightingWorkerQueueClass,
|
|
1084
|
+
priority: dag.priority,
|
|
1085
|
+
dependencies: Object.freeze(dependencies),
|
|
1086
|
+
schedulerMode: "dag"
|
|
1087
|
+
}),
|
|
1088
|
+
performance: Object.freeze({
|
|
1089
|
+
id: job.label,
|
|
1090
|
+
jobType: job.label,
|
|
1091
|
+
queueClass: lightingWorkerQueueClass,
|
|
1092
|
+
domain: spec.domain,
|
|
1093
|
+
authority: "visual",
|
|
1094
|
+
importance: spec.importance,
|
|
1095
|
+
qualityDimensions: resolveLightingQualityDimensions(techniqueName, job.key),
|
|
1096
|
+
importanceSignals: resolveLightingImportanceSignals(techniqueName, job.key),
|
|
1097
|
+
levels: spec.levels
|
|
1098
|
+
}),
|
|
1099
|
+
debug: Object.freeze({
|
|
1100
|
+
owner: lightingDebugOwner,
|
|
1101
|
+
queueClass: lightingWorkerQueueClass,
|
|
1102
|
+
jobType: job.label,
|
|
1103
|
+
tags: Object.freeze([
|
|
1104
|
+
"lighting",
|
|
1105
|
+
techniqueName,
|
|
1106
|
+
job.key,
|
|
1107
|
+
spec.domain
|
|
1108
|
+
]),
|
|
1109
|
+
suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds])
|
|
1110
|
+
})
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
function buildLightingWorkerManifest(name, technique) {
|
|
1114
|
+
const spec = lightingWorkerSpecPresets[name];
|
|
1115
|
+
return Object.freeze({
|
|
1116
|
+
schemaVersion: 1,
|
|
1117
|
+
owner: lightingDebugOwner,
|
|
1118
|
+
technique: name,
|
|
1119
|
+
description: technique.description,
|
|
1120
|
+
queueClass: lightingWorkerQueueClass,
|
|
1121
|
+
schedulerMode: "dag",
|
|
1122
|
+
suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),
|
|
1123
|
+
jobs: Object.freeze(
|
|
1124
|
+
technique.jobs.map((job) => buildWorkerManifestJob(name, job))
|
|
1125
|
+
)
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
function getTechniqueJob(technique, key) {
|
|
1129
|
+
const job = technique.jobs.find((entry) => entry.key === key);
|
|
1130
|
+
if (!job) {
|
|
1131
|
+
const available = technique.jobs.map((entry) => entry.key).join(", ");
|
|
1132
|
+
throw new Error(
|
|
1133
|
+
`Unknown job "${key}" for technique "${technique.name}". Available: ${available}.`
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
return job;
|
|
1137
|
+
}
|
|
1138
|
+
function getLightingTechnique(name = defaultLightingTechnique) {
|
|
1139
|
+
const technique = lightingTechniques[name];
|
|
1140
|
+
if (!technique) {
|
|
1141
|
+
const available = lightingTechniqueNames.join(", ");
|
|
1142
|
+
throw new Error(`Unknown lighting technique "${name}". Available: ${available}.`);
|
|
1143
|
+
}
|
|
1144
|
+
return technique;
|
|
1145
|
+
}
|
|
1146
|
+
function getLightingProfile(name = defaultLightingProfile) {
|
|
1147
|
+
const profile = lightingProfiles[name];
|
|
1148
|
+
if (!profile) {
|
|
1149
|
+
const available = lightingProfileNames.join(", ");
|
|
1150
|
+
throw new Error(`Unknown lighting profile "${name}". Available: ${available}.`);
|
|
1151
|
+
}
|
|
1152
|
+
return profile;
|
|
1153
|
+
}
|
|
1154
|
+
function getLightingTechniqueWorkerManifest(name = defaultLightingTechnique) {
|
|
1155
|
+
const manifest = lightingWorkerManifests[name];
|
|
1156
|
+
if (!manifest) {
|
|
1157
|
+
const available = lightingTechniqueNames.join(", ");
|
|
1158
|
+
throw new Error(
|
|
1159
|
+
`Unknown lighting technique "${name}". Available: ${available}.`
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
return manifest;
|
|
1163
|
+
}
|
|
1164
|
+
function getLightingProfileWorkerManifest(name = defaultLightingProfile) {
|
|
1165
|
+
const profile = getLightingProfile(name);
|
|
1166
|
+
const techniques = profile.techniques.map(
|
|
1167
|
+
(techniqueName) => getLightingTechniqueWorkerManifest(techniqueName)
|
|
1168
|
+
);
|
|
1169
|
+
const lightingBandPlan = createLightingBandPlan({ profile: profile.name });
|
|
1170
|
+
return Object.freeze({
|
|
1171
|
+
schemaVersion: 1,
|
|
1172
|
+
owner: lightingDebugOwner,
|
|
1173
|
+
profile: profile.name,
|
|
1174
|
+
description: profile.description,
|
|
1175
|
+
schedulerMode: "dag",
|
|
1176
|
+
techniques: Object.freeze(techniques),
|
|
1177
|
+
lightingBands: lightingBandPlan.bands,
|
|
1178
|
+
jobs: Object.freeze(techniques.flatMap((technique) => technique.jobs))
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
function assertNotHtmlWgsl(source, context) {
|
|
1182
|
+
const sample = source.slice(0, 200).toLowerCase();
|
|
1183
|
+
if (sample.includes("<!doctype") || sample.includes("<html") || sample.includes("<meta")) {
|
|
1184
|
+
const label = context ? ` for ${context}` : "";
|
|
1185
|
+
throw new Error(
|
|
1186
|
+
`Expected WGSL${label} but received HTML. Check the URL or server root.`
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
async function loadWgslSource(options = {}) {
|
|
1191
|
+
const { wgsl, url, fetcher = globalThis.fetch, base } = options ?? {};
|
|
1192
|
+
if (typeof wgsl === "string") {
|
|
1193
|
+
assertNotHtmlWgsl(wgsl, "inline WGSL");
|
|
1194
|
+
return wgsl;
|
|
1195
|
+
}
|
|
1196
|
+
if (!url) {
|
|
1197
|
+
return null;
|
|
1198
|
+
}
|
|
1199
|
+
const resolved = url instanceof URL ? url : new URL(url, base ?? baseUrl);
|
|
1200
|
+
if (!fetcher || resolved.protocol === "file:") {
|
|
1201
|
+
const { readFile } = await import("fs/promises");
|
|
1202
|
+
const { fileURLToPath } = await import("url");
|
|
1203
|
+
const source2 = await readFile(fileURLToPath(resolved), "utf8");
|
|
1204
|
+
assertNotHtmlWgsl(source2, resolved.href);
|
|
1205
|
+
return source2;
|
|
1206
|
+
}
|
|
1207
|
+
const response = await fetcher(resolved);
|
|
1208
|
+
if (!response.ok) {
|
|
1209
|
+
const status = "status" in response ? response.status : "unknown";
|
|
1210
|
+
const statusText = "statusText" in response ? response.statusText : "";
|
|
1211
|
+
const detail = statusText ? `${status} ${statusText}` : `${status}`;
|
|
1212
|
+
throw new Error(`Failed to load WGSL (${detail})`);
|
|
1213
|
+
}
|
|
1214
|
+
const source = await response.text();
|
|
1215
|
+
assertNotHtmlWgsl(source, resolved.href);
|
|
1216
|
+
return source;
|
|
1217
|
+
}
|
|
1218
|
+
async function loadTechniquePrelude(technique, fetcher) {
|
|
1219
|
+
const source = await loadWgslSource({ url: technique.preludeUrl, fetcher });
|
|
1220
|
+
if (typeof source !== "string") {
|
|
1221
|
+
throw new Error(`Failed to load ${technique.name} prelude WGSL source.`);
|
|
1222
|
+
}
|
|
1223
|
+
return source;
|
|
1224
|
+
}
|
|
1225
|
+
async function loadTechniqueJob(technique, job, fetcher) {
|
|
1226
|
+
const source = await loadWgslSource({ url: job.url, fetcher });
|
|
1227
|
+
if (typeof source !== "string") {
|
|
1228
|
+
throw new Error(
|
|
1229
|
+
`Failed to load ${technique.name} job "${job.key}" WGSL source.`
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
return source;
|
|
1233
|
+
}
|
|
1234
|
+
async function loadLightingTechniquePreludeWgsl(techniqueName, options = {}) {
|
|
1235
|
+
const { fetcher } = options ?? {};
|
|
1236
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1237
|
+
return loadTechniquePrelude(technique, fetcher);
|
|
1238
|
+
}
|
|
1239
|
+
async function loadLightingTechniqueJobWgsl(techniqueName, jobKey, options = {}) {
|
|
1240
|
+
const { fetcher } = options ?? {};
|
|
1241
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1242
|
+
const job = getTechniqueJob(technique, jobKey);
|
|
1243
|
+
return loadTechniqueJob(technique, job, fetcher);
|
|
1244
|
+
}
|
|
1245
|
+
async function loadLightingTechniqueJobs(techniqueName, options = {}) {
|
|
1246
|
+
const { fetcher } = options ?? {};
|
|
1247
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1248
|
+
const preludeWgsl = await loadTechniquePrelude(technique, fetcher);
|
|
1249
|
+
const jobSources = await Promise.all(
|
|
1250
|
+
technique.jobs.map((job) => loadTechniqueJob(technique, job, fetcher))
|
|
1251
|
+
);
|
|
1252
|
+
const jobs = technique.jobs.map((job, index) => ({
|
|
1253
|
+
wgsl: jobSources[index],
|
|
1254
|
+
label: job.label,
|
|
1255
|
+
sourceName: job.sourceName
|
|
1256
|
+
}));
|
|
1257
|
+
return { preludeWgsl, jobs };
|
|
1258
|
+
}
|
|
1259
|
+
async function loadLightingTechniqueWorkerBundle(techniqueName = defaultLightingTechnique, options = {}) {
|
|
1260
|
+
const technique = getLightingTechnique(techniqueName);
|
|
1261
|
+
const { preludeWgsl, jobs } = await loadLightingTechniqueJobs(
|
|
1262
|
+
technique.name,
|
|
1263
|
+
options
|
|
1264
|
+
);
|
|
1265
|
+
return {
|
|
1266
|
+
technique: technique.name,
|
|
1267
|
+
preludeWgsl,
|
|
1268
|
+
jobs,
|
|
1269
|
+
workerManifest: getLightingTechniqueWorkerManifest(technique.name)
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
async function loadLightingPreludeWgsl(options = {}) {
|
|
1273
|
+
const { fetcher } = options ?? {};
|
|
1274
|
+
return loadTechniquePrelude(defaultTechnique, fetcher);
|
|
1275
|
+
}
|
|
1276
|
+
async function loadLightingJobs(options = {}) {
|
|
1277
|
+
return loadLightingTechniqueJobs(defaultLightingTechnique, options);
|
|
1278
|
+
}
|
|
1279
|
+
async function loadLightingProfile(profileName, options = {}) {
|
|
1280
|
+
const profile = getLightingProfile(profileName);
|
|
1281
|
+
const techniques = await Promise.all(
|
|
1282
|
+
profile.techniques.map(async (techniqueName) => {
|
|
1283
|
+
const { preludeWgsl, jobs } = await loadLightingTechniqueJobs(
|
|
1284
|
+
techniqueName,
|
|
1285
|
+
options
|
|
1286
|
+
);
|
|
1287
|
+
return {
|
|
1288
|
+
technique: techniqueName,
|
|
1289
|
+
preludeWgsl,
|
|
1290
|
+
jobs
|
|
1291
|
+
};
|
|
1292
|
+
})
|
|
1293
|
+
);
|
|
1294
|
+
return { profile, techniques };
|
|
1295
|
+
}
|
|
1296
|
+
async function loadLightingProfileWorkerPlan(profileName = defaultLightingProfile, options = {}) {
|
|
1297
|
+
const profile = getLightingProfile(profileName);
|
|
1298
|
+
const techniques = await Promise.all(
|
|
1299
|
+
profile.techniques.map(
|
|
1300
|
+
(techniqueName) => loadLightingTechniqueWorkerBundle(techniqueName, options)
|
|
1301
|
+
)
|
|
1302
|
+
);
|
|
1303
|
+
return {
|
|
1304
|
+
profile,
|
|
1305
|
+
techniques,
|
|
1306
|
+
lightingBandPlan: createLightingBandPlan({ profile: profile.name }),
|
|
1307
|
+
workerManifest: getLightingProfileWorkerManifest(profile.name)
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
var import_meta2, __require, baseUrl, techniqueSpecs, lightingTechniques, lightingTechniqueNames, defaultLightingTechnique, profileSpecs, lightingProfiles, lightingProfileNames, defaultLightingProfile, lightingProfileModeOrder, lightingEnvironmentPresetNames, defaultAdaptiveLightingProfilePolicy, lightingDistanceBands, lightingWorkerQueueClass, lightingDebugOwner, environmentLightingPresets, lightingImportanceLevels, lightingBandPolicySpecs, lightingProfileModeEstimatedCostMs, lightingWorkerSpecPresets, lightingWorkerDagSpecs, lightingWorkerManifests, defaultTechnique, lightingPreludeWgslUrl, lightingJobLabels, lightingJobs;
|
|
1311
|
+
var init_dist = __esm({
|
|
1312
|
+
"node_modules/@plasius/gpu-lighting/dist/index.js"() {
|
|
1313
|
+
import_meta2 = {};
|
|
1314
|
+
__require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
1315
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
1316
|
+
}) : x)(function(x) {
|
|
1317
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
1318
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
1319
|
+
});
|
|
1320
|
+
baseUrl = (() => {
|
|
1321
|
+
if (typeof import_meta2.url !== "undefined") {
|
|
1322
|
+
return createModuleBaseUrl(import_meta2.url);
|
|
1323
|
+
}
|
|
1324
|
+
if (typeof __filename !== "undefined" && typeof __require !== "undefined") {
|
|
1325
|
+
const { pathToFileURL } = __require("url");
|
|
1326
|
+
return pathToFileURL(__filename);
|
|
1327
|
+
}
|
|
1328
|
+
const base = typeof process !== "undefined" && process.cwd ? `file://${process.cwd()}/` : "file:///";
|
|
1329
|
+
return new URL("./index.js", base);
|
|
1330
|
+
})();
|
|
1331
|
+
techniqueSpecs = {
|
|
1332
|
+
hybrid: {
|
|
1333
|
+
description: "Lumen-inspired hybrid realtime GI and reflections with radiance cache final gather.",
|
|
1334
|
+
prelude: "prelude.wgsl",
|
|
1335
|
+
jobs: {
|
|
1336
|
+
directLighting: "direct-lighting.job.wgsl",
|
|
1337
|
+
screenTrace: "screen-trace.job.wgsl",
|
|
1338
|
+
radianceCache: "radiance-cache.job.wgsl",
|
|
1339
|
+
finalGather: "final-gather.job.wgsl",
|
|
1340
|
+
reflectionResolve: "reflection-resolve.job.wgsl"
|
|
1341
|
+
}
|
|
1342
|
+
},
|
|
1343
|
+
pathtracer: {
|
|
1344
|
+
description: "Monte Carlo path-traced reference mode with progressive accumulation and denoise stage.",
|
|
1345
|
+
prelude: "prelude.wgsl",
|
|
1346
|
+
jobs: {
|
|
1347
|
+
pathTrace: "pathtrace.job.wgsl",
|
|
1348
|
+
accumulate: "accumulate.job.wgsl",
|
|
1349
|
+
denoise: "denoise.job.wgsl"
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
volumetrics: {
|
|
1353
|
+
description: "Froxel volumetric lighting for fog, shafts, and participating media shadows.",
|
|
1354
|
+
prelude: "prelude.wgsl",
|
|
1355
|
+
jobs: {
|
|
1356
|
+
froxelIntegrate: "froxel-integrate.job.wgsl",
|
|
1357
|
+
volumetricShadow: "volumetric-shadow.job.wgsl"
|
|
1358
|
+
}
|
|
1359
|
+
},
|
|
1360
|
+
hdri: {
|
|
1361
|
+
description: "HDRI and IBL precompute passes including irradiance, specular prefilter, and BRDF LUT.",
|
|
1362
|
+
prelude: "prelude.wgsl",
|
|
1363
|
+
jobs: {
|
|
1364
|
+
irradianceConvolution: "irradiance-convolution.job.wgsl",
|
|
1365
|
+
specularPrefilter: "specular-prefilter.job.wgsl",
|
|
1366
|
+
brdfLut: "brdf-lut.job.wgsl"
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1370
|
+
lightingTechniques = Object.freeze(
|
|
1371
|
+
Object.fromEntries(
|
|
1372
|
+
Object.entries(techniqueSpecs).map(([name, spec]) => [
|
|
1373
|
+
name,
|
|
1374
|
+
buildTechnique(name, spec)
|
|
1375
|
+
])
|
|
1376
|
+
)
|
|
1377
|
+
);
|
|
1378
|
+
lightingTechniqueNames = Object.freeze(Object.keys(lightingTechniques));
|
|
1379
|
+
defaultLightingTechnique = "hybrid";
|
|
1380
|
+
profileSpecs = {
|
|
1381
|
+
realtime: {
|
|
1382
|
+
description: "Primary runtime profile: hybrid GI/reflections with volumetrics and HDRI/IBL.",
|
|
1383
|
+
techniques: ["hybrid", "volumetrics", "hdri"]
|
|
1384
|
+
},
|
|
1385
|
+
hybrid: {
|
|
1386
|
+
description: "Hybrid-focused profile for direct tuning of Lumen-inspired realtime passes.",
|
|
1387
|
+
techniques: ["hybrid", "hdri"]
|
|
1388
|
+
},
|
|
1389
|
+
reference: {
|
|
1390
|
+
description: "Reference quality profile: path tracing plus volumetrics and HDRI/IBL validation.",
|
|
1391
|
+
techniques: ["pathtracer", "volumetrics", "hdri"]
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
lightingProfiles = Object.freeze(
|
|
1395
|
+
Object.fromEntries(
|
|
1396
|
+
Object.entries(profileSpecs).map(([name, spec]) => [
|
|
1397
|
+
name,
|
|
1398
|
+
buildProfile(name, spec)
|
|
1399
|
+
])
|
|
1400
|
+
)
|
|
1401
|
+
);
|
|
1402
|
+
lightingProfileNames = Object.freeze(Object.keys(lightingProfiles));
|
|
1403
|
+
defaultLightingProfile = "realtime";
|
|
1404
|
+
lightingProfileModeOrder = Object.freeze([
|
|
1405
|
+
"realtime",
|
|
1406
|
+
"hybrid",
|
|
1407
|
+
"reference"
|
|
1408
|
+
]);
|
|
1409
|
+
lightingEnvironmentPresetNames = Object.freeze([
|
|
1410
|
+
"moonlit-harbor",
|
|
1411
|
+
"product-studio",
|
|
1412
|
+
"neutral-studio"
|
|
1413
|
+
]);
|
|
1414
|
+
defaultAdaptiveLightingProfilePolicy = Object.freeze({
|
|
1415
|
+
preferredProfile: "reference",
|
|
1416
|
+
minimumFrameRate: 30,
|
|
1417
|
+
sampleWindowSize: 4
|
|
1418
|
+
});
|
|
1419
|
+
lightingDistanceBands = Object.freeze([
|
|
1420
|
+
"near",
|
|
1421
|
+
"mid",
|
|
1422
|
+
"far",
|
|
1423
|
+
"horizon"
|
|
1424
|
+
]);
|
|
1425
|
+
lightingWorkerQueueClass = "lighting";
|
|
1426
|
+
lightingDebugOwner = "lighting";
|
|
1427
|
+
environmentLightingPresets = Object.freeze({
|
|
1428
|
+
"moonlit-harbor": Object.freeze({
|
|
1429
|
+
preset: "moonlit-harbor",
|
|
1430
|
+
environmentMode: 0,
|
|
1431
|
+
environmentIntensity: 0.86,
|
|
1432
|
+
exposure: 1,
|
|
1433
|
+
horizonColor: freezeVec4([0.33, 0.43, 0.53, 1]),
|
|
1434
|
+
zenithColor: freezeVec4([0.035, 0.07, 0.14, 1]),
|
|
1435
|
+
sunDirection: Object.freeze(normalizeVector3([0.22, 0.88, 0.42], [0, 1, 0])),
|
|
1436
|
+
sunColor: freezeVec4([2.1, 2.25, 2.65, 1]),
|
|
1437
|
+
ambientColor: freezeVec4([0.018, 0.023, 0.03, 1])
|
|
1438
|
+
}),
|
|
1439
|
+
"product-studio": Object.freeze({
|
|
1440
|
+
preset: "product-studio",
|
|
1441
|
+
environmentMode: 1,
|
|
1442
|
+
environmentIntensity: 1.05,
|
|
1443
|
+
exposure: 1,
|
|
1444
|
+
horizonColor: freezeVec4([0.52, 0.61, 0.65, 1]),
|
|
1445
|
+
zenithColor: freezeVec4([0.18, 0.22, 0.26, 1]),
|
|
1446
|
+
sunDirection: Object.freeze(normalizeVector3([0.18, 0.93, 0.24], [0, 1, 0])),
|
|
1447
|
+
sunColor: freezeVec4([3.8, 3.55, 2.85, 1]),
|
|
1448
|
+
ambientColor: freezeVec4([0.024, 0.027, 0.03, 1])
|
|
1449
|
+
}),
|
|
1450
|
+
"neutral-studio": Object.freeze({
|
|
1451
|
+
preset: "neutral-studio",
|
|
1452
|
+
environmentMode: 2,
|
|
1453
|
+
environmentIntensity: 0.95,
|
|
1454
|
+
exposure: 1,
|
|
1455
|
+
horizonColor: freezeVec4([0.48, 0.53, 0.55, 1]),
|
|
1456
|
+
zenithColor: freezeVec4([0.24, 0.26, 0.29, 1]),
|
|
1457
|
+
sunDirection: Object.freeze(normalizeVector3([-0.24, 0.86, 0.36], [0, 1, 0])),
|
|
1458
|
+
sunColor: freezeVec4([2.4, 2.35, 2.2, 1]),
|
|
1459
|
+
ambientColor: freezeVec4([0.028, 0.029, 0.03, 1])
|
|
1460
|
+
})
|
|
1461
|
+
});
|
|
1462
|
+
lightingImportanceLevels = Object.freeze([
|
|
1463
|
+
"low",
|
|
1464
|
+
"medium",
|
|
1465
|
+
"high",
|
|
1466
|
+
"critical"
|
|
1467
|
+
]);
|
|
1468
|
+
lightingBandPolicySpecs = Object.freeze({
|
|
1469
|
+
near: Object.freeze({
|
|
1470
|
+
primaryShadowSource: "ray-traced-primary",
|
|
1471
|
+
assistShadowSources: Object.freeze(["visibility-raster", "shadow-map-assist"]),
|
|
1472
|
+
temporalReuse: "balanced",
|
|
1473
|
+
updateCadenceDivisor: 1,
|
|
1474
|
+
liveObjectShadows: true,
|
|
1475
|
+
impressionOnly: false
|
|
1476
|
+
}),
|
|
1477
|
+
mid: Object.freeze({
|
|
1478
|
+
primaryShadowSource: "selective-raster-and-proxy",
|
|
1479
|
+
assistShadowSources: Object.freeze([
|
|
1480
|
+
"regional-shadow-map",
|
|
1481
|
+
"proxy-caster",
|
|
1482
|
+
"temporal-history"
|
|
1483
|
+
]),
|
|
1484
|
+
temporalReuse: "aggressive",
|
|
1485
|
+
updateCadenceDivisor: 2,
|
|
1486
|
+
liveObjectShadows: true,
|
|
1487
|
+
impressionOnly: false
|
|
1488
|
+
}),
|
|
1489
|
+
far: Object.freeze({
|
|
1490
|
+
primaryShadowSource: "merged-proxy-casters",
|
|
1491
|
+
assistShadowSources: Object.freeze([
|
|
1492
|
+
"coarse-directional",
|
|
1493
|
+
"semi-static-occlusion"
|
|
1494
|
+
]),
|
|
1495
|
+
temporalReuse: "high",
|
|
1496
|
+
updateCadenceDivisor: 8,
|
|
1497
|
+
liveObjectShadows: false,
|
|
1498
|
+
impressionOnly: false
|
|
1499
|
+
}),
|
|
1500
|
+
horizon: Object.freeze({
|
|
1501
|
+
primaryShadowSource: "baked-impression",
|
|
1502
|
+
assistShadowSources: Object.freeze(["atmospheric-gradient", "skyline-darkening"]),
|
|
1503
|
+
temporalReuse: "baked",
|
|
1504
|
+
updateCadenceDivisor: 60,
|
|
1505
|
+
liveObjectShadows: false,
|
|
1506
|
+
impressionOnly: true
|
|
1507
|
+
})
|
|
1508
|
+
});
|
|
1509
|
+
lightingProfileModeEstimatedCostMs = Object.freeze({
|
|
1510
|
+
realtime: 4.5,
|
|
1511
|
+
hybrid: 7.5,
|
|
1512
|
+
reference: 12.5
|
|
1513
|
+
});
|
|
1514
|
+
lightingWorkerSpecPresets = {
|
|
1515
|
+
hybrid: {
|
|
1516
|
+
suggestedAllocationIds: [
|
|
1517
|
+
"lighting.hybrid.radiance-cache",
|
|
1518
|
+
"lighting.hybrid.reflection-history",
|
|
1519
|
+
"lighting.hybrid.shadow-atlas"
|
|
1520
|
+
],
|
|
1521
|
+
jobs: {
|
|
1522
|
+
directLighting: {
|
|
1523
|
+
domain: "lighting",
|
|
1524
|
+
importance: "high",
|
|
1525
|
+
levels: buildWorkerBudgetLevels(
|
|
1526
|
+
"lighting.hybrid.directLighting",
|
|
1527
|
+
lightingWorkerQueueClass,
|
|
1528
|
+
{
|
|
1529
|
+
low: {
|
|
1530
|
+
estimatedCostMs: 0.5,
|
|
1531
|
+
maxDispatchesPerFrame: 1,
|
|
1532
|
+
maxJobsPerDispatch: 64,
|
|
1533
|
+
cadenceDivisor: 2,
|
|
1534
|
+
workgroupScale: 0.5,
|
|
1535
|
+
maxQueueDepth: 128
|
|
1536
|
+
},
|
|
1537
|
+
medium: {
|
|
1538
|
+
estimatedCostMs: 0.9,
|
|
1539
|
+
maxDispatchesPerFrame: 1,
|
|
1540
|
+
maxJobsPerDispatch: 128,
|
|
1541
|
+
cadenceDivisor: 1,
|
|
1542
|
+
workgroupScale: 0.75,
|
|
1543
|
+
maxQueueDepth: 256
|
|
1544
|
+
},
|
|
1545
|
+
high: {
|
|
1546
|
+
estimatedCostMs: 1.2,
|
|
1547
|
+
maxDispatchesPerFrame: 2,
|
|
1548
|
+
maxJobsPerDispatch: 256,
|
|
1549
|
+
cadenceDivisor: 1,
|
|
1550
|
+
workgroupScale: 1,
|
|
1551
|
+
maxQueueDepth: 512
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
),
|
|
1555
|
+
suggestedAllocationIds: ["lighting.hybrid.shadow-atlas"]
|
|
1556
|
+
},
|
|
1557
|
+
screenTrace: {
|
|
1558
|
+
domain: "reflections",
|
|
1559
|
+
importance: "high",
|
|
1560
|
+
levels: buildWorkerBudgetLevels(
|
|
1561
|
+
"lighting.hybrid.screenTrace",
|
|
1562
|
+
lightingWorkerQueueClass,
|
|
1563
|
+
{
|
|
1564
|
+
low: {
|
|
1565
|
+
estimatedCostMs: 0.8,
|
|
1566
|
+
maxDispatchesPerFrame: 1,
|
|
1567
|
+
maxJobsPerDispatch: 32,
|
|
1568
|
+
cadenceDivisor: 3,
|
|
1569
|
+
workgroupScale: 0.4,
|
|
1570
|
+
maxQueueDepth: 96
|
|
1571
|
+
},
|
|
1572
|
+
medium: {
|
|
1573
|
+
estimatedCostMs: 1.5,
|
|
1574
|
+
maxDispatchesPerFrame: 1,
|
|
1575
|
+
maxJobsPerDispatch: 96,
|
|
1576
|
+
cadenceDivisor: 2,
|
|
1577
|
+
workgroupScale: 0.7,
|
|
1578
|
+
maxQueueDepth: 192
|
|
1579
|
+
},
|
|
1580
|
+
high: {
|
|
1581
|
+
estimatedCostMs: 2.2,
|
|
1582
|
+
maxDispatchesPerFrame: 2,
|
|
1583
|
+
maxJobsPerDispatch: 192,
|
|
1584
|
+
cadenceDivisor: 1,
|
|
1585
|
+
workgroupScale: 1,
|
|
1586
|
+
maxQueueDepth: 384
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
),
|
|
1590
|
+
suggestedAllocationIds: ["lighting.hybrid.reflection-history"]
|
|
1591
|
+
},
|
|
1592
|
+
radianceCache: {
|
|
1593
|
+
domain: "lighting",
|
|
1594
|
+
importance: "high",
|
|
1595
|
+
levels: buildWorkerBudgetLevels(
|
|
1596
|
+
"lighting.hybrid.radianceCache",
|
|
1597
|
+
lightingWorkerQueueClass,
|
|
1598
|
+
{
|
|
1599
|
+
low: {
|
|
1600
|
+
estimatedCostMs: 0.7,
|
|
1601
|
+
maxDispatchesPerFrame: 1,
|
|
1602
|
+
maxJobsPerDispatch: 32,
|
|
1603
|
+
cadenceDivisor: 2,
|
|
1604
|
+
workgroupScale: 0.5,
|
|
1605
|
+
maxQueueDepth: 96
|
|
1606
|
+
},
|
|
1607
|
+
medium: {
|
|
1608
|
+
estimatedCostMs: 1.2,
|
|
1609
|
+
maxDispatchesPerFrame: 1,
|
|
1610
|
+
maxJobsPerDispatch: 64,
|
|
1611
|
+
cadenceDivisor: 1,
|
|
1612
|
+
workgroupScale: 0.75,
|
|
1613
|
+
maxQueueDepth: 192
|
|
1614
|
+
},
|
|
1615
|
+
high: {
|
|
1616
|
+
estimatedCostMs: 1.8,
|
|
1617
|
+
maxDispatchesPerFrame: 2,
|
|
1618
|
+
maxJobsPerDispatch: 128,
|
|
1619
|
+
cadenceDivisor: 1,
|
|
1620
|
+
workgroupScale: 1,
|
|
1621
|
+
maxQueueDepth: 256
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
),
|
|
1625
|
+
suggestedAllocationIds: ["lighting.hybrid.radiance-cache"]
|
|
1626
|
+
},
|
|
1627
|
+
finalGather: {
|
|
1628
|
+
domain: "lighting",
|
|
1629
|
+
importance: "critical",
|
|
1630
|
+
levels: buildWorkerBudgetLevels(
|
|
1631
|
+
"lighting.hybrid.finalGather",
|
|
1632
|
+
lightingWorkerQueueClass,
|
|
1633
|
+
{
|
|
1634
|
+
low: {
|
|
1635
|
+
estimatedCostMs: 1,
|
|
1636
|
+
maxDispatchesPerFrame: 1,
|
|
1637
|
+
maxJobsPerDispatch: 48,
|
|
1638
|
+
cadenceDivisor: 2,
|
|
1639
|
+
workgroupScale: 0.5,
|
|
1640
|
+
maxQueueDepth: 128
|
|
1641
|
+
},
|
|
1642
|
+
medium: {
|
|
1643
|
+
estimatedCostMs: 1.8,
|
|
1644
|
+
maxDispatchesPerFrame: 1,
|
|
1645
|
+
maxJobsPerDispatch: 96,
|
|
1646
|
+
cadenceDivisor: 1,
|
|
1647
|
+
workgroupScale: 0.75,
|
|
1648
|
+
maxQueueDepth: 256
|
|
1649
|
+
},
|
|
1650
|
+
high: {
|
|
1651
|
+
estimatedCostMs: 2.6,
|
|
1652
|
+
maxDispatchesPerFrame: 2,
|
|
1653
|
+
maxJobsPerDispatch: 192,
|
|
1654
|
+
cadenceDivisor: 1,
|
|
1655
|
+
workgroupScale: 1,
|
|
1656
|
+
maxQueueDepth: 384
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
),
|
|
1660
|
+
suggestedAllocationIds: [
|
|
1661
|
+
"lighting.hybrid.radiance-cache",
|
|
1662
|
+
"lighting.hybrid.reflection-history"
|
|
1663
|
+
]
|
|
1664
|
+
},
|
|
1665
|
+
reflectionResolve: {
|
|
1666
|
+
domain: "reflections",
|
|
1667
|
+
importance: "high",
|
|
1668
|
+
levels: buildWorkerBudgetLevels(
|
|
1669
|
+
"lighting.hybrid.reflectionResolve",
|
|
1670
|
+
lightingWorkerQueueClass,
|
|
1671
|
+
{
|
|
1672
|
+
low: {
|
|
1673
|
+
estimatedCostMs: 0.4,
|
|
1674
|
+
maxDispatchesPerFrame: 1,
|
|
1675
|
+
maxJobsPerDispatch: 32,
|
|
1676
|
+
cadenceDivisor: 2,
|
|
1677
|
+
workgroupScale: 0.5,
|
|
1678
|
+
maxQueueDepth: 96
|
|
1679
|
+
},
|
|
1680
|
+
medium: {
|
|
1681
|
+
estimatedCostMs: 0.8,
|
|
1682
|
+
maxDispatchesPerFrame: 1,
|
|
1683
|
+
maxJobsPerDispatch: 64,
|
|
1684
|
+
cadenceDivisor: 1,
|
|
1685
|
+
workgroupScale: 0.75,
|
|
1686
|
+
maxQueueDepth: 192
|
|
1687
|
+
},
|
|
1688
|
+
high: {
|
|
1689
|
+
estimatedCostMs: 1.2,
|
|
1690
|
+
maxDispatchesPerFrame: 1,
|
|
1691
|
+
maxJobsPerDispatch: 128,
|
|
1692
|
+
cadenceDivisor: 1,
|
|
1693
|
+
workgroupScale: 1,
|
|
1694
|
+
maxQueueDepth: 256
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
),
|
|
1698
|
+
suggestedAllocationIds: ["lighting.hybrid.reflection-history"]
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
},
|
|
1702
|
+
pathtracer: {
|
|
1703
|
+
suggestedAllocationIds: [
|
|
1704
|
+
"lighting.pathtracer.path-state",
|
|
1705
|
+
"lighting.pathtracer.accumulation",
|
|
1706
|
+
"lighting.pathtracer.denoise-history"
|
|
1707
|
+
],
|
|
1708
|
+
jobs: {
|
|
1709
|
+
pathTrace: {
|
|
1710
|
+
domain: "lighting",
|
|
1711
|
+
importance: "critical",
|
|
1712
|
+
levels: buildWorkerBudgetLevels(
|
|
1713
|
+
"lighting.pathtracer.pathTrace",
|
|
1714
|
+
lightingWorkerQueueClass,
|
|
1715
|
+
{
|
|
1716
|
+
low: {
|
|
1717
|
+
estimatedCostMs: 1.2,
|
|
1718
|
+
maxDispatchesPerFrame: 1,
|
|
1719
|
+
maxJobsPerDispatch: 16,
|
|
1720
|
+
cadenceDivisor: 3,
|
|
1721
|
+
workgroupScale: 0.45,
|
|
1722
|
+
maxQueueDepth: 48
|
|
1723
|
+
},
|
|
1724
|
+
medium: {
|
|
1725
|
+
estimatedCostMs: 2.3,
|
|
1726
|
+
maxDispatchesPerFrame: 1,
|
|
1727
|
+
maxJobsPerDispatch: 32,
|
|
1728
|
+
cadenceDivisor: 2,
|
|
1729
|
+
workgroupScale: 0.7,
|
|
1730
|
+
maxQueueDepth: 96
|
|
1731
|
+
},
|
|
1732
|
+
high: {
|
|
1733
|
+
estimatedCostMs: 3.8,
|
|
1734
|
+
maxDispatchesPerFrame: 2,
|
|
1735
|
+
maxJobsPerDispatch: 64,
|
|
1736
|
+
cadenceDivisor: 1,
|
|
1737
|
+
workgroupScale: 1,
|
|
1738
|
+
maxQueueDepth: 128
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
),
|
|
1742
|
+
suggestedAllocationIds: ["lighting.pathtracer.path-state"]
|
|
1743
|
+
},
|
|
1744
|
+
accumulate: {
|
|
1745
|
+
domain: "lighting",
|
|
1746
|
+
importance: "medium",
|
|
1747
|
+
levels: buildWorkerBudgetLevels(
|
|
1748
|
+
"lighting.pathtracer.accumulate",
|
|
1749
|
+
lightingWorkerQueueClass,
|
|
1750
|
+
{
|
|
1751
|
+
low: {
|
|
1752
|
+
estimatedCostMs: 0.4,
|
|
1753
|
+
maxDispatchesPerFrame: 1,
|
|
1754
|
+
maxJobsPerDispatch: 16,
|
|
1755
|
+
cadenceDivisor: 2,
|
|
1756
|
+
workgroupScale: 0.5,
|
|
1757
|
+
maxQueueDepth: 32
|
|
1758
|
+
},
|
|
1759
|
+
medium: {
|
|
1760
|
+
estimatedCostMs: 0.8,
|
|
1761
|
+
maxDispatchesPerFrame: 1,
|
|
1762
|
+
maxJobsPerDispatch: 32,
|
|
1763
|
+
cadenceDivisor: 1,
|
|
1764
|
+
workgroupScale: 0.75,
|
|
1765
|
+
maxQueueDepth: 64
|
|
1766
|
+
},
|
|
1767
|
+
high: {
|
|
1768
|
+
estimatedCostMs: 1.1,
|
|
1769
|
+
maxDispatchesPerFrame: 1,
|
|
1770
|
+
maxJobsPerDispatch: 64,
|
|
1771
|
+
cadenceDivisor: 1,
|
|
1772
|
+
workgroupScale: 1,
|
|
1773
|
+
maxQueueDepth: 96
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
),
|
|
1777
|
+
suggestedAllocationIds: ["lighting.pathtracer.accumulation"]
|
|
1778
|
+
},
|
|
1779
|
+
denoise: {
|
|
1780
|
+
domain: "post-processing",
|
|
1781
|
+
importance: "high",
|
|
1782
|
+
levels: buildWorkerBudgetLevels(
|
|
1783
|
+
"lighting.pathtracer.denoise",
|
|
1784
|
+
lightingWorkerQueueClass,
|
|
1785
|
+
{
|
|
1786
|
+
low: {
|
|
1787
|
+
estimatedCostMs: 0.4,
|
|
1788
|
+
maxDispatchesPerFrame: 1,
|
|
1789
|
+
maxJobsPerDispatch: 16,
|
|
1790
|
+
cadenceDivisor: 2,
|
|
1791
|
+
workgroupScale: 0.5,
|
|
1792
|
+
maxQueueDepth: 32
|
|
1793
|
+
},
|
|
1794
|
+
medium: {
|
|
1795
|
+
estimatedCostMs: 0.9,
|
|
1796
|
+
maxDispatchesPerFrame: 1,
|
|
1797
|
+
maxJobsPerDispatch: 32,
|
|
1798
|
+
cadenceDivisor: 1,
|
|
1799
|
+
workgroupScale: 0.75,
|
|
1800
|
+
maxQueueDepth: 64
|
|
1801
|
+
},
|
|
1802
|
+
high: {
|
|
1803
|
+
estimatedCostMs: 1.4,
|
|
1804
|
+
maxDispatchesPerFrame: 1,
|
|
1805
|
+
maxJobsPerDispatch: 64,
|
|
1806
|
+
cadenceDivisor: 1,
|
|
1807
|
+
workgroupScale: 1,
|
|
1808
|
+
maxQueueDepth: 96
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
),
|
|
1812
|
+
suggestedAllocationIds: ["lighting.pathtracer.denoise-history"]
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
},
|
|
1816
|
+
volumetrics: {
|
|
1817
|
+
suggestedAllocationIds: [
|
|
1818
|
+
"lighting.volumetrics.froxel-grid",
|
|
1819
|
+
"lighting.volumetrics.shadow-history"
|
|
1820
|
+
],
|
|
1821
|
+
jobs: {
|
|
1822
|
+
froxelIntegrate: {
|
|
1823
|
+
domain: "volumetrics",
|
|
1824
|
+
importance: "high",
|
|
1825
|
+
levels: buildWorkerBudgetLevels(
|
|
1826
|
+
"lighting.volumetrics.froxelIntegrate",
|
|
1827
|
+
lightingWorkerQueueClass,
|
|
1828
|
+
{
|
|
1829
|
+
low: {
|
|
1830
|
+
estimatedCostMs: 0.6,
|
|
1831
|
+
maxDispatchesPerFrame: 1,
|
|
1832
|
+
maxJobsPerDispatch: 32,
|
|
1833
|
+
cadenceDivisor: 2,
|
|
1834
|
+
workgroupScale: 0.5,
|
|
1835
|
+
maxQueueDepth: 96
|
|
1836
|
+
},
|
|
1837
|
+
medium: {
|
|
1838
|
+
estimatedCostMs: 1.1,
|
|
1839
|
+
maxDispatchesPerFrame: 1,
|
|
1840
|
+
maxJobsPerDispatch: 64,
|
|
1841
|
+
cadenceDivisor: 1,
|
|
1842
|
+
workgroupScale: 0.75,
|
|
1843
|
+
maxQueueDepth: 192
|
|
1844
|
+
},
|
|
1845
|
+
high: {
|
|
1846
|
+
estimatedCostMs: 1.7,
|
|
1847
|
+
maxDispatchesPerFrame: 2,
|
|
1848
|
+
maxJobsPerDispatch: 128,
|
|
1849
|
+
cadenceDivisor: 1,
|
|
1850
|
+
workgroupScale: 1,
|
|
1851
|
+
maxQueueDepth: 256
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
),
|
|
1855
|
+
suggestedAllocationIds: ["lighting.volumetrics.froxel-grid"]
|
|
1856
|
+
},
|
|
1857
|
+
volumetricShadow: {
|
|
1858
|
+
domain: "volumetrics",
|
|
1859
|
+
importance: "high",
|
|
1860
|
+
levels: buildWorkerBudgetLevels(
|
|
1861
|
+
"lighting.volumetrics.volumetricShadow",
|
|
1862
|
+
lightingWorkerQueueClass,
|
|
1863
|
+
{
|
|
1864
|
+
low: {
|
|
1865
|
+
estimatedCostMs: 0.5,
|
|
1866
|
+
maxDispatchesPerFrame: 1,
|
|
1867
|
+
maxJobsPerDispatch: 24,
|
|
1868
|
+
cadenceDivisor: 2,
|
|
1869
|
+
workgroupScale: 0.5,
|
|
1870
|
+
maxQueueDepth: 64
|
|
1871
|
+
},
|
|
1872
|
+
medium: {
|
|
1873
|
+
estimatedCostMs: 0.9,
|
|
1874
|
+
maxDispatchesPerFrame: 1,
|
|
1875
|
+
maxJobsPerDispatch: 48,
|
|
1876
|
+
cadenceDivisor: 1,
|
|
1877
|
+
workgroupScale: 0.75,
|
|
1878
|
+
maxQueueDepth: 128
|
|
1879
|
+
},
|
|
1880
|
+
high: {
|
|
1881
|
+
estimatedCostMs: 1.3,
|
|
1882
|
+
maxDispatchesPerFrame: 1,
|
|
1883
|
+
maxJobsPerDispatch: 96,
|
|
1884
|
+
cadenceDivisor: 1,
|
|
1885
|
+
workgroupScale: 1,
|
|
1886
|
+
maxQueueDepth: 192
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
),
|
|
1890
|
+
suggestedAllocationIds: ["lighting.volumetrics.shadow-history"]
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
hdri: {
|
|
1895
|
+
suggestedAllocationIds: [
|
|
1896
|
+
"lighting.hdri.cubemap",
|
|
1897
|
+
"lighting.hdri.prefilter",
|
|
1898
|
+
"lighting.hdri.brdf-lut"
|
|
1899
|
+
],
|
|
1900
|
+
jobs: {
|
|
1901
|
+
irradianceConvolution: {
|
|
1902
|
+
domain: "lighting",
|
|
1903
|
+
importance: "medium",
|
|
1904
|
+
levels: buildWorkerBudgetLevels(
|
|
1905
|
+
"lighting.hdri.irradianceConvolution",
|
|
1906
|
+
lightingWorkerQueueClass,
|
|
1907
|
+
{
|
|
1908
|
+
low: {
|
|
1909
|
+
estimatedCostMs: 0.3,
|
|
1910
|
+
maxDispatchesPerFrame: 1,
|
|
1911
|
+
maxJobsPerDispatch: 8,
|
|
1912
|
+
cadenceDivisor: 3,
|
|
1913
|
+
workgroupScale: 0.5,
|
|
1914
|
+
maxQueueDepth: 16
|
|
1915
|
+
},
|
|
1916
|
+
medium: {
|
|
1917
|
+
estimatedCostMs: 0.5,
|
|
1918
|
+
maxDispatchesPerFrame: 1,
|
|
1919
|
+
maxJobsPerDispatch: 16,
|
|
1920
|
+
cadenceDivisor: 2,
|
|
1921
|
+
workgroupScale: 0.75,
|
|
1922
|
+
maxQueueDepth: 32
|
|
1923
|
+
},
|
|
1924
|
+
high: {
|
|
1925
|
+
estimatedCostMs: 0.8,
|
|
1926
|
+
maxDispatchesPerFrame: 1,
|
|
1927
|
+
maxJobsPerDispatch: 32,
|
|
1928
|
+
cadenceDivisor: 1,
|
|
1929
|
+
workgroupScale: 1,
|
|
1930
|
+
maxQueueDepth: 48
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
),
|
|
1934
|
+
suggestedAllocationIds: ["lighting.hdri.cubemap"]
|
|
1935
|
+
},
|
|
1936
|
+
specularPrefilter: {
|
|
1937
|
+
domain: "lighting",
|
|
1938
|
+
importance: "medium",
|
|
1939
|
+
levels: buildWorkerBudgetLevels(
|
|
1940
|
+
"lighting.hdri.specularPrefilter",
|
|
1941
|
+
lightingWorkerQueueClass,
|
|
1942
|
+
{
|
|
1943
|
+
low: {
|
|
1944
|
+
estimatedCostMs: 0.4,
|
|
1945
|
+
maxDispatchesPerFrame: 1,
|
|
1946
|
+
maxJobsPerDispatch: 8,
|
|
1947
|
+
cadenceDivisor: 3,
|
|
1948
|
+
workgroupScale: 0.5,
|
|
1949
|
+
maxQueueDepth: 16
|
|
1950
|
+
},
|
|
1951
|
+
medium: {
|
|
1952
|
+
estimatedCostMs: 0.7,
|
|
1953
|
+
maxDispatchesPerFrame: 1,
|
|
1954
|
+
maxJobsPerDispatch: 16,
|
|
1955
|
+
cadenceDivisor: 2,
|
|
1956
|
+
workgroupScale: 0.75,
|
|
1957
|
+
maxQueueDepth: 32
|
|
1958
|
+
},
|
|
1959
|
+
high: {
|
|
1960
|
+
estimatedCostMs: 1,
|
|
1961
|
+
maxDispatchesPerFrame: 1,
|
|
1962
|
+
maxJobsPerDispatch: 32,
|
|
1963
|
+
cadenceDivisor: 1,
|
|
1964
|
+
workgroupScale: 1,
|
|
1965
|
+
maxQueueDepth: 48
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
),
|
|
1969
|
+
suggestedAllocationIds: ["lighting.hdri.prefilter"]
|
|
1970
|
+
},
|
|
1971
|
+
brdfLut: {
|
|
1972
|
+
domain: "lighting",
|
|
1973
|
+
importance: "low",
|
|
1974
|
+
levels: buildWorkerBudgetLevels(
|
|
1975
|
+
"lighting.hdri.brdfLut",
|
|
1976
|
+
lightingWorkerQueueClass,
|
|
1977
|
+
{
|
|
1978
|
+
low: {
|
|
1979
|
+
estimatedCostMs: 0.2,
|
|
1980
|
+
maxDispatchesPerFrame: 1,
|
|
1981
|
+
maxJobsPerDispatch: 4,
|
|
1982
|
+
cadenceDivisor: 3,
|
|
1983
|
+
workgroupScale: 0.5,
|
|
1984
|
+
maxQueueDepth: 8
|
|
1985
|
+
},
|
|
1986
|
+
medium: {
|
|
1987
|
+
estimatedCostMs: 0.4,
|
|
1988
|
+
maxDispatchesPerFrame: 1,
|
|
1989
|
+
maxJobsPerDispatch: 8,
|
|
1990
|
+
cadenceDivisor: 2,
|
|
1991
|
+
workgroupScale: 0.75,
|
|
1992
|
+
maxQueueDepth: 16
|
|
1993
|
+
},
|
|
1994
|
+
high: {
|
|
1995
|
+
estimatedCostMs: 0.6,
|
|
1996
|
+
maxDispatchesPerFrame: 1,
|
|
1997
|
+
maxJobsPerDispatch: 16,
|
|
1998
|
+
cadenceDivisor: 1,
|
|
1999
|
+
workgroupScale: 1,
|
|
2000
|
+
maxQueueDepth: 24
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
),
|
|
2004
|
+
suggestedAllocationIds: ["lighting.hdri.brdf-lut"]
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
lightingWorkerDagSpecs = {
|
|
2010
|
+
hybrid: {
|
|
2011
|
+
directLighting: { priority: 4, dependencies: [] },
|
|
2012
|
+
screenTrace: { priority: 3, dependencies: [] },
|
|
2013
|
+
radianceCache: { priority: 4, dependencies: ["directLighting"] },
|
|
2014
|
+
finalGather: { priority: 2, dependencies: ["radianceCache", "screenTrace"] },
|
|
2015
|
+
reflectionResolve: {
|
|
2016
|
+
priority: 1,
|
|
2017
|
+
dependencies: ["screenTrace", "finalGather"]
|
|
2018
|
+
}
|
|
2019
|
+
},
|
|
2020
|
+
pathtracer: {
|
|
2021
|
+
pathTrace: { priority: 4, dependencies: [] },
|
|
2022
|
+
accumulate: { priority: 3, dependencies: ["pathTrace"] },
|
|
2023
|
+
denoise: { priority: 2, dependencies: ["accumulate"] }
|
|
2024
|
+
},
|
|
2025
|
+
volumetrics: {
|
|
2026
|
+
volumetricShadow: { priority: 3, dependencies: [] },
|
|
2027
|
+
froxelIntegrate: { priority: 2, dependencies: ["volumetricShadow"] }
|
|
2028
|
+
},
|
|
2029
|
+
hdri: {
|
|
2030
|
+
irradianceConvolution: { priority: 3, dependencies: [] },
|
|
2031
|
+
specularPrefilter: { priority: 3, dependencies: [] },
|
|
2032
|
+
brdfLut: {
|
|
2033
|
+
priority: 2,
|
|
2034
|
+
dependencies: ["irradianceConvolution", "specularPrefilter"]
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
lightingWorkerManifests = Object.freeze(
|
|
2039
|
+
Object.fromEntries(
|
|
2040
|
+
Object.entries(lightingTechniques).map(([name, technique]) => [
|
|
2041
|
+
name,
|
|
2042
|
+
buildLightingWorkerManifest(name, technique)
|
|
2043
|
+
])
|
|
2044
|
+
)
|
|
2045
|
+
);
|
|
2046
|
+
defaultTechnique = getLightingTechnique(defaultLightingTechnique);
|
|
2047
|
+
lightingPreludeWgslUrl = defaultTechnique.preludeUrl;
|
|
2048
|
+
lightingJobLabels = Object.freeze(
|
|
2049
|
+
Object.fromEntries(defaultTechnique.jobs.map((job) => [job.key, job.label]))
|
|
2050
|
+
);
|
|
2051
|
+
lightingJobs = defaultTechnique.jobs.map((job) => ({
|
|
2052
|
+
label: job.label,
|
|
2053
|
+
url: job.url,
|
|
2054
|
+
sourceName: job.sourceName
|
|
2055
|
+
}));
|
|
2056
|
+
}
|
|
2057
|
+
});
|
|
2058
|
+
|
|
620
2059
|
// src/product-studio-runtime.js
|
|
621
2060
|
var product_studio_runtime_exports = {};
|
|
622
2061
|
__export(product_studio_runtime_exports, {
|
|
@@ -931,7 +2370,7 @@ async function resolveWavefrontLightingOptions(options) {
|
|
|
931
2370
|
environmentColor: [0.35, 0.43, 0.49, 1],
|
|
932
2371
|
ambientColor: [0.02, 0.024, 0.028, 1]
|
|
933
2372
|
};
|
|
934
|
-
const lightingLoader = typeof options.__lightingLoader === "function" ? options.__lightingLoader : () =>
|
|
2373
|
+
const lightingLoader = typeof options.__lightingLoader === "function" ? options.__lightingLoader : () => Promise.resolve().then(() => (init_dist(), dist_exports)).catch(() => null);
|
|
935
2374
|
const lightingModule = await lightingLoader();
|
|
936
2375
|
if (typeof lightingModule?.createWavefrontEnvironmentLightingOptions !== "function") {
|
|
937
2376
|
return fallback;
|
|
@@ -999,6 +2438,7 @@ async function mountGpuProductStudio(options = {}, featureFlags = null) {
|
|
|
999
2438
|
return Object.freeze({
|
|
1000
2439
|
state,
|
|
1001
2440
|
model,
|
|
2441
|
+
productModel: model,
|
|
1002
2442
|
canvas,
|
|
1003
2443
|
renderer,
|
|
1004
2444
|
meshes,
|
|
@@ -4824,10 +6264,10 @@ __export(index_exports, {
|
|
|
4824
6264
|
translateGpuSharedText: () => translateGpuSharedText
|
|
4825
6265
|
});
|
|
4826
6266
|
module.exports = __toCommonJS(index_exports);
|
|
6267
|
+
init_feature_flags();
|
|
4827
6268
|
init_asset_url();
|
|
4828
6269
|
init_i18n();
|
|
4829
6270
|
init_en_GB();
|
|
4830
|
-
init_feature_flags();
|
|
4831
6271
|
init_product_studio_runtime();
|
|
4832
6272
|
var showcaseFocusModes2 = Object.freeze([
|
|
4833
6273
|
"integrated",
|
|
@@ -4843,9 +6283,32 @@ async function loadGltfModel2(url) {
|
|
|
4843
6283
|
const module2 = await Promise.resolve().then(() => (init_gltf_loader(), gltf_loader_exports));
|
|
4844
6284
|
return module2.loadGltfModel(url);
|
|
4845
6285
|
}
|
|
6286
|
+
function isProductStudioFeatureEnabled(featureFlags) {
|
|
6287
|
+
if (typeof featureFlags?.get === "function") {
|
|
6288
|
+
return featureFlags.get(GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE) === true;
|
|
6289
|
+
}
|
|
6290
|
+
const direct = featureFlags?.[GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE];
|
|
6291
|
+
if (typeof direct === "boolean") {
|
|
6292
|
+
return direct;
|
|
6293
|
+
}
|
|
6294
|
+
const flagsValue = featureFlags?.flags?.[GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE];
|
|
6295
|
+
if (typeof flagsValue === "boolean") {
|
|
6296
|
+
return flagsValue;
|
|
6297
|
+
}
|
|
6298
|
+
const enabledValue = featureFlags?.enabled?.[GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE];
|
|
6299
|
+
if (typeof enabledValue === "boolean") {
|
|
6300
|
+
return enabledValue;
|
|
6301
|
+
}
|
|
6302
|
+
return false;
|
|
6303
|
+
}
|
|
4846
6304
|
async function mountGpuShowcase2(options = {}) {
|
|
4847
6305
|
const demoMode = options.demoMode ?? options.mode;
|
|
4848
6306
|
if (demoMode === "product-studio" || demoMode === "product" || demoMode === "studio" || demoMode === "eames") {
|
|
6307
|
+
if (!isProductStudioFeatureEnabled(options.__featureFlags)) {
|
|
6308
|
+
throw new Error(
|
|
6309
|
+
`${GPU_SHOWCASE_PRODUCT_STUDIO_FEATURE} must be enabled before Product Studio can mount.`
|
|
6310
|
+
);
|
|
6311
|
+
}
|
|
4849
6312
|
const productRuntimeLoader = typeof options.__productRuntimeLoader === "function" ? options.__productRuntimeLoader : () => Promise.resolve().then(() => (init_product_studio_runtime(), product_studio_runtime_exports));
|
|
4850
6313
|
const productModule = await productRuntimeLoader();
|
|
4851
6314
|
if (typeof productModule.mountGpuProductStudio !== "function") {
|