@pascal-app/viewer 1.0.3 → 1.0.5
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/capture/capture-runtime.js +1 -1
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.d.ts +1 -1
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +12 -4
- package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -1
- package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -1
- package/dist/components/viewer/frame-limiter.d.ts +1 -0
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
- package/dist/components/viewer/frame-limiter.js +22 -3
- package/dist/components/viewer/glb-interactive.d.ts +25 -1
- package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
- package/dist/components/viewer/glb-interactive.js +253 -86
- package/dist/components/viewer/glb-mechanisms.d.ts +10 -0
- package/dist/components/viewer/glb-mechanisms.d.ts.map +1 -0
- package/dist/components/viewer/glb-mechanisms.js +19 -0
- package/dist/components/viewer/glb-reference-nodes.js +1 -1
- package/dist/components/viewer/glb-replace-instances.js +1 -1
- package/dist/components/viewer/glb-scene.d.ts +45 -27
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +421 -508
- package/dist/components/viewer/glb-walkthrough-controller.d.ts +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.js +13 -2
- package/dist/components/viewer/index.d.ts +24 -1
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +111 -37
- package/dist/components/viewer/lights.d.ts.map +1 -1
- package/dist/components/viewer/lights.js +113 -22
- package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
- package/dist/components/viewer/perf-monitor.js +6 -0
- package/dist/components/viewer/perf-panel.d.ts.map +1 -1
- package/dist/components/viewer/perf-panel.js +1 -1
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +104 -36
- package/dist/components/viewer/registered-systems.d.ts.map +1 -1
- package/dist/components/viewer/registered-systems.js +17 -3
- package/dist/components/viewer/render-error.d.ts +18 -0
- package/dist/components/viewer/render-error.d.ts.map +1 -0
- package/dist/components/viewer/render-error.js +29 -0
- package/dist/components/viewer/scene-bvh.d.ts.map +1 -1
- package/dist/components/viewer/scene-bvh.js +1 -1
- package/dist/components/viewer/scene-environment.d.ts.map +1 -1
- package/dist/components/viewer/scene-environment.js +31 -11
- package/dist/components/viewer/scene-ground-replacement.d.ts +6 -0
- package/dist/components/viewer/scene-ground-replacement.d.ts.map +1 -1
- package/dist/components/viewer/scene-ground-replacement.js +15 -0
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +25 -7
- package/dist/components/viewer/underground-ambiance.d.ts +9 -0
- package/dist/components/viewer/underground-ambiance.d.ts.map +1 -0
- package/dist/components/viewer/underground-ambiance.js +105 -0
- package/dist/components/viewer/viewer-camera.d.ts +4 -0
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/viewer-camera.js +12 -2
- package/dist/components/viewer/viewer-presentations.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-gltf-ktx2.js +2 -0
- package/dist/hooks/use-node-events.d.ts.map +1 -1
- package/dist/index.d.ts +36 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -19
- package/dist/lib/asset-url.d.ts.map +1 -1
- package/dist/lib/asset-url.js +7 -1
- package/dist/lib/backdrop.d.ts +17 -0
- package/dist/lib/backdrop.d.ts.map +1 -1
- package/dist/lib/backdrop.js +18 -1
- package/dist/lib/construction-dust.d.ts +57 -0
- package/dist/lib/construction-dust.d.ts.map +1 -0
- package/dist/lib/construction-dust.js +187 -0
- package/dist/lib/csg-utils.js +1 -1
- package/dist/lib/display-state.d.ts +25 -0
- package/dist/lib/display-state.d.ts.map +1 -0
- package/dist/lib/display-state.js +1 -0
- package/dist/lib/foundation-materials.d.ts +26 -0
- package/dist/lib/foundation-materials.d.ts.map +1 -0
- package/dist/lib/foundation-materials.js +65 -0
- package/dist/lib/gltf-unlit.d.ts +10 -0
- package/dist/lib/gltf-unlit.d.ts.map +1 -0
- package/dist/lib/gltf-unlit.js +23 -0
- package/dist/lib/ground-window.d.ts +33 -0
- package/dist/lib/ground-window.d.ts.map +1 -0
- package/dist/lib/ground-window.js +114 -0
- package/dist/lib/hero-pose.d.ts +13 -3
- package/dist/lib/hero-pose.d.ts.map +1 -1
- package/dist/lib/hero-pose.js +72 -5
- package/dist/lib/ink-edges.d.ts +6 -3
- package/dist/lib/ink-edges.d.ts.map +1 -1
- package/dist/lib/ink-edges.js +17 -7
- package/dist/lib/key-light-override.d.ts +11 -0
- package/dist/lib/key-light-override.d.ts.map +1 -0
- package/dist/lib/key-light-override.js +14 -0
- package/dist/lib/ktx2-loader.d.ts +7 -0
- package/dist/lib/ktx2-loader.d.ts.map +1 -1
- package/dist/lib/ktx2-loader.js +35 -0
- package/dist/lib/layer-pass.d.ts.map +1 -1
- package/dist/lib/layers.d.ts +11 -7
- package/dist/lib/layers.d.ts.map +1 -1
- package/dist/lib/layers.js +16 -6
- package/dist/lib/live-frame-hold.d.ts +14 -0
- package/dist/lib/live-frame-hold.d.ts.map +1 -0
- package/dist/lib/live-frame-hold.js +28 -0
- package/dist/lib/materials.d.ts +19 -7
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +65 -9
- package/dist/lib/merged-outline-node.d.ts +5 -0
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +80 -2
- package/dist/lib/node-top-surface-height.d.ts +6 -0
- package/dist/lib/node-top-surface-height.d.ts.map +1 -0
- package/dist/lib/node-top-surface-height.js +74 -0
- package/dist/lib/perf-probe-state.d.ts +39 -0
- package/dist/lib/perf-probe-state.d.ts.map +1 -0
- package/dist/lib/perf-probe-state.js +17 -0
- package/dist/lib/pointer-events.d.ts +26 -2
- package/dist/lib/pointer-events.d.ts.map +1 -1
- package/dist/lib/pointer-events.js +99 -12
- package/dist/lib/post-processing-resources.d.ts.map +1 -1
- package/dist/lib/procedural-emission.d.ts +7 -0
- package/dist/lib/procedural-emission.d.ts.map +1 -0
- package/dist/lib/procedural-emission.js +54 -0
- package/dist/lib/reveal-candidates.d.ts +80 -0
- package/dist/lib/reveal-candidates.d.ts.map +1 -0
- package/dist/lib/reveal-candidates.js +524 -0
- package/dist/lib/reveal-ghost.d.ts +9 -0
- package/dist/lib/reveal-ghost.d.ts.map +1 -0
- package/dist/lib/reveal-ghost.js +62 -0
- package/dist/lib/reveal-pending.d.ts +12 -0
- package/dist/lib/reveal-pending.d.ts.map +1 -0
- package/dist/lib/reveal-pending.js +12 -0
- package/dist/lib/reveal-pose.d.ts +70 -0
- package/dist/lib/reveal-pose.d.ts.map +1 -0
- package/dist/lib/reveal-pose.js +248 -0
- package/dist/lib/reveal-schedule.d.ts +208 -0
- package/dist/lib/reveal-schedule.d.ts.map +1 -0
- package/dist/lib/reveal-schedule.js +410 -0
- package/dist/lib/reveal-texture-scale.d.ts +5 -0
- package/dist/lib/reveal-texture-scale.d.ts.map +1 -0
- package/dist/lib/reveal-texture-scale.js +113 -0
- package/dist/lib/reveal-windows.d.ts +23 -0
- package/dist/lib/reveal-windows.d.ts.map +1 -0
- package/dist/lib/reveal-windows.js +31 -0
- package/dist/lib/reveal-wipe.d.ts +71 -0
- package/dist/lib/reveal-wipe.d.ts.map +1 -0
- package/dist/lib/reveal-wipe.js +105 -0
- package/dist/lib/scene-pass-mrt.d.ts +12 -0
- package/dist/lib/scene-pass-mrt.d.ts.map +1 -0
- package/dist/lib/scene-pass-mrt.js +23 -0
- package/dist/lib/scene-support-height.d.ts +4 -0
- package/dist/lib/scene-support-height.d.ts.map +1 -0
- package/dist/lib/scene-support-height.js +34 -0
- package/dist/lib/scene-themes.d.ts +30 -8
- package/dist/lib/scene-themes.d.ts.map +1 -1
- package/dist/lib/scene-themes.js +36 -0
- package/dist/lib/scene-visibility.d.ts +17 -1
- package/dist/lib/scene-visibility.d.ts.map +1 -1
- package/dist/lib/scene-visibility.js +53 -3
- package/dist/lib/scripted-opening.d.ts +11 -0
- package/dist/lib/scripted-opening.d.ts.map +1 -0
- package/dist/lib/scripted-opening.js +20 -0
- package/dist/lib/site-surfaces.d.ts +32 -0
- package/dist/lib/site-surfaces.d.ts.map +1 -0
- package/dist/lib/site-surfaces.js +70 -0
- package/dist/lib/snapshot-pipeline.d.ts +34 -3
- package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
- package/dist/lib/snapshot-pipeline.js +247 -117
- package/dist/lib/terrain-perimeter-fill.d.ts.map +1 -1
- package/dist/lib/terrain-perimeter-fill.js +22 -14
- package/dist/lib/tsl-compat.d.ts +2 -2
- package/dist/lib/tsl-compat.d.ts.map +1 -1
- package/dist/lib/underground-ambiance.d.ts +168 -0
- package/dist/lib/underground-ambiance.d.ts.map +1 -0
- package/dist/lib/underground-ambiance.js +334 -0
- package/dist/lib/zone-geometry.d.ts +11 -0
- package/dist/lib/zone-geometry.d.ts.map +1 -0
- package/dist/lib/zone-geometry.js +46 -0
- package/dist/store/use-item-light-pool.d.ts +14 -10
- package/dist/store/use-item-light-pool.d.ts.map +1 -1
- package/dist/store/use-item-light-pool.js +52 -26
- package/dist/store/use-viewer.d.ts +194 -26
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +164 -21
- package/dist/systems/ceiling/ceiling-system.d.ts +15 -1
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +88 -6
- package/dist/systems/construction-reveal/construction-dust.d.ts +16 -0
- package/dist/systems/construction-reveal/construction-dust.d.ts.map +1 -0
- package/dist/systems/construction-reveal/construction-dust.js +92 -0
- package/dist/systems/construction-reveal/construction-reveal.d.ts +276 -0
- package/dist/systems/construction-reveal/construction-reveal.d.ts.map +1 -0
- package/dist/systems/construction-reveal/construction-reveal.js +2383 -0
- package/dist/systems/construction-reveal/dust-material.d.ts +10 -0
- package/dist/systems/construction-reveal/dust-material.d.ts.map +1 -0
- package/dist/systems/construction-reveal/dust-material.js +17 -0
- package/dist/systems/construction-reveal/ghost-dress.d.ts +10 -0
- package/dist/systems/construction-reveal/ghost-dress.d.ts.map +1 -0
- package/dist/systems/construction-reveal/ghost-dress.js +24 -0
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +55 -17
- package/dist/systems/elevator/elevator-interaction-system.d.ts +7 -0
- package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-interaction-system.js +18 -1
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts +3 -1
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -1
- package/dist/systems/floor-elevation/floor-elevation-system.js +33 -5
- package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
- package/dist/systems/geometry/geometry-system.js +71 -11
- package/dist/systems/interactive/control-widget.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.js +52 -17
- package/dist/systems/interactive/procedural-controls.d.ts +13 -0
- package/dist/systems/interactive/procedural-controls.d.ts.map +1 -0
- package/dist/systems/interactive/procedural-controls.js +17 -0
- package/dist/systems/interactive/scripted-clips.d.ts +19 -0
- package/dist/systems/interactive/scripted-clips.d.ts.map +1 -0
- package/dist/systems/interactive/scripted-clips.js +134 -0
- package/dist/systems/item/item-system.d.ts.map +1 -1
- package/dist/systems/item/item-system.js +9 -3
- package/dist/systems/item/object-cut-invalidation.d.ts +3 -0
- package/dist/systems/item/object-cut-invalidation.d.ts.map +1 -0
- package/dist/systems/item/object-cut-invalidation.js +68 -0
- package/dist/systems/item-light/item-light-system.d.ts +1 -1
- package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
- package/dist/systems/item-light/item-light-system.js +48 -53
- package/dist/systems/level/level-hold.d.ts +4 -0
- package/dist/systems/level/level-hold.d.ts.map +1 -0
- package/dist/systems/level/level-hold.js +14 -0
- package/dist/systems/level/level-system.d.ts.map +1 -1
- package/dist/systems/level/level-system.js +19 -6
- package/dist/systems/level/level-utils.d.ts +19 -6
- package/dist/systems/level/level-utils.d.ts.map +1 -1
- package/dist/systems/level/level-utils.js +68 -9
- package/dist/systems/level/shadow-only-levels.d.ts +9 -0
- package/dist/systems/level/shadow-only-levels.d.ts.map +1 -0
- package/dist/systems/level/shadow-only-levels.js +7 -0
- package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts +103 -0
- package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts.map +1 -0
- package/dist/systems/roof/__fixtures__/roof-plane-cases.js +317 -0
- package/dist/systems/roof/roof-materials.d.ts +16 -2
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +64 -31
- package/dist/systems/roof/roof-system.d.ts +21 -4
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +374 -49
- package/dist/systems/slab/slab-system.d.ts +1 -1
- package/dist/systems/slab/slab-system.d.ts.map +1 -1
- package/dist/systems/slab/slab-system.js +49 -19
- package/dist/systems/stair/stair-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-system.js +133 -354
- package/dist/systems/wall/wall-cutout-cache.d.ts +39 -3
- package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout-cache.js +141 -19
- package/dist/systems/wall/wall-cutout.d.ts +6 -0
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +42 -28
- package/dist/systems/wall/wall-finish-data.d.ts +22 -0
- package/dist/systems/wall/wall-finish-data.d.ts.map +1 -0
- package/dist/systems/wall/wall-finish-data.js +17 -0
- package/dist/systems/wall/wall-material-variant.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.d.ts +9 -4
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +135 -153
- package/dist/systems/wall/wall-placeholder-sweep.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.d.ts +33 -2
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +621 -159
- package/dist/systems/window/corner-frame.d.ts +10 -0
- package/dist/systems/window/corner-frame.d.ts.map +1 -0
- package/dist/systems/window/corner-frame.js +17 -0
- package/dist/systems/window/window-system.d.ts +1 -1
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +71 -27
- package/package.json +10 -10
- package/dist/systems/fence/fence-system.d.ts +0 -22
- package/dist/systems/fence/fence-system.d.ts.map +0 -1
- package/dist/systems/fence/fence-system.js +0 -357
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type { AmbientLight, DirectionalLight, HemisphereLight } from 'three';
|
|
2
|
+
import type { GroundMode } from '../store/use-viewer';
|
|
3
|
+
/**
|
|
4
|
+
* Diving under the ground is the scene's own dark mode, as going under water is in a game: the
|
|
5
|
+
* moment the eye crosses the ground surface the backdrop, the far site, the screen's edges and
|
|
6
|
+
* the sky's light go to the dark theme's slate, and crossing back up brings the day back. Above
|
|
7
|
+
* the ground nothing changes, whatever level is shown (a veiled basement seen from above is the
|
|
8
|
+
* veil as it was). The shown level is not touched: its materials keep their colours and the
|
|
9
|
+
* eye's own light keeps its rooms as readable as ever. Dark around, not dark inside.
|
|
10
|
+
*
|
|
11
|
+
* One factor drives all of it: `0` is the world as it is, `1` is the dark mode. The factor eases
|
|
12
|
+
* between the two over {@link AMBIANCE_SECONDS}, never pops, and is instant when the person's
|
|
13
|
+
* animation setting is Off. It lives here as a shader uniform (the pipeline and the veil read
|
|
14
|
+
* it with no rebuild); the store keeps only whether it is above 0 (`ambianceActive`).
|
|
15
|
+
*/
|
|
16
|
+
/** How long the crossing takes, in and out. */
|
|
17
|
+
export declare const AMBIANCE_SECONDS = 0.7;
|
|
18
|
+
/** The simple fade's crossing (`UndergroundTransition` `fade`), in and out. */
|
|
19
|
+
export declare const FADE_SECONDS = 0.4;
|
|
20
|
+
/** The thin rim along the cut of the hole in the ground, from above. */
|
|
21
|
+
export declare const UNDERGROUND_RIM: "#3c3c3c";
|
|
22
|
+
/** The grade ring, where the ground meets the level below grade: a light rim in the dark mode. */
|
|
23
|
+
export declare const UNDERGROUND_RING: "#b4b4b4";
|
|
24
|
+
/** The corners the vignette closes in to. */
|
|
25
|
+
export declare const UNDERGROUND_VIGNETTE: "#0c0c0c";
|
|
26
|
+
/** The sky's ambient and hemisphere light, as a share of what the theme gives. */
|
|
27
|
+
export declare const SKY_LIGHT_SCALE = 0.65;
|
|
28
|
+
/**
|
|
29
|
+
* The eye's own light at full ambiance: the veil's own fill (1) and as much again as the sky's
|
|
30
|
+
* comes down, so the rooms keep their light. It rides the factor, from the veil's own fill (or
|
|
31
|
+
* from nothing where no veil stands), so it neither steps on nor off.
|
|
32
|
+
*/
|
|
33
|
+
export declare const EYE_FILL_INTENSITY = 2.4;
|
|
34
|
+
/** The sky light's tint pulls this much toward the palette's neutral light grey. */
|
|
35
|
+
export declare const SKY_LIGHT_TINT = 0.15;
|
|
36
|
+
/** Fog begins this far past the shown level's box and has taken the site by the second. */
|
|
37
|
+
export declare const FOG_START = 3;
|
|
38
|
+
export declare const FOG_END = 24;
|
|
39
|
+
/** The screen's corners darken by this much at most. */
|
|
40
|
+
export declare const VIGNETTE_STRENGTH = 0.42;
|
|
41
|
+
/**
|
|
42
|
+
* How far the eye goes under (or back over) the ground before the flag turns, in metres: it dives
|
|
43
|
+
* 0.10 m below the ground and surfaces 0.10 m above it, a 0.20 m band in all, so an orbit
|
|
44
|
+
* grazing the surface does not flicker.
|
|
45
|
+
*/
|
|
46
|
+
export declare const EYE_BAND = 0.1;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the world beyond the walls is the earth's: only the eye under the ground, and never on
|
|
49
|
+
* Solid (the person's own override). What level is shown, or whether the ground is veiled, is not
|
|
50
|
+
* in it. The backdrop and, outside the walkthrough, the whole dark mode follow this edge.
|
|
51
|
+
*/
|
|
52
|
+
export declare function earthTarget(state: {
|
|
53
|
+
eyeUnderGround: boolean;
|
|
54
|
+
groundMode: GroundMode;
|
|
55
|
+
}): 0 | 1;
|
|
56
|
+
/**
|
|
57
|
+
* The edge the dark mode (fog, vignette, the sky's light and the eye's own) is wanted by: the
|
|
58
|
+
* earth's edge, except in the walkthrough, where the rooms keep their normal light as the person
|
|
59
|
+
* walks down a stair, and only what is seen outside (the backdrop) turns to earth.
|
|
60
|
+
*/
|
|
61
|
+
export declare function ambianceTarget(state: {
|
|
62
|
+
eyeUnderGround: boolean;
|
|
63
|
+
groundMode: GroundMode;
|
|
64
|
+
walkthroughMode?: boolean;
|
|
65
|
+
}): 0 | 1;
|
|
66
|
+
/**
|
|
67
|
+
* Whether the eye lies under the ground, with a small band so a camera resting on the ground
|
|
68
|
+
* plane does not chatter: it goes under {@link EYE_BAND} below the ground and comes back
|
|
69
|
+
* {@link EYE_BAND} above it.
|
|
70
|
+
*/
|
|
71
|
+
export declare function eyeUnderTheGround(previous: boolean, eyeY: number, groundY: number): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* One step of the crossing: `progress` moves toward `target` (0 or 1) in a straight line over
|
|
74
|
+
* `seconds`, and is exactly the target once it has arrived. `seconds <= 0` is instant.
|
|
75
|
+
*/
|
|
76
|
+
export declare function stepAmbianceProgress(progress: number, target: number, dt: number, seconds: number): number;
|
|
77
|
+
/** The eased factor of a straight-line progress: slow in, slow out. */
|
|
78
|
+
export declare function easeAmbiance(progress: number): number;
|
|
79
|
+
/** The factor as shaders read it: zero while a capture holds the ambiance off. */
|
|
80
|
+
export declare function undergroundAmbianceNode(): import("three/webgpu").UniformNode<"float", number>;
|
|
81
|
+
/** How far the backdrop is the earth's, as shaders read it: zero while a capture holds the ambiance off. */
|
|
82
|
+
export declare function undergroundEarthNode(): import("three/webgpu").UniformNode<"float", number>;
|
|
83
|
+
/** How far the ground's hole is open, as shaders read it: 0 while a capture holds the world plain. */
|
|
84
|
+
export declare function groundHoleOpenNode(): import("three/webgpu").UniformNode<"float", number>;
|
|
85
|
+
/** How far the ground's hole is open now (0 while a capture holds the world plain). */
|
|
86
|
+
export declare function groundHoleOpenNow(): number;
|
|
87
|
+
/** Sets how much the crossing is the noise mask (1) rather than a uniform fade (0); the system's word. */
|
|
88
|
+
export declare function setDiveGrainWeight(next: number): void;
|
|
89
|
+
/** Sets the live opening of the ground's hole (the system's word). */
|
|
90
|
+
export declare function setGroundHoleOpen(next: number): void;
|
|
91
|
+
/** The factor the shown frame wears now: the eased value, or `0` while a capture holds it off. */
|
|
92
|
+
export declare function ambianceNow(): number;
|
|
93
|
+
/** How far the backdrop is the earth's now: the eased value, or `0` while a capture holds it off. */
|
|
94
|
+
export declare function earthNow(): number;
|
|
95
|
+
/** Sets the live factor (the system's word); shaders and lights follow the held value. */
|
|
96
|
+
export declare function setAmbianceFactor(next: number): void;
|
|
97
|
+
/** Sets the live earth factor of the backdrop (the system's word). */
|
|
98
|
+
export declare function setEarthFactor(next: number): void;
|
|
99
|
+
/**
|
|
100
|
+
* The shown frame without the ambiance, for one capture: an agent's picture of a level below
|
|
101
|
+
* grade is read for its rooms, so it is taken in the world's own light, and the person's hole in
|
|
102
|
+
* the ground is not in it (a capture sets its own ground: the plain veil over a level below
|
|
103
|
+
* grade, solid for an exterior). The returned function gives the person's view back.
|
|
104
|
+
*/
|
|
105
|
+
export declare function temporarilyWithoutAmbiance(): () => void;
|
|
106
|
+
/** The box the fog keeps clear: the shown level's, or a cube about the eye when none is shown. */
|
|
107
|
+
export declare function setAmbianceFocus(box: {
|
|
108
|
+
min: readonly number[];
|
|
109
|
+
max: readonly number[];
|
|
110
|
+
} | null, eye: {
|
|
111
|
+
x: number;
|
|
112
|
+
y: number;
|
|
113
|
+
z: number;
|
|
114
|
+
}): void;
|
|
115
|
+
/** The box the fog keeps clear now (what {@link setAmbianceFocus} last set). */
|
|
116
|
+
export declare function ambianceFocus(): {
|
|
117
|
+
min: number[];
|
|
118
|
+
max: number[];
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* The dark mode's backdrop for a view direction: the theme backdrop's own gradient, in the dark
|
|
122
|
+
* theme's colours. The fog dissolves into this same colour per pixel, so what is far leaves no seam.
|
|
123
|
+
*/
|
|
124
|
+
export declare function undergroundBackdrop(dirY: any): any;
|
|
125
|
+
/**
|
|
126
|
+
* How far a world position stands in the dark mode's fog, 0 to 1, from its distance outside the
|
|
127
|
+
* shown box (the box itself, and what stands close about it, stays clear). Not scaled by the
|
|
128
|
+
* factor: the pipeline weighs it with {@link undergroundDissolve}.
|
|
129
|
+
*/
|
|
130
|
+
export declare function undergroundFogAmount(worldPosition: any): any;
|
|
131
|
+
/**
|
|
132
|
+
* The noise the crossing's mask is cut from: two screen-space perlin octaves, 0 to 1. Computed once
|
|
133
|
+
* a pixel and handed to every {@link undergroundDissolve} that needs it.
|
|
134
|
+
*/
|
|
135
|
+
export declare function undergroundDissolveGrain(uv?: any): any;
|
|
136
|
+
/**
|
|
137
|
+
* The crossing as a noise mask closing over the screen: a per-pixel weight, 0 to 1, that goes
|
|
138
|
+
* from 0 everywhere at `amount` 0 (the factor, by default) to 1 everywhere at 1, through soft
|
|
139
|
+
* blobs of the dark world spreading (a fine perlin mask in screen space, not a cross-fade). Weighs
|
|
140
|
+
* the backdrop, the fog and the vignette; above and below the crossing it is exactly 0 and 1.
|
|
141
|
+
* With the simple fade chosen (`grainWeightNode` 0) it is `amount` itself, the same everywhere.
|
|
142
|
+
*/
|
|
143
|
+
export declare function undergroundDissolve(uv?: any, amount?: any, grain?: any): any;
|
|
144
|
+
/** The world position of the pixel at `uv` from the scene pass's raw depth. */
|
|
145
|
+
export declare function worldPositionFromDepth(rawDepth: any, projectionInverse: any, cameraWorld: any, uv?: any): any;
|
|
146
|
+
/** The screen's edges closing in: 0 at the centre, 1 at the corners (weigh it with the dissolve). */
|
|
147
|
+
export declare function undergroundVignette(uv?: any): any;
|
|
148
|
+
type SkyLights = {
|
|
149
|
+
ambient: AmbientLight | null;
|
|
150
|
+
hemisphere: HemisphereLight | null;
|
|
151
|
+
/** The light from the eye (`UndergroundFill`), when it is mounted. */
|
|
152
|
+
fill: DirectionalLight | null;
|
|
153
|
+
/** What the fill shines at with no ambiance: the veil's own 1 over a veiled ground, else 0. */
|
|
154
|
+
fillRest: number;
|
|
155
|
+
};
|
|
156
|
+
/** The lights the ambiance moves: `Lights` offers the sky's ambient and hemisphere and the eye's fill. */
|
|
157
|
+
export declare function registerSkyLights(source: () => SkyLights): () => void;
|
|
158
|
+
/**
|
|
159
|
+
* Brings the sky's lights down and tints them by `amount`, and brings the eye's fill up, for the
|
|
160
|
+
* frame about to be drawn. Their neutral state is kept and given back by
|
|
161
|
+
* {@link restoreSkyLights} before the next frame lerps them, so the theme's own smoothing never
|
|
162
|
+
* fights the ambiance. With no ambiance (or none registered) the fill is simply set to its rest.
|
|
163
|
+
*/
|
|
164
|
+
export declare function applyAmbianceToSkyLights(amount: number): void;
|
|
165
|
+
/** Gives the sky's lights back as the theme set them, and the eye's fill its rest. */
|
|
166
|
+
export declare function restoreSkyLights(): void;
|
|
167
|
+
export {};
|
|
168
|
+
//# sourceMappingURL=underground-ambiance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"underground-ambiance.d.ts","sourceRoot":"","sources":["../../src/lib/underground-ambiance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { Color, Vector3 } from 'three';
|
|
2
|
+
import { abs, clamp, color, float, getViewPosition, max, mix, mx_noise_float, screenUV, smoothstep, uniform, vec2, vec3, vec4, } from 'three/tsl';
|
|
3
|
+
import { backdropGradient } from './backdrop';
|
|
4
|
+
import { UNDERGROUND_PALETTE } from './scene-themes';
|
|
5
|
+
/**
|
|
6
|
+
* Diving under the ground is the scene's own dark mode, as going under water is in a game: the
|
|
7
|
+
* moment the eye crosses the ground surface the backdrop, the far site, the screen's edges and
|
|
8
|
+
* the sky's light go to the dark theme's slate, and crossing back up brings the day back. Above
|
|
9
|
+
* the ground nothing changes, whatever level is shown (a veiled basement seen from above is the
|
|
10
|
+
* veil as it was). The shown level is not touched: its materials keep their colours and the
|
|
11
|
+
* eye's own light keeps its rooms as readable as ever. Dark around, not dark inside.
|
|
12
|
+
*
|
|
13
|
+
* One factor drives all of it: `0` is the world as it is, `1` is the dark mode. The factor eases
|
|
14
|
+
* between the two over {@link AMBIANCE_SECONDS}, never pops, and is instant when the person's
|
|
15
|
+
* animation setting is Off. It lives here as a shader uniform (the pipeline and the veil read
|
|
16
|
+
* it with no rebuild); the store keeps only whether it is above 0 (`ambianceActive`).
|
|
17
|
+
*/
|
|
18
|
+
/** How long the crossing takes, in and out. */
|
|
19
|
+
export const AMBIANCE_SECONDS = 0.7;
|
|
20
|
+
/** The simple fade's crossing (`UndergroundTransition` `fade`), in and out. */
|
|
21
|
+
export const FADE_SECONDS = 0.4;
|
|
22
|
+
/**
|
|
23
|
+
* The dark mode's palette is one place, beside the scene theme tokens
|
|
24
|
+
* (`UNDERGROUND_PALETTE` in `lib/scene-themes.ts`): neutral anthracite, no blue cast. The backdrop
|
|
25
|
+
* is the theme backdrop's own gradient (`lib/backdrop.ts`) in its stops.
|
|
26
|
+
*/
|
|
27
|
+
const BACKDROP = {
|
|
28
|
+
background: UNDERGROUND_PALETTE.background,
|
|
29
|
+
haze: UNDERGROUND_PALETTE.haze,
|
|
30
|
+
sky: UNDERGROUND_PALETTE.sky,
|
|
31
|
+
skyDeep: UNDERGROUND_PALETTE.skyDeep,
|
|
32
|
+
};
|
|
33
|
+
/** The thin rim along the cut of the hole in the ground, from above. */
|
|
34
|
+
export const UNDERGROUND_RIM = UNDERGROUND_PALETTE.rim;
|
|
35
|
+
/** The grade ring, where the ground meets the level below grade: a light rim in the dark mode. */
|
|
36
|
+
export const UNDERGROUND_RING = UNDERGROUND_PALETTE.ring;
|
|
37
|
+
/** The corners the vignette closes in to. */
|
|
38
|
+
export const UNDERGROUND_VIGNETTE = UNDERGROUND_PALETTE.vignette;
|
|
39
|
+
/** The sky's ambient and hemisphere light, as a share of what the theme gives. */
|
|
40
|
+
export const SKY_LIGHT_SCALE = 0.65;
|
|
41
|
+
/**
|
|
42
|
+
* The eye's own light at full ambiance: the veil's own fill (1) and as much again as the sky's
|
|
43
|
+
* comes down, so the rooms keep their light. It rides the factor, from the veil's own fill (or
|
|
44
|
+
* from nothing where no veil stands), so it neither steps on nor off.
|
|
45
|
+
*/
|
|
46
|
+
export const EYE_FILL_INTENSITY = 2.4;
|
|
47
|
+
/** The sky light's tint pulls this much toward the palette's neutral light grey. */
|
|
48
|
+
export const SKY_LIGHT_TINT = 0.15;
|
|
49
|
+
const TINT = UNDERGROUND_PALETTE.tint;
|
|
50
|
+
/** Fog begins this far past the shown level's box and has taken the site by the second. */
|
|
51
|
+
export const FOG_START = 3;
|
|
52
|
+
export const FOG_END = 24;
|
|
53
|
+
/** What remains of the far site when the fog is complete. */
|
|
54
|
+
const FOG_CAP = 0.97;
|
|
55
|
+
/** The screen's corners darken by this much at most. */
|
|
56
|
+
export const VIGNETTE_STRENGTH = 0.42;
|
|
57
|
+
/**
|
|
58
|
+
* How far the eye goes under (or back over) the ground before the flag turns, in metres: it dives
|
|
59
|
+
* 0.10 m below the ground and surfaces 0.10 m above it, a 0.20 m band in all, so an orbit
|
|
60
|
+
* grazing the surface does not flicker.
|
|
61
|
+
*/
|
|
62
|
+
export const EYE_BAND = 0.1;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the world beyond the walls is the earth's: only the eye under the ground, and never on
|
|
65
|
+
* Solid (the person's own override). What level is shown, or whether the ground is veiled, is not
|
|
66
|
+
* in it. The backdrop and, outside the walkthrough, the whole dark mode follow this edge.
|
|
67
|
+
*/
|
|
68
|
+
export function earthTarget(state) {
|
|
69
|
+
if (state.groundMode !== 'auto')
|
|
70
|
+
return 0;
|
|
71
|
+
return state.eyeUnderGround ? 1 : 0;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The edge the dark mode (fog, vignette, the sky's light and the eye's own) is wanted by: the
|
|
75
|
+
* earth's edge, except in the walkthrough, where the rooms keep their normal light as the person
|
|
76
|
+
* walks down a stair, and only what is seen outside (the backdrop) turns to earth.
|
|
77
|
+
*/
|
|
78
|
+
export function ambianceTarget(state) {
|
|
79
|
+
return state.walkthroughMode === true ? 0 : earthTarget(state);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Whether the eye lies under the ground, with a small band so a camera resting on the ground
|
|
83
|
+
* plane does not chatter: it goes under {@link EYE_BAND} below the ground and comes back
|
|
84
|
+
* {@link EYE_BAND} above it.
|
|
85
|
+
*/
|
|
86
|
+
export function eyeUnderTheGround(previous, eyeY, groundY) {
|
|
87
|
+
return previous ? eyeY < groundY + EYE_BAND : eyeY < groundY - EYE_BAND;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* One step of the crossing: `progress` moves toward `target` (0 or 1) in a straight line over
|
|
91
|
+
* `seconds`, and is exactly the target once it has arrived. `seconds <= 0` is instant.
|
|
92
|
+
*/
|
|
93
|
+
export function stepAmbianceProgress(progress, target, dt, seconds) {
|
|
94
|
+
if (seconds <= 0 || dt >= seconds)
|
|
95
|
+
return target;
|
|
96
|
+
const step = dt / seconds;
|
|
97
|
+
return target > progress ? Math.min(target, progress + step) : Math.max(target, progress - step);
|
|
98
|
+
}
|
|
99
|
+
/** The eased factor of a straight-line progress: slow in, slow out. */
|
|
100
|
+
export function easeAmbiance(progress) {
|
|
101
|
+
const p = Math.min(1, Math.max(0, progress));
|
|
102
|
+
return p * p * (3 - 2 * p);
|
|
103
|
+
}
|
|
104
|
+
// ── The shared factor ────────────────────────────────────────────────────────────────────────
|
|
105
|
+
const factorNode = uniform(0);
|
|
106
|
+
/**
|
|
107
|
+
* How far what is seen beyond the walls (the sky) has turned to earth, 0 to 1. The same as the
|
|
108
|
+
* factor in the overview; in the walkthrough the factor stays 0 (no fog, no vignette, the rooms'
|
|
109
|
+
* own light) and this one alone follows the eye under the ground.
|
|
110
|
+
*/
|
|
111
|
+
const earthNode = uniform(0);
|
|
112
|
+
/**
|
|
113
|
+
* How far the hole in the ground is open (0 closed, 1 open): over a level below grade seen from
|
|
114
|
+
* above, the ground stays solid and a hole with a noise-eroded edge opens over the below-grade
|
|
115
|
+
* footprint. Eased like the factor; 0 in a capture, whose own ground it keeps (see
|
|
116
|
+
* {@link temporarilyWithoutAmbiance}).
|
|
117
|
+
*/
|
|
118
|
+
const holeNode = uniform(0);
|
|
119
|
+
/**
|
|
120
|
+
* How much of the crossing is the noise mask: 1 the blobs of the dark world spreading, 0 the whole
|
|
121
|
+
* frame fading at once (`UndergroundTransition`). A uniform, so the two share one pipeline.
|
|
122
|
+
*/
|
|
123
|
+
const grainWeightNode = uniform(1);
|
|
124
|
+
let hole = 0;
|
|
125
|
+
let factor = 0;
|
|
126
|
+
let earth = 0;
|
|
127
|
+
let held = false;
|
|
128
|
+
/** The factor as shaders read it: zero while a capture holds the ambiance off. */
|
|
129
|
+
export function undergroundAmbianceNode() {
|
|
130
|
+
return factorNode;
|
|
131
|
+
}
|
|
132
|
+
/** How far the backdrop is the earth's, as shaders read it: zero while a capture holds the ambiance off. */
|
|
133
|
+
export function undergroundEarthNode() {
|
|
134
|
+
return earthNode;
|
|
135
|
+
}
|
|
136
|
+
/** How far the ground's hole is open, as shaders read it: 0 while a capture holds the world plain. */
|
|
137
|
+
export function groundHoleOpenNode() {
|
|
138
|
+
return holeNode;
|
|
139
|
+
}
|
|
140
|
+
/** How far the ground's hole is open now (0 while a capture holds the world plain). */
|
|
141
|
+
export function groundHoleOpenNow() {
|
|
142
|
+
return holeNode.value;
|
|
143
|
+
}
|
|
144
|
+
/** Sets how much the crossing is the noise mask (1) rather than a uniform fade (0); the system's word. */
|
|
145
|
+
export function setDiveGrainWeight(next) {
|
|
146
|
+
grainWeightNode.value = next;
|
|
147
|
+
}
|
|
148
|
+
/** Sets the live opening of the ground's hole (the system's word). */
|
|
149
|
+
export function setGroundHoleOpen(next) {
|
|
150
|
+
hole = next;
|
|
151
|
+
holeNode.value = held ? 0 : next;
|
|
152
|
+
}
|
|
153
|
+
/** The factor the shown frame wears now: the eased value, or `0` while a capture holds it off. */
|
|
154
|
+
export function ambianceNow() {
|
|
155
|
+
return held ? 0 : factor;
|
|
156
|
+
}
|
|
157
|
+
/** How far the backdrop is the earth's now: the eased value, or `0` while a capture holds it off. */
|
|
158
|
+
export function earthNow() {
|
|
159
|
+
return held ? 0 : earth;
|
|
160
|
+
}
|
|
161
|
+
/** Sets the live factor (the system's word); shaders and lights follow the held value. */
|
|
162
|
+
export function setAmbianceFactor(next) {
|
|
163
|
+
factor = next;
|
|
164
|
+
factorNode.value = held ? 0 : next;
|
|
165
|
+
}
|
|
166
|
+
/** Sets the live earth factor of the backdrop (the system's word). */
|
|
167
|
+
export function setEarthFactor(next) {
|
|
168
|
+
earth = next;
|
|
169
|
+
earthNode.value = held ? 0 : next;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The shown frame without the ambiance, for one capture: an agent's picture of a level below
|
|
173
|
+
* grade is read for its rooms, so it is taken in the world's own light, and the person's hole in
|
|
174
|
+
* the ground is not in it (a capture sets its own ground: the plain veil over a level below
|
|
175
|
+
* grade, solid for an exterior). The returned function gives the person's view back.
|
|
176
|
+
*/
|
|
177
|
+
export function temporarilyWithoutAmbiance() {
|
|
178
|
+
const wasHeld = held;
|
|
179
|
+
held = true;
|
|
180
|
+
factorNode.value = 0;
|
|
181
|
+
earthNode.value = 0;
|
|
182
|
+
holeNode.value = 0;
|
|
183
|
+
restoreSkyLights();
|
|
184
|
+
return () => {
|
|
185
|
+
held = wasHeld;
|
|
186
|
+
factorNode.value = held ? 0 : factor;
|
|
187
|
+
earthNode.value = held ? 0 : earth;
|
|
188
|
+
holeNode.value = held ? 0 : hole;
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// ── The shown level's box: where the world stays clear ──────────────────────────────────────
|
|
192
|
+
const focusMin = uniform(new Vector3(-20, -20, -20));
|
|
193
|
+
const focusMax = uniform(new Vector3(20, 20, 20));
|
|
194
|
+
/** The box the fog keeps clear: the shown level's, or a cube about the eye when none is shown. */
|
|
195
|
+
export function setAmbianceFocus(box, eye) {
|
|
196
|
+
if (box) {
|
|
197
|
+
focusMin.value.set(box.min[0], box.min[1], box.min[2]);
|
|
198
|
+
focusMax.value.set(box.max[0], box.max[1], box.max[2]);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const half = 20;
|
|
202
|
+
focusMin.value.set(eye.x - half, eye.y - half, eye.z - half);
|
|
203
|
+
focusMax.value.set(eye.x + half, eye.y + half, eye.z + half);
|
|
204
|
+
}
|
|
205
|
+
/** The box the fog keeps clear now (what {@link setAmbianceFocus} last set). */
|
|
206
|
+
export function ambianceFocus() {
|
|
207
|
+
return { min: focusMin.value.toArray(), max: focusMax.value.toArray() };
|
|
208
|
+
}
|
|
209
|
+
// ── The pipeline's pieces (TSL) ──────────────────────────────────────────────────────────────
|
|
210
|
+
/**
|
|
211
|
+
* The dark mode's backdrop for a view direction: the theme backdrop's own gradient, in the dark
|
|
212
|
+
* theme's colours. The fog dissolves into this same colour per pixel, so what is far leaves no seam.
|
|
213
|
+
*/
|
|
214
|
+
export function undergroundBackdrop(dirY) {
|
|
215
|
+
return backdropGradient({
|
|
216
|
+
dirY,
|
|
217
|
+
background: color(BACKDROP.background),
|
|
218
|
+
haze: color(BACKDROP.haze),
|
|
219
|
+
sky: color(BACKDROP.sky),
|
|
220
|
+
skyDeep: color(BACKDROP.skyDeep),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* How far a world position stands in the dark mode's fog, 0 to 1, from its distance outside the
|
|
225
|
+
* shown box (the box itself, and what stands close about it, stays clear). Not scaled by the
|
|
226
|
+
* factor: the pipeline weighs it with {@link undergroundDissolve}.
|
|
227
|
+
*/
|
|
228
|
+
export function undergroundFogAmount(worldPosition) {
|
|
229
|
+
const centre = focusMin.add(focusMax).mul(0.5);
|
|
230
|
+
const half = focusMax.sub(focusMin).mul(0.5);
|
|
231
|
+
const outside = max(abs(worldPosition.sub(centre)).sub(half), vec3(0)).length();
|
|
232
|
+
return smoothstep(float(FOG_START), float(FOG_END), outside).mul(FOG_CAP);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The noise the crossing's mask is cut from: two screen-space perlin octaves, 0 to 1. Computed once
|
|
236
|
+
* a pixel and handed to every {@link undergroundDissolve} that needs it.
|
|
237
|
+
*/
|
|
238
|
+
export function undergroundDissolveGrain(uv = screenUV) {
|
|
239
|
+
// Perlin is centred on 0 with a short spread: stretch it so the mask covers 0..1.
|
|
240
|
+
const grain = mx_noise_float(vec3(uv.mul(vec2(9, 5.8)), 0.37))
|
|
241
|
+
.mul(0.62)
|
|
242
|
+
.add(mx_noise_float(vec3(uv.mul(vec2(21, 13.5)), 1.91)).mul(0.22));
|
|
243
|
+
return clamp(grain.add(0.5), 0, 1);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The crossing as a noise mask closing over the screen: a per-pixel weight, 0 to 1, that goes
|
|
247
|
+
* from 0 everywhere at `amount` 0 (the factor, by default) to 1 everywhere at 1, through soft
|
|
248
|
+
* blobs of the dark world spreading (a fine perlin mask in screen space, not a cross-fade). Weighs
|
|
249
|
+
* the backdrop, the fog and the vignette; above and below the crossing it is exactly 0 and 1.
|
|
250
|
+
* With the simple fade chosen (`grainWeightNode` 0) it is `amount` itself, the same everywhere.
|
|
251
|
+
*/
|
|
252
|
+
export function undergroundDissolve(uv = screenUV, amount = factorNode, grain = undergroundDissolveGrain(uv)) {
|
|
253
|
+
const softness = 0.32;
|
|
254
|
+
const t = amount.mul(1 + 2 * softness).sub(softness);
|
|
255
|
+
return mix(amount, smoothstep(grain.sub(softness), grain.add(softness), t), grainWeightNode);
|
|
256
|
+
}
|
|
257
|
+
/** The world position of the pixel at `uv` from the scene pass's raw depth. */
|
|
258
|
+
export function worldPositionFromDepth(rawDepth, projectionInverse, cameraWorld, uv = screenUV) {
|
|
259
|
+
const viewPosition = getViewPosition(uv, rawDepth, projectionInverse);
|
|
260
|
+
return cameraWorld.mul(vec4(viewPosition, 1)).xyz;
|
|
261
|
+
}
|
|
262
|
+
/** The screen's edges closing in: 0 at the centre, 1 at the corners (weigh it with the dissolve). */
|
|
263
|
+
export function undergroundVignette(uv = screenUV) {
|
|
264
|
+
const radial = uv.sub(0.5).length().mul(2);
|
|
265
|
+
return smoothstep(float(0.55), float(1.45), radial).mul(VIGNETTE_STRENGTH);
|
|
266
|
+
}
|
|
267
|
+
let skyLightSource = null;
|
|
268
|
+
let saved = null;
|
|
269
|
+
const tint = new Color(TINT);
|
|
270
|
+
/** The lights the ambiance moves: `Lights` offers the sky's ambient and hemisphere and the eye's fill. */
|
|
271
|
+
export function registerSkyLights(source) {
|
|
272
|
+
skyLightSource = source;
|
|
273
|
+
return () => {
|
|
274
|
+
if (skyLightSource === source) {
|
|
275
|
+
restoreSkyLights();
|
|
276
|
+
skyLightSource = null;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Brings the sky's lights down and tints them by `amount`, and brings the eye's fill up, for the
|
|
282
|
+
* frame about to be drawn. Their neutral state is kept and given back by
|
|
283
|
+
* {@link restoreSkyLights} before the next frame lerps them, so the theme's own smoothing never
|
|
284
|
+
* fights the ambiance. With no ambiance (or none registered) the fill is simply set to its rest.
|
|
285
|
+
*/
|
|
286
|
+
export function applyAmbianceToSkyLights(amount) {
|
|
287
|
+
restoreSkyLights();
|
|
288
|
+
if (!skyLightSource)
|
|
289
|
+
return;
|
|
290
|
+
const { ambient, hemisphere, fill, fillRest } = skyLightSource();
|
|
291
|
+
saved = { fill: null, ambient: null, hemisphere: null };
|
|
292
|
+
if (fill) {
|
|
293
|
+
saved.fill = { light: fill, intensity: fillRest };
|
|
294
|
+
fill.intensity = fillRest + (EYE_FILL_INTENSITY - fillRest) * Math.max(0, amount);
|
|
295
|
+
}
|
|
296
|
+
if (amount <= 0)
|
|
297
|
+
return;
|
|
298
|
+
const scale = 1 + (SKY_LIGHT_SCALE - 1) * amount;
|
|
299
|
+
const warmth = SKY_LIGHT_TINT * amount;
|
|
300
|
+
if (ambient) {
|
|
301
|
+
saved.ambient = { light: ambient, intensity: ambient.intensity, color: ambient.color.clone() };
|
|
302
|
+
ambient.intensity *= scale;
|
|
303
|
+
ambient.color.lerp(tint, warmth);
|
|
304
|
+
}
|
|
305
|
+
if (hemisphere) {
|
|
306
|
+
saved.hemisphere = {
|
|
307
|
+
light: hemisphere,
|
|
308
|
+
intensity: hemisphere.intensity,
|
|
309
|
+
color: hemisphere.color.clone(),
|
|
310
|
+
groundColor: hemisphere.groundColor.clone(),
|
|
311
|
+
};
|
|
312
|
+
hemisphere.intensity *= scale;
|
|
313
|
+
hemisphere.color.lerp(tint, warmth);
|
|
314
|
+
hemisphere.groundColor.lerp(tint, warmth);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/** Gives the sky's lights back as the theme set them, and the eye's fill its rest. */
|
|
318
|
+
export function restoreSkyLights() {
|
|
319
|
+
if (!saved)
|
|
320
|
+
return;
|
|
321
|
+
const { fill, ambient, hemisphere } = saved;
|
|
322
|
+
saved = null;
|
|
323
|
+
if (fill)
|
|
324
|
+
fill.light.intensity = fill.intensity;
|
|
325
|
+
if (ambient) {
|
|
326
|
+
ambient.light.intensity = ambient.intensity;
|
|
327
|
+
ambient.light.color.copy(ambient.color);
|
|
328
|
+
}
|
|
329
|
+
if (hemisphere) {
|
|
330
|
+
hemisphere.light.intensity = hemisphere.intensity;
|
|
331
|
+
hemisphere.light.color.copy(hemisphere.color);
|
|
332
|
+
hemisphere.light.groundColor.copy(hemisphere.groundColor);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Ring } from '@pascal-app/core';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
type ZoneFootprint = {
|
|
4
|
+
polygon: Ring;
|
|
5
|
+
holes?: Ring[];
|
|
6
|
+
};
|
|
7
|
+
export declare function createZoneShape({ polygon, holes }: ZoneFootprint): THREE.Shape;
|
|
8
|
+
/** Vertical quads along each polygon edge (UV.y 0 at the floor, 1 at the top). */
|
|
9
|
+
export declare function createZoneWallGeometry(footprint: ZoneFootprint): THREE.BufferGeometry;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=zone-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zone-geometry.d.ts","sourceRoot":"","sources":["../../src/lib/zone-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,KAAK,aAAa,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CAAE,CAAA;AAItD,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,KAAU,EAAE,EAAE,aAAa,GAAG,KAAK,CAAC,KAAK,CAiBnF;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,aAAa,GAAG,KAAK,CAAC,cAAc,CAiCrF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
const Y_OFFSET = 0.01;
|
|
3
|
+
const ZONE_WALL_HEIGHT = 2.3;
|
|
4
|
+
export function createZoneShape({ polygon, holes = [] }) {
|
|
5
|
+
const shape = new THREE.Shape();
|
|
6
|
+
const draw = (path, ring) => {
|
|
7
|
+
ring.forEach(([x, z], i) => {
|
|
8
|
+
if (i === 0)
|
|
9
|
+
path.moveTo(x, -z);
|
|
10
|
+
else
|
|
11
|
+
path.lineTo(x, -z);
|
|
12
|
+
});
|
|
13
|
+
path.closePath();
|
|
14
|
+
};
|
|
15
|
+
draw(shape, polygon);
|
|
16
|
+
for (const ring of holes) {
|
|
17
|
+
if (ring.length < 3)
|
|
18
|
+
continue;
|
|
19
|
+
const path = new THREE.Path();
|
|
20
|
+
draw(path, ring);
|
|
21
|
+
shape.holes.push(path);
|
|
22
|
+
}
|
|
23
|
+
return shape;
|
|
24
|
+
}
|
|
25
|
+
/** Vertical quads along each polygon edge (UV.y 0 at the floor, 1 at the top). */
|
|
26
|
+
export function createZoneWallGeometry(footprint) {
|
|
27
|
+
const positions = [];
|
|
28
|
+
const uvs = [];
|
|
29
|
+
const indices = [];
|
|
30
|
+
for (const polygon of [footprint.polygon, ...(footprint.holes ?? [])]) {
|
|
31
|
+
for (let i = 0; i < polygon.length; i++) {
|
|
32
|
+
const [cx, cz] = polygon[i];
|
|
33
|
+
const [nx, nz] = polygon[(i + 1) % polygon.length];
|
|
34
|
+
const base = positions.length / 3;
|
|
35
|
+
positions.push(cx, Y_OFFSET, cz, nx, Y_OFFSET, nz, nx, Y_OFFSET + ZONE_WALL_HEIGHT, nz, cx, Y_OFFSET + ZONE_WALL_HEIGHT, cz);
|
|
36
|
+
uvs.push(0, 0, 1, 0, 1, 1, 0, 1);
|
|
37
|
+
indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const geometry = new THREE.BufferGeometry();
|
|
41
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
|
42
|
+
geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
|
|
43
|
+
geometry.setIndex(indices);
|
|
44
|
+
geometry.computeVertexNormals();
|
|
45
|
+
return geometry;
|
|
46
|
+
}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type AnyNodeId, type Interactive, type LightEffect } from '@pascal-app/core';
|
|
2
|
+
import type { Object3D, Vector3 } from 'three';
|
|
3
|
+
export type LightSource = {
|
|
4
|
+
key: string;
|
|
3
5
|
nodeId: AnyNodeId;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
hasSlider: boolean;
|
|
6
|
+
color: string;
|
|
7
|
+
distance: number;
|
|
8
|
+
getWorldPosition: (out: Vector3) => boolean;
|
|
9
|
+
getIntensity: () => number;
|
|
10
|
+
isEligible: () => boolean;
|
|
10
11
|
};
|
|
12
|
+
export declare function catalogLightSource(key: string, nodeId: AnyNodeId, effect: LightEffect, interactive: Interactive, localScale?: readonly [number, number, number]): LightSource;
|
|
11
13
|
type ItemLightPoolStore = {
|
|
12
|
-
registrations: Map<string,
|
|
13
|
-
|
|
14
|
+
registrations: Map<string, LightSource>;
|
|
15
|
+
bakedCanvases: Set<Object3D>;
|
|
16
|
+
setBakedCanvas: (scene: Object3D, active: boolean) => void;
|
|
17
|
+
register: (source: LightSource) => void;
|
|
14
18
|
unregister: (key: string) => void;
|
|
15
19
|
};
|
|
16
20
|
export declare const useItemLightPool: import("zustand").UseBoundStore<import("zustand").StoreApi<ItemLightPoolStore>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-item-light-pool.d.ts","sourceRoot":"","sources":["../../src/store/use-item-light-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"use-item-light-pool.d.ts","sourceRoot":"","sources":["../../src/store/use-item-light-pool.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAIjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAG9C,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,SAAS,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAA;IAC3C,YAAY,EAAE,MAAM,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,OAAO,CAAA;CAC1B,CAAA;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC7C,WAAW,CAwCb;AAED,KAAK,kBAAkB,GAAG;IACxB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACvC,aAAa,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC5B,cAAc,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1D,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;IACvC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC,CAAA;AAED,eAAO,MAAM,gBAAgB,iFAkB1B,CAAA"}
|