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