@plasius/gpu-lighting 0.1.19 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -123,10 +123,45 @@ var lightingProfileModeOrder = Object.freeze([
123
123
  "hybrid",
124
124
  "reference"
125
125
  ]);
126
- var lightingEnvironmentPresetNames = Object.freeze([
127
- "moonlit-harbor",
128
- "product-studio",
129
- "neutral-studio"
126
+ var lightingEnvironmentTimeOfDayNames = Object.freeze([
127
+ "dawn",
128
+ "midday",
129
+ "dusk",
130
+ "night"
131
+ ]);
132
+ var lightingEnvironmentSceneNames = Object.freeze([
133
+ "studio",
134
+ "harbor",
135
+ "grass-field",
136
+ "forest",
137
+ "warehouse",
138
+ "cavern"
139
+ ]);
140
+ var lightingEnvironmentLightSourceKinds = Object.freeze([
141
+ "sky",
142
+ "sun",
143
+ "moon",
144
+ "stars",
145
+ "horizon-glow",
146
+ "ground-bounce",
147
+ "studio-softbox",
148
+ "canopy-transmission",
149
+ "window-portal",
150
+ "fluorescent-strip",
151
+ "sodium-door",
152
+ "emergency-beacon",
153
+ "cave-mouth",
154
+ "torch",
155
+ "bioluminescence",
156
+ "lava-fissure",
157
+ "crystal",
158
+ "custom"
159
+ ]);
160
+ var lightingEnvironmentPortalShapes = Object.freeze(["rectangle"]);
161
+ var lightingEnvironmentPortalModes = Object.freeze([
162
+ "disabled",
163
+ "guide",
164
+ "guide-and-gate"
130
165
  ]);
131
166
  var defaultAdaptiveLightingProfilePolicy = Object.freeze({
132
167
  preferredProfile: "reference",
@@ -141,9 +176,37 @@ var lightingDistanceBands = Object.freeze([
141
176
  ]);
142
177
  var lightingWorkerQueueClass = "lighting";
143
178
  var lightingDebugOwner = "lighting";
179
+ var environmentPresetAmbientScales = Object.freeze({
180
+ "grass-field": 0.78,
181
+ forest: 0.78,
182
+ warehouse: 0.82,
183
+ cavern: 0.78
184
+ });
185
+ var environmentSunlitBaselineByTimeOfDay = Object.freeze({
186
+ dawn: 0.18,
187
+ midday: 0.28,
188
+ dusk: 0.14,
189
+ night: 0.035
190
+ });
191
+ var environmentSunlitBaselineSceneScales = Object.freeze({
192
+ "grass-field": 1,
193
+ forest: 0.78,
194
+ warehouse: 0.62,
195
+ cavern: 0.42,
196
+ harbor: 0.85,
197
+ studio: 0.58
198
+ });
144
199
  function freezeVec4(value) {
145
200
  return Object.freeze([value[0], value[1], value[2], value[3] ?? 1]);
146
201
  }
202
+ function scaleVec4(value, scale) {
203
+ return [
204
+ value[0] * scale,
205
+ value[1] * scale,
206
+ value[2] * scale,
207
+ value[3] ?? 1
208
+ ];
209
+ }
147
210
  function normalizeVector3(value, fallback) {
148
211
  if (!Array.isArray(value) || value.length < 3) {
149
212
  return [...fallback];
@@ -170,12 +233,290 @@ function readColor(value, fallback) {
170
233
  Number.isFinite(value[3]) ? Math.max(0, Math.min(1, value[3])) : fallback[3] ?? 1
171
234
  ]);
172
235
  }
236
+ function colorLuminance(value) {
237
+ return value[0] * 0.2126 + value[1] * 0.7152 + value[2] * 0.0722;
238
+ }
239
+ function readPositiveColor(value, fallback) {
240
+ const color = readColor(value, fallback);
241
+ const fallbackColor = readColor(fallback, [1, 1, 1, 1]);
242
+ return freezeVec4([
243
+ color[0] > 0 ? color[0] : Math.max(fallbackColor[0], 1e-4),
244
+ color[1] > 0 ? color[1] : Math.max(fallbackColor[1], 1e-4),
245
+ color[2] > 0 ? color[2] : Math.max(fallbackColor[2], 1e-4),
246
+ color[3]
247
+ ]);
248
+ }
249
+ function ensureNonNullColor(value, fallback = [1, 1, 1, 1]) {
250
+ const color = readColor(value, fallback);
251
+ if (colorLuminance(color) > 1e-6) {
252
+ return color;
253
+ }
254
+ return readPositiveColor(fallback, [1, 1, 1, 1]);
255
+ }
173
256
  function readFinite(value, fallback) {
174
257
  return Number.isFinite(value) ? value : fallback;
175
258
  }
259
+ function readVector3(value, fallback) {
260
+ if (!Array.isArray(value) || value.length < 3) {
261
+ return [...fallback];
262
+ }
263
+ return [
264
+ Number.isFinite(value[0]) ? value[0] : fallback[0],
265
+ Number.isFinite(value[1]) ? value[1] : fallback[1],
266
+ Number.isFinite(value[2]) ? value[2] : fallback[2]
267
+ ];
268
+ }
269
+ function dot3(a, b) {
270
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
271
+ }
272
+ function cross3(a, b) {
273
+ return [
274
+ a[1] * b[2] - a[2] * b[1],
275
+ a[2] * b[0] - a[0] * b[2],
276
+ a[0] * b[1] - a[1] * b[0]
277
+ ];
278
+ }
279
+ function normalizeRawVector3(value, fallback) {
280
+ const length = Math.hypot(value[0], value[1], value[2]);
281
+ if (!Number.isFinite(length) || length <= 1e-6) {
282
+ return [...fallback];
283
+ }
284
+ return value.map((component) => component / length);
285
+ }
286
+ function orthogonalFallback(normal) {
287
+ if (Math.abs(normal[1]) < 0.92) {
288
+ return normalizeRawVector3(cross3([0, 1, 0], normal), [1, 0, 0]);
289
+ }
290
+ return normalizeRawVector3(cross3([1, 0, 0], normal), [0, 0, 1]);
291
+ }
292
+ function normalizePortalTangent(value, normal) {
293
+ const raw = normalizeVector3(value, orthogonalFallback(normal));
294
+ const projected = [
295
+ raw[0] - normal[0] * dot3(raw, normal),
296
+ raw[1] - normal[1] * dot3(raw, normal),
297
+ raw[2] - normal[2] * dot3(raw, normal)
298
+ ];
299
+ return normalizeRawVector3(projected, orthogonalFallback(normal));
300
+ }
301
+ function readPositiveFinite(value, fallback) {
302
+ const number = Number(value ?? fallback);
303
+ if (!Number.isFinite(number)) {
304
+ return fallback;
305
+ }
306
+ return Math.max(number, 1e-4);
307
+ }
308
+ function normalizeEnvironmentPortalMode(value, hasPortals) {
309
+ if (value == null) {
310
+ return hasPortals ? "guide-and-gate" : "disabled";
311
+ }
312
+ if (value === "gate") {
313
+ return "guide-and-gate";
314
+ }
315
+ if (lightingEnvironmentPortalModes.includes(value)) {
316
+ return value;
317
+ }
318
+ throw new Error(
319
+ `environmentPortalMode must be one of: ${lightingEnvironmentPortalModes.join(", ")}.`
320
+ );
321
+ }
322
+ function normalizeEnvironmentPortal(portal, index) {
323
+ if (!portal || typeof portal !== "object") {
324
+ throw new Error(`environmentPortals[${index}] must be an object.`);
325
+ }
326
+ const shape = portal.shape ?? portal.kind ?? "rectangle";
327
+ if (!lightingEnvironmentPortalShapes.includes(shape)) {
328
+ throw new Error(
329
+ `environmentPortals[${index}].shape must be one of: ${lightingEnvironmentPortalShapes.join(", ")}.`
330
+ );
331
+ }
332
+ const normal = Object.freeze(
333
+ normalizeVector3(portal.normal, [0, 0, 1])
334
+ );
335
+ const tangent = Object.freeze(normalizePortalTangent(portal.tangent, normal));
336
+ const bitangent = Object.freeze(
337
+ normalizeRawVector3(cross3(normal, tangent), [0, 1, 0])
338
+ );
339
+ const width = readPositiveFinite(
340
+ portal.width,
341
+ readPositiveFinite(portal.halfWidth, 0.5) * 2
342
+ );
343
+ const height = readPositiveFinite(
344
+ portal.height,
345
+ readPositiveFinite(portal.halfHeight, 0.5) * 2
346
+ );
347
+ const radianceScale = Math.max(
348
+ 0,
349
+ readFinite(portal.radianceScale ?? portal.intensity, 1)
350
+ );
351
+ return Object.freeze({
352
+ id: typeof portal.id === "string" && portal.id.length > 0 ? portal.id : `environment-portal-${index}`,
353
+ shape,
354
+ position: Object.freeze(readVector3(portal.position ?? portal.center, [0, 0, 0])),
355
+ normal,
356
+ tangent,
357
+ bitangent,
358
+ width,
359
+ height,
360
+ radianceScale,
361
+ color: readColor(portal.color, [1, 1, 1, 1]),
362
+ twoSided: portal.twoSided !== false
363
+ });
364
+ }
365
+ function normalizeEnvironmentPortals(value) {
366
+ if (value == null) {
367
+ return Object.freeze([]);
368
+ }
369
+ if (!Array.isArray(value)) {
370
+ throw new Error("environmentPortals must be an array when provided.");
371
+ }
372
+ return Object.freeze(value.map(normalizeEnvironmentPortal));
373
+ }
374
+ function normalizeEnvironmentMap(value) {
375
+ if (value == null) {
376
+ return null;
377
+ }
378
+ if (!value || typeof value !== "object") {
379
+ throw new Error("environmentMap must be an object when provided.");
380
+ }
381
+ return Object.freeze({
382
+ ...value,
383
+ id: typeof value.id === "string" && value.id.length > 0 ? value.id : "environment-map",
384
+ projection: typeof value.projection === "string" && value.projection.length > 0 ? value.projection : "equirectangular",
385
+ intensity: readPositiveFinite(value.intensity ?? value.radianceScale, 1),
386
+ rotationRadians: readFinite(value.rotationRadians ?? value.rotation, 0),
387
+ ambientStrength: Math.max(0, readFinite(value.ambientStrength, 0.32))
388
+ });
389
+ }
390
+ function freezeLightSourceSpec(source) {
391
+ return Object.freeze({
392
+ ...source,
393
+ color: source.color ? freezeVec4(source.color) : void 0,
394
+ direction: source.direction ? Object.freeze(normalizeVector3(source.direction, [0, 1, 0])) : void 0,
395
+ position: source.position ? Object.freeze(readVector3(source.position, [0, 0, 0])) : void 0
396
+ });
397
+ }
398
+ function defineEnvironmentPreset(spec) {
399
+ const scene = spec.scene ?? "studio";
400
+ const timeOfDay = spec.timeOfDay ?? "midday";
401
+ const ambientScale = Math.max(
402
+ 0,
403
+ readFinite(spec.ambientScale, environmentPresetAmbientScales[scene] ?? 1)
404
+ );
405
+ const defaultSunlitBaseline = (environmentSunlitBaselineByTimeOfDay[timeOfDay] ?? environmentSunlitBaselineByTimeOfDay.midday) * (environmentSunlitBaselineSceneScales[scene] ?? 0.58);
406
+ const sunlitBaseline = Math.max(
407
+ 0,
408
+ readFinite(spec.sunlitBaseline, defaultSunlitBaseline)
409
+ );
410
+ return Object.freeze({
411
+ ...spec,
412
+ scene,
413
+ timeOfDay,
414
+ horizonColor: freezeVec4(spec.horizonColor),
415
+ zenithColor: freezeVec4(spec.zenithColor),
416
+ sunDirection: Object.freeze(normalizeVector3(spec.sunDirection, [0, 1, 0])),
417
+ sunColor: freezeVec4(spec.sunColor),
418
+ ambientColor: freezeVec4(scaleVec4(spec.ambientColor, ambientScale)),
419
+ sunlitBaseline,
420
+ environmentLightSources: Object.freeze(
421
+ (spec.environmentLightSources ?? []).map(freezeLightSourceSpec)
422
+ )
423
+ });
424
+ }
425
+ function buildEnvironmentLightSourceFallback(config, preset) {
426
+ const firstPresetSource = preset.environmentLightSources[0] ?? {};
427
+ return {
428
+ kind: firstPresetSource.kind ?? "sky",
429
+ role: firstPresetSource.role ?? "fill",
430
+ color: firstPresetSource.color ?? config.sunColor,
431
+ intensity: firstPresetSource.intensity ?? Math.max(config.environmentIntensity, 1e-4),
432
+ direction: firstPresetSource.direction ?? config.sunDirection,
433
+ angularRadiusRadians: firstPresetSource.angularRadiusRadians ?? 0.25,
434
+ reach: firstPresetSource.reach ?? 1e3
435
+ };
436
+ }
437
+ function normalizeEnvironmentLightSource(source, index, fallback) {
438
+ if (!source || typeof source !== "object") {
439
+ throw new Error(`environmentLightSources[${index}] must be an object.`);
440
+ }
441
+ const requestedKind = source.kind ?? source.type ?? fallback.kind ?? "custom";
442
+ const kind = lightingEnvironmentLightSourceKinds.includes(requestedKind) ? requestedKind : "custom";
443
+ const color = readPositiveColor(source.color, fallback.color ?? [1, 1, 1, 1]);
444
+ const intensity = readPositiveFinite(
445
+ source.intensity ?? source.radianceScale,
446
+ fallback.intensity ?? 1
447
+ );
448
+ const radiance = freezeVec4([
449
+ color[0] * intensity,
450
+ color[1] * intensity,
451
+ color[2] * intensity,
452
+ color[3]
453
+ ]);
454
+ return Object.freeze({
455
+ id: typeof source.id === "string" && source.id.length > 0 ? source.id : `environment-light-source-${index}`,
456
+ kind,
457
+ type: kind,
458
+ role: typeof source.role === "string" && source.role.length > 0 ? source.role : fallback.role ?? "fill",
459
+ direction: Object.freeze(
460
+ normalizeVector3(source.direction, fallback.direction ?? [0, 1, 0])
461
+ ),
462
+ position: Object.freeze(
463
+ readVector3(source.position ?? source.origin, fallback.position ?? [0, 0, 0])
464
+ ),
465
+ color,
466
+ intensity,
467
+ radiance,
468
+ luminance: colorLuminance(radiance),
469
+ angularRadiusRadians: readPositiveFinite(
470
+ source.angularRadiusRadians ?? source.angularRadius,
471
+ fallback.angularRadiusRadians ?? 0.25
472
+ ),
473
+ reach: readPositiveFinite(
474
+ source.reach ?? source.distance,
475
+ fallback.reach ?? 1e3
476
+ ),
477
+ castsShadows: source.castsShadows !== false,
478
+ contributesToEnvironment: source.contributesToEnvironment !== false
479
+ });
480
+ }
481
+ function normalizeEnvironmentLightSources(value, preset, config) {
482
+ const baseSources = value ?? preset.environmentLightSources;
483
+ const fallback = buildEnvironmentLightSourceFallback(config, preset);
484
+ if (!Array.isArray(baseSources)) {
485
+ throw new Error("environmentLightSources must be an array when provided.");
486
+ }
487
+ const normalizedSources = baseSources.length > 0 ? baseSources.map(
488
+ (source, index) => normalizeEnvironmentLightSource(source, index, fallback)
489
+ ) : [normalizeEnvironmentLightSource(fallback, 0, fallback)];
490
+ return Object.freeze(normalizedSources);
491
+ }
492
+ function findDominantEnvironmentLightSource(sources) {
493
+ return sources.reduce(
494
+ (dominant, source) => source.luminance > dominant.luminance ? source : dominant
495
+ );
496
+ }
497
+ function createEnvironmentMissLighting(source, environmentColor) {
498
+ const fallbackRadiance = readPositiveColor(environmentColor, source.radiance);
499
+ const radiance = ensureNonNullColor(source.radiance, fallbackRadiance);
500
+ const color = readPositiveColor(source.color, environmentColor);
501
+ return Object.freeze({
502
+ sourceId: source.id,
503
+ kind: source.kind,
504
+ role: source.role,
505
+ contribution: "inferred-environment",
506
+ startingPoint: "environment-miss",
507
+ direction: source.direction,
508
+ position: source.position,
509
+ color,
510
+ intensity: Math.max(source.intensity, 1e-4),
511
+ radiance,
512
+ luminance: Math.max(colorLuminance(radiance), 1e-4)
513
+ });
514
+ }
176
515
  var environmentLightingPresets = Object.freeze({
177
- "moonlit-harbor": Object.freeze({
516
+ "moonlit-harbor": defineEnvironmentPreset({
178
517
  preset: "moonlit-harbor",
518
+ scene: "harbor",
519
+ timeOfDay: "night",
179
520
  environmentMode: 0,
180
521
  environmentIntensity: 0.86,
181
522
  exposure: 1,
@@ -183,10 +524,31 @@ var environmentLightingPresets = Object.freeze({
183
524
  zenithColor: freezeVec4([0.035, 0.07, 0.14, 1]),
184
525
  sunDirection: Object.freeze(normalizeVector3([0.22, 0.88, 0.42], [0, 1, 0])),
185
526
  sunColor: freezeVec4([2.1, 2.25, 2.65, 1]),
186
- ambientColor: freezeVec4([0.018, 0.023, 0.03, 1])
527
+ ambientColor: freezeVec4([0.018, 0.023, 0.03, 1]),
528
+ environmentLightSources: [
529
+ {
530
+ id: "harbor-moon",
531
+ kind: "moon",
532
+ role: "key",
533
+ direction: [0.22, 0.88, 0.42],
534
+ color: [0.7, 0.76, 0.9, 1],
535
+ intensity: 2.2,
536
+ angularRadiusRadians: 0.018
537
+ },
538
+ {
539
+ id: "harbor-sky",
540
+ kind: "sky",
541
+ role: "fill",
542
+ direction: [0, 1, 0],
543
+ color: [0.22, 0.31, 0.48, 1],
544
+ intensity: 0.35
545
+ }
546
+ ]
187
547
  }),
188
- "product-studio": Object.freeze({
548
+ "product-studio": defineEnvironmentPreset({
189
549
  preset: "product-studio",
550
+ scene: "studio",
551
+ timeOfDay: "midday",
190
552
  environmentMode: 1,
191
553
  environmentIntensity: 1.05,
192
554
  exposure: 1,
@@ -194,10 +556,32 @@ var environmentLightingPresets = Object.freeze({
194
556
  zenithColor: freezeVec4([0.18, 0.22, 0.26, 1]),
195
557
  sunDirection: Object.freeze(normalizeVector3([0.18, 0.93, 0.24], [0, 1, 0])),
196
558
  sunColor: freezeVec4([3.8, 3.55, 2.85, 1]),
197
- ambientColor: freezeVec4([0.024, 0.027, 0.03, 1])
559
+ ambientColor: freezeVec4([0.024, 0.027, 0.03, 1]),
560
+ environmentLightSources: [
561
+ {
562
+ id: "studio-key-softbox",
563
+ kind: "studio-softbox",
564
+ role: "key",
565
+ direction: [0.18, 0.93, 0.24],
566
+ color: [1, 0.94, 0.82, 1],
567
+ intensity: 4.1,
568
+ angularRadiusRadians: 0.42
569
+ },
570
+ {
571
+ id: "studio-fill-panel",
572
+ kind: "studio-softbox",
573
+ role: "fill",
574
+ direction: [-0.56, 0.62, -0.2],
575
+ color: [0.75, 0.84, 1, 1],
576
+ intensity: 1.3,
577
+ angularRadiusRadians: 0.55
578
+ }
579
+ ]
198
580
  }),
199
- "neutral-studio": Object.freeze({
581
+ "neutral-studio": defineEnvironmentPreset({
200
582
  preset: "neutral-studio",
583
+ scene: "studio",
584
+ timeOfDay: "midday",
201
585
  environmentMode: 2,
202
586
  environmentIntensity: 0.95,
203
587
  exposure: 1,
@@ -205,13 +589,335 @@ var environmentLightingPresets = Object.freeze({
205
589
  zenithColor: freezeVec4([0.24, 0.26, 0.29, 1]),
206
590
  sunDirection: Object.freeze(normalizeVector3([-0.24, 0.86, 0.36], [0, 1, 0])),
207
591
  sunColor: freezeVec4([2.4, 2.35, 2.2, 1]),
208
- ambientColor: freezeVec4([0.028, 0.029, 0.03, 1])
592
+ ambientColor: freezeVec4([0.028, 0.029, 0.03, 1]),
593
+ environmentLightSources: [
594
+ {
595
+ id: "neutral-studio-overhead",
596
+ kind: "studio-softbox",
597
+ role: "key",
598
+ direction: [-0.24, 0.86, 0.36],
599
+ color: [0.96, 0.97, 1, 1],
600
+ intensity: 2.5,
601
+ angularRadiusRadians: 0.5
602
+ },
603
+ {
604
+ id: "neutral-studio-wall-bounce",
605
+ kind: "ground-bounce",
606
+ role: "fill",
607
+ direction: [0.2, 0.3, -0.9],
608
+ color: [0.55, 0.58, 0.62, 1],
609
+ intensity: 0.8
610
+ }
611
+ ]
612
+ }),
613
+ "grass-field-dawn": defineEnvironmentPreset({
614
+ preset: "grass-field-dawn",
615
+ scene: "grass-field",
616
+ timeOfDay: "dawn",
617
+ environmentMode: 3,
618
+ environmentIntensity: 0.92,
619
+ exposure: 1.06,
620
+ horizonColor: [0.92, 0.54, 0.32, 1],
621
+ zenithColor: [0.16, 0.28, 0.5, 1],
622
+ sunDirection: [0.64, 0.32, 0.18],
623
+ sunColor: [5.6, 3.15, 1.55, 1],
624
+ ambientColor: [0.034, 0.047, 0.032, 1],
625
+ environmentLightSources: [
626
+ { id: "field-dawn-sun", kind: "sun", role: "key", direction: [0.64, 0.32, 0.18], color: [1, 0.58, 0.28, 1], intensity: 5.6, angularRadiusRadians: 0.012 },
627
+ { id: "field-dawn-sky", kind: "sky", role: "fill", direction: [0, 1, 0], color: [0.36, 0.52, 0.82, 1], intensity: 0.9 },
628
+ { id: "field-dawn-grass-bounce", kind: "ground-bounce", role: "bounce", direction: [0, 0.25, 0.1], color: [0.22, 0.44, 0.12, 1], intensity: 0.45 }
629
+ ]
630
+ }),
631
+ "grass-field-midday": defineEnvironmentPreset({
632
+ preset: "grass-field-midday",
633
+ scene: "grass-field",
634
+ timeOfDay: "midday",
635
+ environmentMode: 4,
636
+ environmentIntensity: 1.18,
637
+ exposure: 0.96,
638
+ horizonColor: [0.58, 0.78, 0.96, 1],
639
+ zenithColor: [0.1, 0.34, 0.82, 1],
640
+ sunDirection: [0.18, 0.98, 0.08],
641
+ sunColor: [9.8, 9.4, 8.55, 1],
642
+ ambientColor: [0.048, 0.062, 0.04, 1],
643
+ environmentLightSources: [
644
+ { id: "field-midday-sun", kind: "sun", role: "key", direction: [0.18, 0.98, 0.08], color: [1, 0.96, 0.86, 1], intensity: 9.8, angularRadiusRadians: 93e-4 },
645
+ { id: "field-midday-sky", kind: "sky", role: "fill", direction: [0, 1, 0], color: [0.48, 0.7, 1, 1], intensity: 1.8 },
646
+ { id: "field-midday-ground", kind: "ground-bounce", role: "bounce", direction: [0, 0.35, -0.15], color: [0.28, 0.56, 0.16, 1], intensity: 0.65 }
647
+ ]
648
+ }),
649
+ "grass-field-dusk": defineEnvironmentPreset({
650
+ preset: "grass-field-dusk",
651
+ scene: "grass-field",
652
+ timeOfDay: "dusk",
653
+ environmentMode: 5,
654
+ environmentIntensity: 0.82,
655
+ exposure: 1.12,
656
+ horizonColor: [1.08, 0.42, 0.24, 1],
657
+ zenithColor: [0.09, 0.1, 0.32, 1],
658
+ sunDirection: [-0.76, 0.24, 0.22],
659
+ sunColor: [4.8, 1.65, 0.72, 1],
660
+ ambientColor: [0.026, 0.026, 0.034, 1],
661
+ environmentLightSources: [
662
+ { id: "field-dusk-sun", kind: "sun", role: "key", direction: [-0.76, 0.24, 0.22], color: [1, 0.34, 0.16, 1], intensity: 4.8, angularRadiusRadians: 0.014 },
663
+ { id: "field-dusk-horizon", kind: "horizon-glow", role: "fill", direction: [-0.9, 0.08, 0.1], color: [0.92, 0.28, 0.16, 1], intensity: 1.2 },
664
+ { id: "field-dusk-grass", kind: "ground-bounce", role: "bounce", direction: [0, 0.22, 0.2], color: [0.12, 0.28, 0.11, 1], intensity: 0.35 }
665
+ ]
666
+ }),
667
+ "grass-field-night": defineEnvironmentPreset({
668
+ preset: "grass-field-night",
669
+ scene: "grass-field",
670
+ timeOfDay: "night",
671
+ environmentMode: 6,
672
+ environmentIntensity: 0.48,
673
+ exposure: 1.35,
674
+ horizonColor: [0.08, 0.13, 0.2, 1],
675
+ zenithColor: [0.018, 0.035, 0.09, 1],
676
+ sunDirection: [-0.22, 0.86, -0.34],
677
+ sunColor: [0.72, 0.82, 1.35, 1],
678
+ ambientColor: [0.012, 0.017, 0.026, 1],
679
+ environmentLightSources: [
680
+ { id: "field-night-moon", kind: "moon", role: "key", direction: [-0.22, 0.86, -0.34], color: [0.52, 0.62, 1, 1], intensity: 1.25, angularRadiusRadians: 0.018 },
681
+ { id: "field-night-stars", kind: "stars", role: "fill", direction: [0, 1, 0], color: [0.32, 0.38, 0.6, 1], intensity: 0.24 },
682
+ { id: "field-night-horizon", kind: "horizon-glow", role: "rim", direction: [0.8, 0.08, -0.15], color: [0.08, 0.14, 0.26, 1], intensity: 0.28 }
683
+ ]
684
+ }),
685
+ "forest-dawn": defineEnvironmentPreset({
686
+ preset: "forest-dawn",
687
+ scene: "forest",
688
+ timeOfDay: "dawn",
689
+ environmentMode: 7,
690
+ environmentIntensity: 0.78,
691
+ exposure: 1.14,
692
+ horizonColor: [0.72, 0.48, 0.28, 1],
693
+ zenithColor: [0.08, 0.18, 0.18, 1],
694
+ sunDirection: [0.58, 0.42, -0.24],
695
+ sunColor: [4.4, 2.65, 1.32, 1],
696
+ ambientColor: [0.024, 0.04, 0.026, 1],
697
+ environmentLightSources: [
698
+ { id: "forest-dawn-sun-shaft", kind: "sun", role: "key", direction: [0.58, 0.42, -0.24], color: [1, 0.62, 0.32, 1], intensity: 4.4, angularRadiusRadians: 0.018 },
699
+ { id: "forest-dawn-canopy", kind: "canopy-transmission", role: "filter", direction: [0.12, 0.78, 0.2], color: [0.34, 0.68, 0.24, 1], intensity: 0.86 },
700
+ { id: "forest-dawn-sky-gap", kind: "sky", role: "fill", direction: [-0.18, 0.92, 0.12], color: [0.28, 0.46, 0.62, 1], intensity: 0.48 }
701
+ ]
702
+ }),
703
+ "forest-midday": defineEnvironmentPreset({
704
+ preset: "forest-midday",
705
+ scene: "forest",
706
+ timeOfDay: "midday",
707
+ environmentMode: 8,
708
+ environmentIntensity: 0.96,
709
+ exposure: 1.02,
710
+ horizonColor: [0.38, 0.62, 0.42, 1],
711
+ zenithColor: [0.08, 0.28, 0.32, 1],
712
+ sunDirection: [0.08, 0.96, -0.18],
713
+ sunColor: [7.2, 6.9, 5.25, 1],
714
+ ambientColor: [0.034, 0.055, 0.032, 1],
715
+ environmentLightSources: [
716
+ { id: "forest-midday-sun-gap", kind: "sun", role: "key", direction: [0.08, 0.96, -0.18], color: [1, 0.96, 0.74, 1], intensity: 7.2, angularRadiusRadians: 0.013 },
717
+ { id: "forest-midday-leaves", kind: "canopy-transmission", role: "filter", direction: [0.32, 0.75, 0.12], color: [0.24, 0.72, 0.28, 1], intensity: 1.35 },
718
+ { id: "forest-midday-floor", kind: "ground-bounce", role: "bounce", direction: [-0.1, 0.25, 0.18], color: [0.18, 0.35, 0.13, 1], intensity: 0.42 }
719
+ ]
720
+ }),
721
+ "forest-dusk": defineEnvironmentPreset({
722
+ preset: "forest-dusk",
723
+ scene: "forest",
724
+ timeOfDay: "dusk",
725
+ environmentMode: 9,
726
+ environmentIntensity: 0.68,
727
+ exposure: 1.2,
728
+ horizonColor: [0.72, 0.28, 0.2, 1],
729
+ zenithColor: [0.04, 0.07, 0.18, 1],
730
+ sunDirection: [-0.7, 0.28, -0.18],
731
+ sunColor: [3.2, 1.18, 0.56, 1],
732
+ ambientColor: [0.018, 0.026, 0.024, 1],
733
+ environmentLightSources: [
734
+ { id: "forest-dusk-horizon", kind: "horizon-glow", role: "key", direction: [-0.7, 0.18, -0.18], color: [1, 0.34, 0.2, 1], intensity: 2.2, angularRadiusRadians: 0.1 },
735
+ { id: "forest-dusk-canopy", kind: "canopy-transmission", role: "filter", direction: [0.18, 0.7, 0.26], color: [0.18, 0.38, 0.2, 1], intensity: 0.52 },
736
+ { id: "forest-dusk-sky-gap", kind: "sky", role: "fill", direction: [0, 1, 0], color: [0.12, 0.16, 0.34, 1], intensity: 0.42 }
737
+ ]
738
+ }),
739
+ "forest-night": defineEnvironmentPreset({
740
+ preset: "forest-night",
741
+ scene: "forest",
742
+ timeOfDay: "night",
743
+ environmentMode: 10,
744
+ environmentIntensity: 0.42,
745
+ exposure: 1.42,
746
+ horizonColor: [0.035, 0.08, 0.1, 1],
747
+ zenithColor: [0.012, 0.025, 0.06, 1],
748
+ sunDirection: [0.2, 0.82, -0.46],
749
+ sunColor: [0.42, 0.56, 1.1, 1],
750
+ ambientColor: [0.01, 0.016, 0.02, 1],
751
+ environmentLightSources: [
752
+ { id: "forest-night-moon-gap", kind: "moon", role: "key", direction: [0.2, 0.82, -0.46], color: [0.42, 0.56, 1, 1], intensity: 0.95, angularRadiusRadians: 0.025 },
753
+ { id: "forest-night-canopy", kind: "canopy-transmission", role: "filter", direction: [-0.16, 0.66, 0.1], color: [0.08, 0.18, 0.12, 1], intensity: 0.28 },
754
+ { id: "forest-night-stars", kind: "stars", role: "fill", direction: [0, 1, 0], color: [0.22, 0.28, 0.5, 1], intensity: 0.18 }
755
+ ]
756
+ }),
757
+ "warehouse-dawn": defineEnvironmentPreset({
758
+ preset: "warehouse-dawn",
759
+ scene: "warehouse",
760
+ timeOfDay: "dawn",
761
+ environmentMode: 11,
762
+ environmentIntensity: 0.74,
763
+ exposure: 1.08,
764
+ horizonColor: [0.58, 0.44, 0.34, 1],
765
+ zenithColor: [0.16, 0.19, 0.24, 1],
766
+ sunDirection: [0.82, 0.28, 0.18],
767
+ sunColor: [2.8, 1.7, 0.92, 1],
768
+ ambientColor: [0.028, 0.03, 0.032, 1],
769
+ environmentLightSources: [
770
+ { id: "warehouse-dawn-loading-door", kind: "window-portal", role: "key", direction: [0.82, 0.28, 0.18], color: [1, 0.62, 0.34, 1], intensity: 2.8, angularRadiusRadians: 0.22 },
771
+ { id: "warehouse-dawn-fluorescent", kind: "fluorescent-strip", role: "fill", direction: [0, 1, 0], color: [0.78, 0.9, 1, 1], intensity: 1.1, angularRadiusRadians: 0.35 },
772
+ { id: "warehouse-dawn-concrete-bounce", kind: "ground-bounce", role: "bounce", direction: [0, 0.28, -0.2], color: [0.34, 0.36, 0.38, 1], intensity: 0.42 }
773
+ ]
774
+ }),
775
+ "warehouse-midday": defineEnvironmentPreset({
776
+ preset: "warehouse-midday",
777
+ scene: "warehouse",
778
+ timeOfDay: "midday",
779
+ environmentMode: 12,
780
+ environmentIntensity: 0.92,
781
+ exposure: 0.98,
782
+ horizonColor: [0.64, 0.7, 0.74, 1],
783
+ zenithColor: [0.28, 0.34, 0.42, 1],
784
+ sunDirection: [0.35, 0.86, 0.16],
785
+ sunColor: [4.2, 4, 3.45, 1],
786
+ ambientColor: [0.034, 0.036, 0.038, 1],
787
+ environmentLightSources: [
788
+ { id: "warehouse-midday-skylights", kind: "window-portal", role: "key", direction: [0.35, 0.86, 0.16], color: [0.92, 0.96, 1, 1], intensity: 4.2, angularRadiusRadians: 0.18 },
789
+ { id: "warehouse-midday-fluorescent", kind: "fluorescent-strip", role: "fill", direction: [-0.2, 0.92, 0.1], color: [0.78, 0.92, 1, 1], intensity: 1.6, angularRadiusRadians: 0.45 },
790
+ { id: "warehouse-midday-door-spill", kind: "sodium-door", role: "rim", direction: [-0.82, 0.18, -0.12], color: [1, 0.58, 0.24, 1], intensity: 0.68 }
791
+ ]
792
+ }),
793
+ "warehouse-dusk": defineEnvironmentPreset({
794
+ preset: "warehouse-dusk",
795
+ scene: "warehouse",
796
+ timeOfDay: "dusk",
797
+ environmentMode: 13,
798
+ environmentIntensity: 0.7,
799
+ exposure: 1.16,
800
+ horizonColor: [0.7, 0.32, 0.24, 1],
801
+ zenithColor: [0.08, 0.1, 0.18, 1],
802
+ sunDirection: [-0.78, 0.18, 0.16],
803
+ sunColor: [2.4, 0.94, 0.48, 1],
804
+ ambientColor: [0.022, 0.024, 0.03, 1],
805
+ environmentLightSources: [
806
+ { id: "warehouse-dusk-door-glow", kind: "sodium-door", role: "key", direction: [-0.78, 0.18, 0.16], color: [1, 0.42, 0.2, 1], intensity: 2.4, angularRadiusRadians: 0.18 },
807
+ { id: "warehouse-dusk-fluorescent", kind: "fluorescent-strip", role: "fill", direction: [0, 0.95, -0.08], color: [0.72, 0.88, 1, 1], intensity: 1.35, angularRadiusRadians: 0.4 },
808
+ { id: "warehouse-dusk-emergency", kind: "emergency-beacon", role: "accent", direction: [0.2, 0.35, -0.8], color: [1, 0.08, 0.04, 1], intensity: 0.32 }
809
+ ]
810
+ }),
811
+ "warehouse-night": defineEnvironmentPreset({
812
+ preset: "warehouse-night",
813
+ scene: "warehouse",
814
+ timeOfDay: "night",
815
+ environmentMode: 14,
816
+ environmentIntensity: 0.58,
817
+ exposure: 1.28,
818
+ horizonColor: [0.06, 0.08, 0.12, 1],
819
+ zenithColor: [0.02, 0.03, 0.055, 1],
820
+ sunDirection: [0.1, 0.94, -0.12],
821
+ sunColor: [1.2, 1.65, 2.25, 1],
822
+ ambientColor: [0.014, 0.018, 0.024, 1],
823
+ environmentLightSources: [
824
+ { id: "warehouse-night-fluorescent", kind: "fluorescent-strip", role: "key", direction: [0.1, 0.94, -0.12], color: [0.68, 0.88, 1, 1], intensity: 2.25, angularRadiusRadians: 0.5 },
825
+ { id: "warehouse-night-emergency", kind: "emergency-beacon", role: "accent", direction: [-0.4, 0.3, 0.7], color: [1, 0.05, 0.025, 1], intensity: 0.4 },
826
+ { id: "warehouse-night-door-leak", kind: "window-portal", role: "rim", direction: [0.82, 0.08, -0.2], color: [0.12, 0.22, 0.42, 1], intensity: 0.34 }
827
+ ]
828
+ }),
829
+ "cavern-dawn": defineEnvironmentPreset({
830
+ preset: "cavern-dawn",
831
+ scene: "cavern",
832
+ timeOfDay: "dawn",
833
+ environmentMode: 15,
834
+ environmentIntensity: 0.62,
835
+ exposure: 1.24,
836
+ horizonColor: [0.5, 0.3, 0.2, 1],
837
+ zenithColor: [0.04, 0.07, 0.09, 1],
838
+ sunDirection: [0.72, 0.32, 0.26],
839
+ sunColor: [2.1, 1.22, 0.64, 1],
840
+ ambientColor: [0.018, 0.018, 0.016, 1],
841
+ environmentLightSources: [
842
+ { id: "cavern-dawn-mouth", kind: "cave-mouth", role: "key", direction: [0.72, 0.32, 0.26], color: [1, 0.58, 0.3, 1], intensity: 2.1, angularRadiusRadians: 0.24 },
843
+ { id: "cavern-dawn-torch", kind: "torch", role: "emissive", direction: [-0.35, 0.28, -0.6], color: [1, 0.42, 0.16, 1], intensity: 1.35, reach: 18 },
844
+ { id: "cavern-dawn-crystal", kind: "crystal", role: "accent", direction: [0.08, 0.22, 0.9], color: [0.22, 0.72, 1, 1], intensity: 0.28, reach: 10 }
845
+ ]
846
+ }),
847
+ "cavern-midday": defineEnvironmentPreset({
848
+ preset: "cavern-midday",
849
+ scene: "cavern",
850
+ timeOfDay: "midday",
851
+ environmentMode: 16,
852
+ environmentIntensity: 0.72,
853
+ exposure: 1.16,
854
+ horizonColor: [0.6, 0.56, 0.48, 1],
855
+ zenithColor: [0.08, 0.12, 0.14, 1],
856
+ sunDirection: [0.36, 0.82, 0.14],
857
+ sunColor: [3.4, 3.05, 2.2, 1],
858
+ ambientColor: [0.02, 0.022, 0.02, 1],
859
+ environmentLightSources: [
860
+ { id: "cavern-midday-mouth", kind: "cave-mouth", role: "key", direction: [0.36, 0.82, 0.14], color: [1, 0.9, 0.66, 1], intensity: 3.4, angularRadiusRadians: 0.18 },
861
+ { id: "cavern-midday-biolume", kind: "bioluminescence", role: "fill", direction: [-0.25, 0.25, 0.7], color: [0.1, 0.82, 0.64, 1], intensity: 0.46, reach: 14 },
862
+ { id: "cavern-midday-wet-rock", kind: "ground-bounce", role: "bounce", direction: [0.1, 0.2, -0.3], color: [0.18, 0.2, 0.18, 1], intensity: 0.22 }
863
+ ]
864
+ }),
865
+ "cavern-dusk": defineEnvironmentPreset({
866
+ preset: "cavern-dusk",
867
+ scene: "cavern",
868
+ timeOfDay: "dusk",
869
+ environmentMode: 17,
870
+ environmentIntensity: 0.56,
871
+ exposure: 1.32,
872
+ horizonColor: [0.46, 0.18, 0.14, 1],
873
+ zenithColor: [0.035, 0.045, 0.08, 1],
874
+ sunDirection: [-0.62, 0.22, 0.22],
875
+ sunColor: [1.55, 0.56, 0.28, 1],
876
+ ambientColor: [0.014, 0.014, 0.018, 1],
877
+ environmentLightSources: [
878
+ { id: "cavern-dusk-mouth", kind: "cave-mouth", role: "rim", direction: [-0.62, 0.22, 0.22], color: [1, 0.36, 0.18, 1], intensity: 1.55, angularRadiusRadians: 0.22 },
879
+ { id: "cavern-dusk-torch", kind: "torch", role: "key", direction: [0.32, 0.34, -0.54], color: [1, 0.38, 0.12, 1], intensity: 1.85, reach: 20 },
880
+ { id: "cavern-dusk-biolume", kind: "bioluminescence", role: "fill", direction: [-0.18, 0.18, 0.74], color: [0.08, 0.58, 0.72, 1], intensity: 0.34, reach: 12 }
881
+ ]
882
+ }),
883
+ "cavern-night": defineEnvironmentPreset({
884
+ preset: "cavern-night",
885
+ scene: "cavern",
886
+ timeOfDay: "night",
887
+ environmentMode: 18,
888
+ environmentIntensity: 0.5,
889
+ exposure: 1.45,
890
+ horizonColor: [0.025, 0.035, 0.06, 1],
891
+ zenithColor: [8e-3, 0.014, 0.03, 1],
892
+ sunDirection: [0.18, 0.28, -0.68],
893
+ sunColor: [1.9, 0.72, 0.24, 1],
894
+ ambientColor: [0.01, 0.012, 0.018, 1],
895
+ environmentLightSources: [
896
+ { id: "cavern-night-torch", kind: "torch", role: "key", direction: [0.18, 0.28, -0.68], color: [1, 0.36, 0.12, 1], intensity: 1.9, reach: 18 },
897
+ { id: "cavern-night-biolume", kind: "bioluminescence", role: "fill", direction: [-0.32, 0.16, 0.72], color: [0.06, 0.62, 0.76, 1], intensity: 0.52, reach: 16 },
898
+ { id: "cavern-night-lava", kind: "lava-fissure", role: "emissive", direction: [0.42, 0.12, 0.28], color: [1, 0.18, 0.04, 1], intensity: 0.8, reach: 12 }
899
+ ]
209
900
  })
210
901
  });
211
- function resolveEnvironmentPreset(name) {
902
+ var lightingEnvironmentPresetNames = Object.freeze(
903
+ Object.keys(environmentLightingPresets)
904
+ );
905
+ function resolveEnvironmentPreset(name, timeOfDay) {
212
906
  const presetName = typeof name === "string" && name.length > 0 ? name : "product-studio";
213
907
  const preset = environmentLightingPresets[presetName];
214
908
  if (!preset) {
909
+ if (lightingEnvironmentSceneNames.includes(presetName)) {
910
+ if (timeOfDay != null && !lightingEnvironmentTimeOfDayNames.includes(timeOfDay)) {
911
+ throw new Error(
912
+ `timeOfDay must be one of: ${lightingEnvironmentTimeOfDayNames.join(", ")}.`
913
+ );
914
+ }
915
+ const scenePresetName = `${presetName}-${timeOfDay ?? "midday"}`;
916
+ const scenePreset = environmentLightingPresets[scenePresetName];
917
+ if (scenePreset) {
918
+ return scenePreset;
919
+ }
920
+ }
215
921
  throw new Error(
216
922
  `Unknown lighting environment preset "${presetName}". Expected one of: ${lightingEnvironmentPresetNames.join(", ")}.`
217
923
  );
@@ -223,21 +929,36 @@ function estimateEnvironmentColor(config) {
223
929
  const zenithWeight = 1 - horizonWeight;
224
930
  const glowWeight = 0.055;
225
931
  const intensity = Math.max(config.environmentIntensity, 1e-4);
226
- return freezeVec4([
932
+ return ensureNonNullColor([
227
933
  (config.horizonColor[0] * horizonWeight + config.zenithColor[0] * zenithWeight + config.sunColor[0] * glowWeight) * intensity,
228
934
  (config.horizonColor[1] * horizonWeight + config.zenithColor[1] * zenithWeight + config.sunColor[1] * glowWeight) * intensity,
229
935
  (config.horizonColor[2] * horizonWeight + config.zenithColor[2] * zenithWeight + config.sunColor[2] * glowWeight) * intensity,
230
936
  1
231
- ]);
937
+ ], config.dominantLightSource?.radiance ?? config.sunColor);
232
938
  }
233
939
  function createEnvironmentLightingConfig(options = {}) {
234
- const preset = resolveEnvironmentPreset(options.preset ?? options.name);
940
+ const preset = resolveEnvironmentPreset(
941
+ options.preset ?? options.name ?? options.scene,
942
+ options.timeOfDay
943
+ );
944
+ const environmentPortals = normalizeEnvironmentPortals(
945
+ options.environmentPortals ?? options.portals
946
+ );
947
+ const environmentMap = normalizeEnvironmentMap(
948
+ options.environmentMap ?? options.hdri ?? preset.environmentMap
949
+ );
950
+ const environmentPortalMode = normalizeEnvironmentPortalMode(
951
+ options.environmentPortalMode ?? options.portalMode,
952
+ environmentPortals.length > 0
953
+ );
235
954
  const environmentIntensity = Math.max(
236
955
  readFinite(options.environmentIntensity ?? options.intensity, preset.environmentIntensity),
237
956
  1e-4
238
957
  );
239
- const config = {
958
+ const baseConfig = {
240
959
  preset: preset.preset,
960
+ scene: preset.scene,
961
+ timeOfDay: preset.timeOfDay,
241
962
  profile: typeof options.profile === "string" ? options.profile : defaultLightingProfile,
242
963
  environmentMode: Math.max(0, Math.trunc(readFinite(options.environmentMode, preset.environmentMode))),
243
964
  environmentIntensity,
@@ -248,15 +969,49 @@ function createEnvironmentLightingConfig(options = {}) {
248
969
  normalizeVector3(options.sunDirection, preset.sunDirection)
249
970
  ),
250
971
  sunColor: readColor(options.sunColor, preset.sunColor),
251
- ambientColor: readColor(options.ambientColor, preset.ambientColor)
972
+ ambientColor: readColor(options.ambientColor, preset.ambientColor),
973
+ sunlitBaseline: Math.max(
974
+ 0,
975
+ readFinite(options.sunlitBaseline ?? options.daylightBaseline, preset.sunlitBaseline)
976
+ ),
977
+ environmentPortalMode,
978
+ environmentPortals,
979
+ environmentMap
980
+ };
981
+ const environmentLightSources = normalizeEnvironmentLightSources(
982
+ options.environmentLightSources ?? options.lightSources,
983
+ preset,
984
+ baseConfig
985
+ );
986
+ const dominantLightSource = findDominantEnvironmentLightSource(
987
+ environmentLightSources
988
+ );
989
+ const config = {
990
+ ...baseConfig,
991
+ environmentLightSources,
992
+ lightSources: environmentLightSources,
993
+ dominantLightSource
252
994
  };
253
995
  const environmentColor = estimateEnvironmentColor(config);
996
+ const environmentMissLighting = createEnvironmentMissLighting(
997
+ dominantLightSource,
998
+ environmentColor
999
+ );
254
1000
  return Object.freeze({
255
1001
  ...config,
256
1002
  environmentColor,
1003
+ environmentMissLighting,
257
1004
  wavefront: Object.freeze({
258
1005
  environmentColor,
259
1006
  ambientColor: config.ambientColor,
1007
+ sunlitBaseline: config.sunlitBaseline,
1008
+ environmentPortalMode: config.environmentPortalMode,
1009
+ environmentPortals: config.environmentPortals,
1010
+ environmentMap: config.environmentMap,
1011
+ environmentLightSources: config.environmentLightSources,
1012
+ lightSources: config.environmentLightSources,
1013
+ dominantLightSource,
1014
+ environmentMissLighting,
260
1015
  environmentLighting: Object.freeze({
261
1016
  horizonColor: config.horizonColor,
262
1017
  zenithColor: config.zenithColor,
@@ -264,7 +1019,15 @@ function createEnvironmentLightingConfig(options = {}) {
264
1019
  sunColor: config.sunColor,
265
1020
  intensity: config.environmentIntensity,
266
1021
  mode: config.environmentMode,
267
- exposure: config.exposure
1022
+ exposure: config.exposure,
1023
+ sunlitBaseline: config.sunlitBaseline,
1024
+ environmentPortalMode: config.environmentPortalMode,
1025
+ environmentPortalCount: config.environmentPortals.length,
1026
+ environmentMap: config.environmentMap,
1027
+ environmentLightSources: config.environmentLightSources,
1028
+ environmentLightSourceCount: config.environmentLightSources.length,
1029
+ dominantLightSource,
1030
+ environmentMissLighting
268
1031
  })
269
1032
  })
270
1033
  });
@@ -274,6 +1037,14 @@ function createWavefrontEnvironmentLightingOptions(options = {}) {
274
1037
  return Object.freeze({
275
1038
  environmentColor: config.wavefront.environmentColor,
276
1039
  ambientColor: config.wavefront.ambientColor,
1040
+ sunlitBaseline: config.wavefront.sunlitBaseline,
1041
+ environmentPortalMode: config.wavefront.environmentPortalMode,
1042
+ environmentPortals: config.wavefront.environmentPortals,
1043
+ environmentMap: config.wavefront.environmentMap,
1044
+ environmentLightSources: config.wavefront.environmentLightSources,
1045
+ lightSources: config.wavefront.environmentLightSources,
1046
+ dominantLightSource: config.wavefront.dominantLightSource,
1047
+ environmentMissLighting: config.wavefront.environmentMissLighting,
277
1048
  environmentLighting: config.wavefront.environmentLighting,
278
1049
  lightingEnvironment: config
279
1050
  });
@@ -1407,7 +2178,12 @@ export {
1407
2178
  getLightingTechniqueWorkerManifest,
1408
2179
  lightingDebugOwner,
1409
2180
  lightingDistanceBands,
2181
+ lightingEnvironmentLightSourceKinds,
2182
+ lightingEnvironmentPortalModes,
2183
+ lightingEnvironmentPortalShapes,
1410
2184
  lightingEnvironmentPresetNames,
2185
+ lightingEnvironmentSceneNames,
2186
+ lightingEnvironmentTimeOfDayNames,
1411
2187
  lightingJobLabels,
1412
2188
  lightingJobs,
1413
2189
  lightingPreludeWgslUrl,