@3driseai/3drise-viewer 0.1.40 → 0.1.41
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/animationsV2/ClipsRuntime.d.ts.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +9 -5
- package/dist/animationsV2/clipUtils.d.ts +9 -0
- package/dist/animationsV2/clipUtils.d.ts.map +1 -1
- package/dist/animationsV2/clipUtils.js +11 -2
- package/dist/animationsV2/normalize.d.ts.map +1 -1
- package/dist/animationsV2/normalize.js +2 -0
- package/dist/animationsV2/types.d.ts +4 -0
- package/dist/animationsV2/types.d.ts.map +1 -1
- package/dist/api/sceneHandle.d.ts +40 -3
- package/dist/api/sceneHandle.d.ts.map +1 -1
- package/dist/api/sceneHandle.js +40 -0
- package/dist/components/GalleryObject.d.ts +13 -0
- package/dist/components/GalleryObject.d.ts.map +1 -0
- package/dist/components/GalleryObject.js +46 -0
- package/dist/components/ImageObject.d.ts +9 -0
- package/dist/components/ImageObject.d.ts.map +1 -0
- package/dist/components/ImageObject.js +26 -0
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +11 -5
- package/dist/components/ProjectLoader.d.ts +2 -0
- package/dist/components/ProjectLoader.d.ts.map +1 -1
- package/dist/components/ProjectLoader.js +2 -2
- package/dist/components/SceneBuilder.d.ts +10 -0
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SceneBuilder.js +3 -2
- package/dist/components/gallery/BasicCarouselGallery.d.ts +18 -0
- package/dist/components/gallery/BasicCarouselGallery.d.ts.map +1 -0
- package/dist/components/gallery/BasicCarouselGallery.js +9 -0
- package/dist/components/gallery/ContourLinesGallery.d.ts +18 -0
- package/dist/components/gallery/ContourLinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/ContourLinesGallery.js +9 -0
- package/dist/components/gallery/DepthLayersGallery.d.ts +18 -0
- package/dist/components/gallery/DepthLayersGallery.d.ts.map +1 -0
- package/dist/components/gallery/DepthLayersGallery.js +9 -0
- package/dist/components/gallery/EngravingGallery.d.ts +18 -0
- package/dist/components/gallery/EngravingGallery.d.ts.map +1 -0
- package/dist/components/gallery/EngravingGallery.js +9 -0
- package/dist/components/gallery/FlowLinesGallery.d.ts +18 -0
- package/dist/components/gallery/FlowLinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/FlowLinesGallery.js +9 -0
- package/dist/components/gallery/FoldGallery.d.ts +18 -0
- package/dist/components/gallery/FoldGallery.d.ts.map +1 -0
- package/dist/components/gallery/FoldGallery.js +9 -0
- package/dist/components/gallery/GlassPanesGallery.d.ts +18 -0
- package/dist/components/gallery/GlassPanesGallery.d.ts.map +1 -0
- package/dist/components/gallery/GlassPanesGallery.js +9 -0
- package/dist/components/gallery/HaloGallery.d.ts +18 -0
- package/dist/components/gallery/HaloGallery.d.ts.map +1 -0
- package/dist/components/gallery/HaloGallery.js +9 -0
- package/dist/components/gallery/LightThreadsGallery.d.ts +18 -0
- package/dist/components/gallery/LightThreadsGallery.d.ts.map +1 -0
- package/dist/components/gallery/LightThreadsGallery.js +9 -0
- package/dist/components/gallery/LoomGallery.d.ts +18 -0
- package/dist/components/gallery/LoomGallery.d.ts.map +1 -0
- package/dist/components/gallery/LoomGallery.js +9 -0
- package/dist/components/gallery/PaperLanternsGallery.d.ts +18 -0
- package/dist/components/gallery/PaperLanternsGallery.d.ts.map +1 -0
- package/dist/components/gallery/PaperLanternsGallery.js +9 -0
- package/dist/components/gallery/ParticleShiftGallery.d.ts +18 -0
- package/dist/components/gallery/ParticleShiftGallery.d.ts.map +1 -0
- package/dist/components/gallery/ParticleShiftGallery.js +9 -0
- package/dist/components/gallery/PinscreenGallery.d.ts +18 -0
- package/dist/components/gallery/PinscreenGallery.d.ts.map +1 -0
- package/dist/components/gallery/PinscreenGallery.js +9 -0
- package/dist/components/gallery/PopUpGallery.d.ts +18 -0
- package/dist/components/gallery/PopUpGallery.d.ts.map +1 -0
- package/dist/components/gallery/PopUpGallery.js +9 -0
- package/dist/components/gallery/PrismSplitGallery.d.ts +18 -0
- package/dist/components/gallery/PrismSplitGallery.d.ts.map +1 -0
- package/dist/components/gallery/PrismSplitGallery.js +9 -0
- package/dist/components/gallery/RidgelinesGallery.d.ts +18 -0
- package/dist/components/gallery/RidgelinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/RidgelinesGallery.js +9 -0
- package/dist/components/gallery/ShadowBoxGallery.d.ts +18 -0
- package/dist/components/gallery/ShadowBoxGallery.d.ts.map +1 -0
- package/dist/components/gallery/ShadowBoxGallery.js +9 -0
- package/dist/components/gallery/SilkGallery.d.ts +18 -0
- package/dist/components/gallery/SilkGallery.d.ts.map +1 -0
- package/dist/components/gallery/SilkGallery.js +9 -0
- package/dist/components/gallery/SlatsGallery.d.ts +18 -0
- package/dist/components/gallery/SlatsGallery.d.ts.map +1 -0
- package/dist/components/gallery/SlatsGallery.js +9 -0
- package/dist/components/gallery/StrataGallery.d.ts +18 -0
- package/dist/components/gallery/StrataGallery.d.ts.map +1 -0
- package/dist/components/gallery/StrataGallery.js +9 -0
- package/dist/components/gallery/TerracesGallery.d.ts +18 -0
- package/dist/components/gallery/TerracesGallery.d.ts.map +1 -0
- package/dist/components/gallery/TerracesGallery.js +9 -0
- package/dist/components/gallery/WireReliefGallery.d.ts +18 -0
- package/dist/components/gallery/WireReliefGallery.d.ts.map +1 -0
- package/dist/components/gallery/WireReliefGallery.js +9 -0
- package/dist/components/gallery/index.d.ts +46 -0
- package/dist/components/gallery/index.d.ts.map +1 -0
- package/dist/components/gallery/index.js +22 -0
- package/dist/components/gallery/kit/GalleryVariant.d.ts +68 -0
- package/dist/components/gallery/kit/GalleryVariant.d.ts.map +1 -0
- package/dist/components/gallery/kit/GalleryVariant.js +231 -0
- package/dist/components/gallery/kit/feeds.d.ts +7 -0
- package/dist/components/gallery/kit/feeds.d.ts.map +1 -0
- package/dist/components/gallery/kit/feeds.js +83 -0
- package/dist/components/gallery/kit/galleryKit.d.ts +118 -0
- package/dist/components/gallery/kit/galleryKit.d.ts.map +1 -0
- package/dist/components/gallery/kit/galleryKit.js +298 -0
- package/dist/components/gallery/kit/lookBase.d.ts +157 -0
- package/dist/components/gallery/kit/lookBase.d.ts.map +1 -0
- package/dist/components/gallery/kit/lookBase.js +211 -0
- package/dist/components/gallery/kit/pictures.d.ts +14 -0
- package/dist/components/gallery/kit/pictures.d.ts.map +1 -0
- package/dist/components/gallery/kit/pictures.js +81 -0
- package/dist/components/gallery/looks/basicCarousel.d.ts +177 -0
- package/dist/components/gallery/looks/basicCarousel.d.ts.map +1 -0
- package/dist/components/gallery/looks/basicCarousel.js +315 -0
- package/dist/components/gallery/looks/contourLines.d.ts +153 -0
- package/dist/components/gallery/looks/contourLines.d.ts.map +1 -0
- package/dist/components/gallery/looks/contourLines.js +91 -0
- package/dist/components/gallery/looks/depthLayers.d.ts +155 -0
- package/dist/components/gallery/looks/depthLayers.d.ts.map +1 -0
- package/dist/components/gallery/looks/depthLayers.js +87 -0
- package/dist/components/gallery/looks/engraving.d.ts +162 -0
- package/dist/components/gallery/looks/engraving.d.ts.map +1 -0
- package/dist/components/gallery/looks/engraving.js +96 -0
- package/dist/components/gallery/looks/flowLines.d.ts +180 -0
- package/dist/components/gallery/looks/flowLines.d.ts.map +1 -0
- package/dist/components/gallery/looks/flowLines.js +113 -0
- package/dist/components/gallery/looks/fold.d.ts +209 -0
- package/dist/components/gallery/looks/fold.d.ts.map +1 -0
- package/dist/components/gallery/looks/fold.js +155 -0
- package/dist/components/gallery/looks/glassPanes.d.ts +133 -0
- package/dist/components/gallery/looks/glassPanes.d.ts.map +1 -0
- package/dist/components/gallery/looks/glassPanes.js +208 -0
- package/dist/components/gallery/looks/halo.d.ts +100 -0
- package/dist/components/gallery/looks/halo.d.ts.map +1 -0
- package/dist/components/gallery/looks/halo.js +119 -0
- package/dist/components/gallery/looks/lightThreads.d.ts +199 -0
- package/dist/components/gallery/looks/lightThreads.d.ts.map +1 -0
- package/dist/components/gallery/looks/lightThreads.js +246 -0
- package/dist/components/gallery/looks/loom.d.ts +238 -0
- package/dist/components/gallery/looks/loom.d.ts.map +1 -0
- package/dist/components/gallery/looks/loom.js +256 -0
- package/dist/components/gallery/looks/paperLanterns.d.ts +181 -0
- package/dist/components/gallery/looks/paperLanterns.d.ts.map +1 -0
- package/dist/components/gallery/looks/paperLanterns.js +399 -0
- package/dist/components/gallery/looks/particleShift.d.ts +193 -0
- package/dist/components/gallery/looks/particleShift.d.ts.map +1 -0
- package/dist/components/gallery/looks/particleShift.js +282 -0
- package/dist/components/gallery/looks/pinscreen.d.ts +175 -0
- package/dist/components/gallery/looks/pinscreen.d.ts.map +1 -0
- package/dist/components/gallery/looks/pinscreen.js +96 -0
- package/dist/components/gallery/looks/popUp.d.ts +206 -0
- package/dist/components/gallery/looks/popUp.d.ts.map +1 -0
- package/dist/components/gallery/looks/popUp.js +132 -0
- package/dist/components/gallery/looks/prismSplit.d.ts +151 -0
- package/dist/components/gallery/looks/prismSplit.d.ts.map +1 -0
- package/dist/components/gallery/looks/prismSplit.js +84 -0
- package/dist/components/gallery/looks/ridgelines.d.ts +179 -0
- package/dist/components/gallery/looks/ridgelines.d.ts.map +1 -0
- package/dist/components/gallery/looks/ridgelines.js +111 -0
- package/dist/components/gallery/looks/shadowBox.d.ts +152 -0
- package/dist/components/gallery/looks/shadowBox.d.ts.map +1 -0
- package/dist/components/gallery/looks/shadowBox.js +82 -0
- package/dist/components/gallery/looks/silk.d.ts +140 -0
- package/dist/components/gallery/looks/silk.d.ts.map +1 -0
- package/dist/components/gallery/looks/silk.js +346 -0
- package/dist/components/gallery/looks/slats.d.ts +176 -0
- package/dist/components/gallery/looks/slats.d.ts.map +1 -0
- package/dist/components/gallery/looks/slats.js +93 -0
- package/dist/components/gallery/looks/strata.d.ts +172 -0
- package/dist/components/gallery/looks/strata.d.ts.map +1 -0
- package/dist/components/gallery/looks/strata.js +88 -0
- package/dist/components/gallery/looks/terraces.d.ts +168 -0
- package/dist/components/gallery/looks/terraces.d.ts.map +1 -0
- package/dist/components/gallery/looks/terraces.js +91 -0
- package/dist/components/gallery/looks/wireRelief.d.ts +153 -0
- package/dist/components/gallery/looks/wireRelief.d.ts.map +1 -0
- package/dist/components/gallery/looks/wireRelief.js +128 -0
- package/dist/components/image/ContourImage.d.ts +7 -0
- package/dist/components/image/ContourImage.d.ts.map +1 -0
- package/dist/components/image/ContourImage.js +6 -0
- package/dist/components/image/EngravingImage.d.ts +7 -0
- package/dist/components/image/EngravingImage.d.ts.map +1 -0
- package/dist/components/image/EngravingImage.js +6 -0
- package/dist/components/image/FrostImage.d.ts +7 -0
- package/dist/components/image/FrostImage.d.ts.map +1 -0
- package/dist/components/image/FrostImage.js +6 -0
- package/dist/components/image/LenticularImage.d.ts +7 -0
- package/dist/components/image/LenticularImage.d.ts.map +1 -0
- package/dist/components/image/LenticularImage.js +6 -0
- package/dist/components/image/PinscreenImage.d.ts +7 -0
- package/dist/components/image/PinscreenImage.d.ts.map +1 -0
- package/dist/components/image/PinscreenImage.js +6 -0
- package/dist/components/image/PrismImage.d.ts +7 -0
- package/dist/components/image/PrismImage.d.ts.map +1 -0
- package/dist/components/image/PrismImage.js +6 -0
- package/dist/components/image/ProjectorImage.d.ts +7 -0
- package/dist/components/image/ProjectorImage.d.ts.map +1 -0
- package/dist/components/image/ProjectorImage.js +6 -0
- package/dist/components/image/ReliefImage.d.ts +7 -0
- package/dist/components/image/ReliefImage.d.ts.map +1 -0
- package/dist/components/image/ReliefImage.js +6 -0
- package/dist/components/image/RollImage.d.ts +7 -0
- package/dist/components/image/RollImage.d.ts.map +1 -0
- package/dist/components/image/RollImage.js +6 -0
- package/dist/components/image/ShardsImage.d.ts +126 -0
- package/dist/components/image/ShardsImage.d.ts.map +1 -0
- package/dist/components/image/ShardsImage.js +470 -0
- package/dist/components/image/core/contour.d.ts +126 -0
- package/dist/components/image/core/contour.d.ts.map +1 -0
- package/dist/components/image/core/contour.js +123 -0
- package/dist/components/image/core/engraving.d.ts +135 -0
- package/dist/components/image/core/engraving.d.ts.map +1 -0
- package/dist/components/image/core/engraving.js +163 -0
- package/dist/components/image/core/frost.d.ts +126 -0
- package/dist/components/image/core/frost.d.ts.map +1 -0
- package/dist/components/image/core/frost.js +156 -0
- package/dist/components/image/core/imageCore.d.ts +110 -0
- package/dist/components/image/core/imageCore.d.ts.map +1 -0
- package/dist/components/image/core/imageCore.js +269 -0
- package/dist/components/image/core/lenticular.d.ts +129 -0
- package/dist/components/image/core/lenticular.d.ts.map +1 -0
- package/dist/components/image/core/lenticular.js +132 -0
- package/dist/components/image/core/pinscreen.d.ts +126 -0
- package/dist/components/image/core/pinscreen.d.ts.map +1 -0
- package/dist/components/image/core/pinscreen.js +147 -0
- package/dist/components/image/core/prism.d.ts +120 -0
- package/dist/components/image/core/prism.d.ts.map +1 -0
- package/dist/components/image/core/prism.js +164 -0
- package/dist/components/image/core/projector.d.ts +135 -0
- package/dist/components/image/core/projector.d.ts.map +1 -0
- package/dist/components/image/core/projector.js +225 -0
- package/dist/components/image/core/relief.d.ts +111 -0
- package/dist/components/image/core/relief.d.ts.map +1 -0
- package/dist/components/image/core/relief.js +94 -0
- package/dist/components/image/core/roll.d.ts +114 -0
- package/dist/components/image/core/roll.d.ts.map +1 -0
- package/dist/components/image/core/roll.js +116 -0
- package/dist/components/image/imageVariant.d.ts +46 -0
- package/dist/components/image/imageVariant.d.ts.map +1 -0
- package/dist/components/image/imageVariant.js +128 -0
- package/dist/components/image/index.d.ts +22 -0
- package/dist/components/image/index.d.ts.map +1 -0
- package/dist/components/image/index.js +10 -0
- package/dist/components/image/pictureCycle.d.ts +15 -0
- package/dist/components/image/pictureCycle.d.ts.map +1 -0
- package/dist/components/image/pictureCycle.js +82 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +9 -7
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
- package/dist/components/volumetricClouds/VolumetricCloudsPass.js +39 -27
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/galleryRuntime.d.ts +57 -0
- package/dist/galleryRuntime.d.ts.map +1 -0
- package/dist/galleryRuntime.js +105 -0
- package/dist/hooks/useConfigLive.d.ts +1 -1
- package/dist/hooks/useConfigLive.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/keyPad/KeyPadControls.d.ts +16 -0
- package/dist/keyPad/KeyPadControls.d.ts.map +1 -0
- package/dist/keyPad/KeyPadControls.js +176 -0
- package/dist/keyPad/index.d.ts +16 -0
- package/dist/keyPad/index.d.ts.map +1 -0
- package/dist/keyPad/index.js +8 -0
- package/dist/keyPad/keyBindings.d.ts +43 -0
- package/dist/keyPad/keyBindings.d.ts.map +1 -0
- package/dist/keyPad/keyBindings.js +92 -0
- package/dist/keyPad/keyPadAnimation.d.ts +28 -0
- package/dist/keyPad/keyPadAnimation.d.ts.map +1 -0
- package/dist/keyPad/keyPadAnimation.js +131 -0
- package/dist/keyPad/keyPadMotion.d.ts +68 -0
- package/dist/keyPad/keyPadMotion.d.ts.map +1 -0
- package/dist/keyPad/keyPadMotion.js +283 -0
- package/dist/keyPad/keyPadStore.d.ts +25 -0
- package/dist/keyPad/keyPadStore.d.ts.map +1 -0
- package/dist/keyPad/keyPadStore.js +63 -0
- package/dist/keyPad/types.d.ts +23 -0
- package/dist/keyPad/types.d.ts.map +1 -0
- package/dist/keyPad/types.js +9 -0
- package/dist/operations/catalogue/visibility.d.ts.map +1 -1
- package/dist/operations/catalogue/visibility.js +23 -1
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts +2 -1
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudResolveMaterial.js +37 -12
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +4 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudVolumeMaterial.js +15 -3
- package/dist/triggers/kinds/gallery.d.ts +2 -0
- package/dist/triggers/kinds/gallery.d.ts.map +1 -0
- package/dist/triggers/kinds/gallery.js +39 -0
- package/dist/triggers/kinds/index.d.ts +1 -0
- package/dist/triggers/kinds/index.d.ts.map +1 -1
- package/dist/triggers/kinds/index.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// GENERATED from the lab (Claude outputs/gallery-lab/image/frost.mjs) by emit_image.mjs — change the lab and re-emit.
|
|
2
|
+
// frost — an image variant (type 'image', config.type 'frost'). Materials: the print is a MeshStandardMaterial,
|
|
3
|
+
// the pane in front of it a MeshPhysicalMaterial with transmission (both lit by the scene; object effects attach).
|
|
4
|
+
//
|
|
5
|
+
// A print behind a pane of real glass, a small gap between them. Frost on the glass is the glass's own
|
|
6
|
+
// roughness: three's transmission samples the scene behind the pane through a blur that grows with roughness, so
|
|
7
|
+
// frosted glass genuinely blurs the print (and anything behind it), refracted through the pane's thickness, and
|
|
8
|
+
// clear glass shows it sharp with the scene's highlights on top. A change is a breath on the glass: frost
|
|
9
|
+
// crystallises in from the edges (a front shaped by distance to the edge and a dendritic ridged-noise field, so it
|
|
10
|
+
// grows in feathers, not a fade), the print changes behind the fully frosted pane, and the frost clears from the
|
|
11
|
+
// centre outward. Idle: a fine rim of frost stays at the edges and breathes. Cursor: `wipe` — a finger wipes the
|
|
12
|
+
// glass clear along its path and it frosts back over a few seconds; `fog` — the cursor breathes frost onto it.
|
|
13
|
+
import * as THREE from 'three';
|
|
14
|
+
import { baseUniforms, applyBase, setU, createPicture, stepPointer, patchMaterial, depthTwin } from './imageCore.js';
|
|
15
|
+
export const POINTER_MODES = ['wipe', 'fog'];
|
|
16
|
+
const TRAIL = 24;
|
|
17
|
+
export const STRUCTURAL = ['imageUrls'];
|
|
18
|
+
export function createUniforms() {
|
|
19
|
+
return { ...baseUniforms(), uFrost: { value: 0.75 }, uWhite: { value: 0.25 }, uFeather: { value: 0.6 }, uRim: { value: 0.25 }, uSelf: { value: 0.12 },
|
|
20
|
+
uFrostColor: { value: new THREE.Color('#eef3f8') }, uTrail: { value: Array.from({ length: TRAIL }, () => new THREE.Vector3(0, 0, 99)) }, uRefrost: { value: 3 } };
|
|
21
|
+
}
|
|
22
|
+
export function applyConfig(u, c) {
|
|
23
|
+
applyBase(u, c, POINTER_MODES);
|
|
24
|
+
setU(u, 'uFrost', c.frost);
|
|
25
|
+
setU(u, 'uWhite', c.whiteness);
|
|
26
|
+
setU(u, 'uFeather', c.feather);
|
|
27
|
+
setU(u, 'uRim', c.rim);
|
|
28
|
+
setU(u, 'uSelf', c.selfLight);
|
|
29
|
+
setU(u, 'uFrostColor', c.frostColor);
|
|
30
|
+
setU(u, 'uRefrost', c.refrost);
|
|
31
|
+
}
|
|
32
|
+
// ---- the print
|
|
33
|
+
const printPars = /* glsl */ `
|
|
34
|
+
uniform float uSelf; varying vec2 vPic;
|
|
35
|
+
`;
|
|
36
|
+
const printVertex = /* glsl */ `
|
|
37
|
+
fxP = vec3(position.xy * uSize, 0.0);
|
|
38
|
+
vPic = position.xy + 0.5;
|
|
39
|
+
`;
|
|
40
|
+
const printDiffuse = /* glsl */ `
|
|
41
|
+
float sw = smoothstep(0.4, 0.6, uP); // behind the fully frosted glass
|
|
42
|
+
diffuseColor.rgb = mix(picA(vPic), picB(vPic), sw) * uIntensity;
|
|
43
|
+
diffuseColor.a *= uOpacity;
|
|
44
|
+
`;
|
|
45
|
+
const printEmissive = /* glsl */ ` totalEmissiveRadiance += diffuseColor.rgb * uSelf;\n`;
|
|
46
|
+
// ---- the pane
|
|
47
|
+
const panePars = /* glsl */ `
|
|
48
|
+
uniform float uFrost, uWhite, uFeather, uRim, uRefrost; uniform vec3 uFrostColor; uniform vec3 uTrail[${TRAIL}];
|
|
49
|
+
varying vec2 vPic;
|
|
50
|
+
float ridged(vec2 p){ float s = 0.0, a = 0.5; for (int i = 0; i < 4; i++){ s += a * (1.0 - abs(2.0 * vnoise(p) - 1.0)); p = mat2(1.6, 1.2, -1.2, 1.6) * p + 3.1; a *= 0.5; } return s; }
|
|
51
|
+
// frost coverage 0..1 at uv: a front in 'reach' (edge distance + feathers) driven by the breath of the change
|
|
52
|
+
float frostAt(vec2 uv, out float crystal){
|
|
53
|
+
vec2 q = (uv - 0.5) * uSize;
|
|
54
|
+
vec2 hs = 0.5 * uSize;
|
|
55
|
+
float box = min(hs.x - abs(q.x), hs.y - abs(q.y)) / min(hs.x, hs.y);
|
|
56
|
+
float oval = 1.0 - length(q / hs);
|
|
57
|
+
float edge = clamp(mix(box, oval, 0.6), 0.0, 1.0); // 0 at the edge, ~1 at the centre (rounded)
|
|
58
|
+
crystal = ridged(q * 9.0);
|
|
59
|
+
float reach = edge * 0.8 + uFeather * 0.45 * (crystal - 0.45) + 0.06;
|
|
60
|
+
float breath = pow(sin(PI * uP), 0.8) * 1.05;
|
|
61
|
+
float rest = uRim * (0.32 + 0.02 * uBreathe * sin(uTime * 0.6 + q.x));
|
|
62
|
+
float a = max(breath, rest);
|
|
63
|
+
float F = smoothstep(reach - 0.05, reach + 0.05, a);
|
|
64
|
+
// the wiped trail frosts back over uRefrost seconds
|
|
65
|
+
float wipe = 0.0;
|
|
66
|
+
if (uPointerMode > -0.5 && uPointerMode < 0.5) {
|
|
67
|
+
for (int i = 0; i < ${TRAIL}; i++) {
|
|
68
|
+
vec3 t = uTrail[i];
|
|
69
|
+
float age = t.z / max(uRefrost, 0.1);
|
|
70
|
+
if (age < 1.0) { float d = length(q - t.xy) / max(uPointerRadius, 1e-3); wipe = max(wipe, (1.0 - smoothstep(0.55, 1.0, d)) * (1.0 - age * age) * uPointerStrength); }
|
|
71
|
+
}
|
|
72
|
+
F *= 1.0 - clamp(wipe, 0.0, 1.0);
|
|
73
|
+
} else if (uPointerMode > 0.5) F = max(F, smoothstep(0.0, 0.7, pointerBump(q)) * smoothstep(reach - 0.3, reach + 0.1, 0.9));
|
|
74
|
+
return F;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
const paneVertex = /* glsl */ `
|
|
78
|
+
fxP = vec3(position.xy * uSize, 0.0);
|
|
79
|
+
vPic = position.xy + 0.5;
|
|
80
|
+
`;
|
|
81
|
+
const paneDiffuse = /* glsl */ `
|
|
82
|
+
float crystal; float F = frostAt(vPic, crystal);
|
|
83
|
+
diffuseColor.rgb = uFrostColor;
|
|
84
|
+
diffuseColor.a *= uOpacity;
|
|
85
|
+
`;
|
|
86
|
+
const paneRough = /* glsl */ `
|
|
87
|
+
{ float crystal; float F = frostAt(vPic, crystal);
|
|
88
|
+
roughnessFactor = mix(0.03, 0.18 + 0.5 * uFrost * (0.75 + 0.35 * crystal), F * uFrost); }
|
|
89
|
+
`;
|
|
90
|
+
const paneNormal = /* glsl */ `
|
|
91
|
+
{ float crystal; float F = frostAt(vPic, crystal);
|
|
92
|
+
vec2 g = vec2(dFdx(crystal), dFdy(crystal));
|
|
93
|
+
normal = normalize(normal + vec3(g * 1.2, 0.0) * F * uFeather); }
|
|
94
|
+
`;
|
|
95
|
+
export function build(u, c) {
|
|
96
|
+
const object = new THREE.Group();
|
|
97
|
+
const geo = new THREE.PlaneGeometry(1, 1, 1, 1);
|
|
98
|
+
// print
|
|
99
|
+
const PP = { key: 'frost-print', uniforms: u, pars: printPars, vertex: printVertex, diffuse: printDiffuse, emissive: printEmissive };
|
|
100
|
+
const printMat = patchMaterial(new THREE.MeshStandardMaterial({ roughness: 0.7 }), PP);
|
|
101
|
+
const print = new THREE.Mesh(geo, printMat);
|
|
102
|
+
print.castShadow = true;
|
|
103
|
+
print.receiveShadow = true;
|
|
104
|
+
print.frustumCulled = false;
|
|
105
|
+
print.customDepthMaterial = depthTwin(PP);
|
|
106
|
+
// pane: transmission (the frost is its roughness); the frost's white scatter lowers transmission where it lies
|
|
107
|
+
const PG = { key: 'frost-pane', uniforms: u, pars: panePars, vertex: paneVertex, diffuse: paneDiffuse, roughness: paneRough, normalFrag: paneNormal };
|
|
108
|
+
const paneMat = patchMaterial(new THREE.MeshPhysicalMaterial({ transmission: 1, thickness: 0.03, ior: 1.5, roughness: 0.05, metalness: 0, specularIntensity: 1 }), PG);
|
|
109
|
+
const own = paneMat.onBeforeCompile;
|
|
110
|
+
paneMat.onBeforeCompile = (sh, r) => {
|
|
111
|
+
own(sh, r);
|
|
112
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <transmission_fragment>', THREE.ShaderChunk.transmission_fragment.replace('material.transmission = transmission;', 'float crystalT; float FT = frostAt(vPic, crystalT);\n\tmaterial.transmission = transmission * (1.0 - uWhite * 0.75 * FT * uFrost * (0.7 + 0.3 * crystalT));'));
|
|
113
|
+
};
|
|
114
|
+
const pane = new THREE.Mesh(geo, paneMat);
|
|
115
|
+
pane.frustumCulled = false;
|
|
116
|
+
pane.renderOrder = 2;
|
|
117
|
+
object.add(print, pane);
|
|
118
|
+
const cfg = { ...c };
|
|
119
|
+
const pic = createPicture(u, cfg);
|
|
120
|
+
const pst = {}, trail = u.uTrail.value;
|
|
121
|
+
let trailHead = 0, trailT = 0, last = null;
|
|
122
|
+
const api = {
|
|
123
|
+
object, materials: [printMat, paneMat],
|
|
124
|
+
controls: { show: (t) => pic.show(t), get busy() { return pic.busy; }, pic },
|
|
125
|
+
apply(k) { Object.assign(cfg, k); applyConfig(u, k); if (k.opacity !== undefined) {
|
|
126
|
+
printMat.transparent = k.opacity < 1;
|
|
127
|
+
} },
|
|
128
|
+
update(dt, pointer) {
|
|
129
|
+
dt = Math.min(dt, 0.1);
|
|
130
|
+
u.uTime.value += dt;
|
|
131
|
+
pic.step(dt);
|
|
132
|
+
stepPointer(u, pointer, dt, pst);
|
|
133
|
+
pane.position.z = cfg.gap;
|
|
134
|
+
for (const t of trail)
|
|
135
|
+
t.z += dt;
|
|
136
|
+
trailT += dt;
|
|
137
|
+
if (pointer && cfg.pointerMode === 'wipe') {
|
|
138
|
+
const moved = !last || Math.hypot(pointer.x - last.x, pointer.y - last.y) > 0.025;
|
|
139
|
+
if (moved && trailT > 0.016) {
|
|
140
|
+
trail[trailHead].set(pointer.x, pointer.y, 0);
|
|
141
|
+
trailHead = (trailHead + 1) % TRAIL;
|
|
142
|
+
trailT = 0;
|
|
143
|
+
last = { x: pointer.x, y: pointer.y };
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const prevI = (trailHead - 1 + TRAIL) % TRAIL;
|
|
147
|
+
trail[prevI].z = Math.min(trail[prevI].z, 0);
|
|
148
|
+
} // resting finger keeps its spot clear
|
|
149
|
+
}
|
|
150
|
+
else
|
|
151
|
+
last = null;
|
|
152
|
+
},
|
|
153
|
+
dispose() { geo.dispose(); printMat.dispose(); paneMat.dispose(); print.customDepthMaterial.dispose(); pic.dispose(); },
|
|
154
|
+
};
|
|
155
|
+
return api;
|
|
156
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
export declare const WIDTH = 2;
|
|
3
|
+
export declare const col: (c: any) => THREE.Color;
|
|
4
|
+
export declare const clamp01: (x: any) => number;
|
|
5
|
+
export declare const smooth: (x: any) => number;
|
|
6
|
+
export declare function mulberry32(a: any): () => number;
|
|
7
|
+
export declare function blankTexture(hex?: string): THREE.DataTexture;
|
|
8
|
+
export declare const aspectOf: (tex: any) => number;
|
|
9
|
+
/** The uniforms every variant has (picture, change, pointer, look). */
|
|
10
|
+
export declare function baseUniforms(): {
|
|
11
|
+
uTexA: {
|
|
12
|
+
value: any;
|
|
13
|
+
};
|
|
14
|
+
uTexB: {
|
|
15
|
+
value: any;
|
|
16
|
+
};
|
|
17
|
+
uFitA: {
|
|
18
|
+
value: THREE.Vector2;
|
|
19
|
+
};
|
|
20
|
+
uFitB: {
|
|
21
|
+
value: THREE.Vector2;
|
|
22
|
+
};
|
|
23
|
+
uP: {
|
|
24
|
+
value: number;
|
|
25
|
+
};
|
|
26
|
+
uHasA: {
|
|
27
|
+
value: number;
|
|
28
|
+
};
|
|
29
|
+
uSeq: {
|
|
30
|
+
value: number;
|
|
31
|
+
};
|
|
32
|
+
uSize: {
|
|
33
|
+
value: THREE.Vector2;
|
|
34
|
+
};
|
|
35
|
+
uTime: {
|
|
36
|
+
value: number;
|
|
37
|
+
};
|
|
38
|
+
uDir: {
|
|
39
|
+
value: THREE.Vector2;
|
|
40
|
+
};
|
|
41
|
+
uSpread: {
|
|
42
|
+
value: number;
|
|
43
|
+
};
|
|
44
|
+
uBlank: {
|
|
45
|
+
value: THREE.Color;
|
|
46
|
+
};
|
|
47
|
+
uIntensity: {
|
|
48
|
+
value: number;
|
|
49
|
+
};
|
|
50
|
+
uOpacity: {
|
|
51
|
+
value: number;
|
|
52
|
+
};
|
|
53
|
+
uBreathe: {
|
|
54
|
+
value: number;
|
|
55
|
+
};
|
|
56
|
+
uPointer: {
|
|
57
|
+
value: THREE.Vector3;
|
|
58
|
+
};
|
|
59
|
+
uPointerVel: {
|
|
60
|
+
value: THREE.Vector2;
|
|
61
|
+
};
|
|
62
|
+
uPointerActive: {
|
|
63
|
+
value: number;
|
|
64
|
+
};
|
|
65
|
+
uPointerMode: {
|
|
66
|
+
value: number;
|
|
67
|
+
};
|
|
68
|
+
uPointerStrength: {
|
|
69
|
+
value: number;
|
|
70
|
+
};
|
|
71
|
+
uPointerRadius: {
|
|
72
|
+
value: number;
|
|
73
|
+
};
|
|
74
|
+
uPointerColor: {
|
|
75
|
+
value: THREE.Color;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
/** Write one config value into a uniform (colours accept a hex string or a THREE.Color). */
|
|
79
|
+
export declare function setU(u: any, k: any, v: any): void;
|
|
80
|
+
/** The shared part of the one door: every variant's applyConfig starts here. */
|
|
81
|
+
export declare function applyBase(u: any, c: any, modes: any): void;
|
|
82
|
+
/** The picture state machine (see the header). `cfg` is read live (duration, aspect). */
|
|
83
|
+
export declare function createPicture(u: any, cfg: any): {
|
|
84
|
+
st: {
|
|
85
|
+
A: any;
|
|
86
|
+
B: any;
|
|
87
|
+
aspA: number;
|
|
88
|
+
aspB: number;
|
|
89
|
+
p: number;
|
|
90
|
+
dir: number;
|
|
91
|
+
pending: any;
|
|
92
|
+
seq: number;
|
|
93
|
+
frame: number;
|
|
94
|
+
};
|
|
95
|
+
show: (tex: any) => void;
|
|
96
|
+
jump: (tex: any) => void;
|
|
97
|
+
step: (dt: any) => void;
|
|
98
|
+
readonly busy: boolean;
|
|
99
|
+
dispose(): void;
|
|
100
|
+
};
|
|
101
|
+
/** cover-fit: uv' = 0.5 + (uv - 0.5) * s, s <= 1 on the axis that overflows. */
|
|
102
|
+
export declare function fit(texAspect: any, frameAspect: any, out: any): void;
|
|
103
|
+
/** Pointer in the image's own plane (lab: the stage gives {x, y} on z = 0), with a smoothed velocity and an eased presence. */
|
|
104
|
+
export declare function stepPointer(u: any, pointer: any, dt: any, st: any): void;
|
|
105
|
+
export declare const GLSL_COMMON = "\n#ifndef PI\n#define PI 3.141592653589793\n#endif\nuniform sampler2D uTexA, uTexB; uniform vec2 uFitA, uFitB, uSize, uDir;\nuniform float uP, uHasA, uSeq, uTime, uSpread, uIntensity, uOpacity, uBreathe;\nuniform vec3 uBlank;\nuniform vec3 uPointer; uniform vec2 uPointerVel; uniform float uPointerActive, uPointerMode, uPointerStrength, uPointerRadius; uniform vec3 uPointerColor;\nvec2 fitA(vec2 uv){ return 0.5 + (uv - 0.5) * uFitA; }\nvec2 fitB(vec2 uv){ return 0.5 + (uv - 0.5) * uFitB; }\nvec3 picA(vec2 uv){ return mix(uBlank, texture(uTexA, fitA(uv)).rgb, uHasA); }\nvec3 picB(vec2 uv){ return texture(uTexB, fitB(uv)).rgb; }\nvec3 picAL(vec2 uv, float lod){ return mix(uBlank, textureLod(uTexA, fitA(uv), lod).rgb, uHasA); }\nvec3 picBL(vec2 uv, float lod){ return textureLod(uTexB, fitB(uv), lod).rgb; }\nfloat luma(vec3 c){ return dot(c, vec3(0.2126, 0.7152, 0.0722)); }\nfloat hash12(vec2 p){ vec3 p3 = fract(vec3(p.xyx) * 0.1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); }\nfloat vnoise(vec2 p){ vec2 i = floor(p), f = fract(p); vec2 w = f * f * (3.0 - 2.0 * f);\n return mix(mix(hash12(i), hash12(i + vec2(1, 0)), w.x), mix(hash12(i + vec2(0, 1)), hash12(i + vec2(1, 1)), w.x), w.y); }\nfloat fbm(vec2 p){ float s = 0.0, a = 0.5; for (int i = 0; i < 4; i++){ s += a * vnoise(p); p = p * 2.03 + 17.1; a *= 0.5; } return s; }\n// the travelling front: 0 where the change starts, 1 where it ends (sweep along uDir across the frame, softly warped)\nfloat frontField(vec2 uv){\n vec2 q = (uv - 0.5) * uSize;\n float ext = 0.5 * (abs(uDir.x) * uSize.x + abs(uDir.y) * uSize.y);\n float f = 0.5 + 0.5 * dot(q, uDir) / ext;\n return clamp(f + 0.05 * (vnoise(uv * 3.0 + 7.0) - 0.5), 0.0, 1.0);\n}\n// local progress of the change at uv (0 = still A, 1 = already B); reversible because it is a pure function of uP\nfloat localP(vec2 uv){ return clamp((uP * (1.0 + uSpread) - frontField(uv)) / uSpread, 0.0, 1.0); }\nfloat sstep(float x){ return x * x * (3.0 - 2.0 * x); }\n// pointer bump in plane units (0 outside the radius)\nfloat pointerBump(vec2 xy){ float d = length(xy - uPointer.xy) / max(uPointerRadius, 1e-3); float b = max(0.0, 1.0 - d * d); return b * b * uPointerActive * uPointerStrength; }\n";
|
|
106
|
+
export declare function patchMaterial(mat: any, P: any): any;
|
|
107
|
+
/** The shadow twin of a patched material: the same vertex code (and an optional discard), so shadows follow the shape. */
|
|
108
|
+
export declare function depthTwin(P: any): any;
|
|
109
|
+
export declare const fragHead = "\n layout(location = 0) out highp vec4 pc_fragColor;\n #define gl_FragColor pc_fragColor\n";
|
|
110
|
+
//# sourceMappingURL=imageCore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageCore.d.ts","sourceRoot":"","sources":["../../../../src/components/image/core/imageCore.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,eAAO,MAAM,KAAK,IAAI,CAAC;AACvB,eAAO,MAAM,GAAG,GAAI,MAAC,gBAAuB,CAAC;AAC7C,eAAO,MAAM,OAAO,GAAI,MAAC,WAAgC,CAAC;AAC1D,eAAO,MAAM,MAAM,GAAI,MAAC,WAAoD,CAAC;AAC7E,wBAAgB,UAAU,CAAC,CAAC,KAAA,gBAAuM;AAEnO,wBAAgB,YAAY,CAAC,GAAG,SAAY,qBAK3C;AACD,eAAO,MAAM,QAAQ,GAAI,QAAG,WAAuI,CAAC;AAEpK,uEAAuE;AACvE,wBAAgB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY3B;AACD,4FAA4F;AAC5F,wBAAgB,IAAI,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,EAAE,CAAC,KAAA,QAA6J;AACzL,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,EAAE,KAAK,KAAA,QAMpC;AAED,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,CAAC,KAAA,EAAE,GAAG,KAAA;;;;;;;;;;;;;;;;;EAsCnC;AACD,gFAAgF;AAChF,wBAAgB,GAAG,CAAC,SAAS,KAAA,EAAE,WAAW,KAAA,EAAE,GAAG,KAAA,QAAiH;AAEhK,+HAA+H;AAC/H,wBAAgB,WAAW,CAAC,CAAC,KAAA,EAAE,OAAO,KAAA,EAAE,EAAE,KAAA,EAAE,EAAE,KAAA,QAU7C;AAGD,eAAO,MAAM,WAAW,usEA+BvB,CAAC;AAaF,wBAAgB,aAAa,CAAC,GAAG,KAAA,EAAE,CAAC,KAAA,OAoBnC;AACD,0HAA0H;AAC1H,wBAAgB,SAAS,CAAC,CAAC,KAAA,OAG1B;AAED,eAAO,MAAM,QAAQ,qGAGpB,CAAC"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// GENERATED from the lab (Claude outputs/gallery-lab/image/imageCommon.mjs) by emit_image.mjs — change the lab and re-emit.
|
|
2
|
+
// imageCommon — the shared core of the image-object variants (lab).
|
|
3
|
+
//
|
|
4
|
+
// An image variant shows ONE picture, 2 units wide, the height from the picture's aspect. A change of picture is
|
|
5
|
+
// a progress p 0 -> 1 between the outgoing picture A and the incoming B (the variant keeps A itself). The rules
|
|
6
|
+
// the state machine enforces for every variant:
|
|
7
|
+
// - continuous: every uniform a shader reads is continuous in time; at p = 0 a variant shows exactly A, at
|
|
8
|
+
// p = 1 exactly B, at rest (p = 1, A == B) nothing is left over;
|
|
9
|
+
// - reversible half-way: asking for the outgoing picture mid-change runs p backwards; asking for anything else
|
|
10
|
+
// mid-change queues it (the newest wins) and it plays when the current change lands;
|
|
11
|
+
// - the first picture plays the variant's own entrance (A = blank, uHasA = 0);
|
|
12
|
+
// - the frame's aspect eases from A's to B's with the change (`aspect` > 0 pins it).
|
|
13
|
+
// `uSeq` counts completed changes so a variant whose rest state accumulates (prisms turning a third each time)
|
|
14
|
+
// stays continuous: its rest angle is (uSeq + p).
|
|
15
|
+
import * as THREE from 'three';
|
|
16
|
+
export const WIDTH = 2;
|
|
17
|
+
export const col = (c) => new THREE.Color(c);
|
|
18
|
+
export const clamp01 = (x) => Math.min(1, Math.max(0, x));
|
|
19
|
+
export const smooth = (x) => { x = clamp01(x); return x * x * (3 - 2 * x); };
|
|
20
|
+
export function mulberry32(a) { return function () { a |= 0; a = (a + 0x6D2B79F5) | 0; let t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; }
|
|
21
|
+
export function blankTexture(hex = '#0e1016') {
|
|
22
|
+
const c = new THREE.Color(hex);
|
|
23
|
+
const t = new THREE.DataTexture(new Uint8Array([c.r * 255, c.g * 255, c.b * 255, 255]), 1, 1);
|
|
24
|
+
t.colorSpace = THREE.SRGBColorSpace;
|
|
25
|
+
t.needsUpdate = true;
|
|
26
|
+
return t;
|
|
27
|
+
}
|
|
28
|
+
export const aspectOf = (tex) => { const im = tex?.image; const w = im?.width || im?.naturalWidth || 16, h = im?.height || im?.naturalHeight || 10; return w / h; };
|
|
29
|
+
/** The uniforms every variant has (picture, change, pointer, look). */
|
|
30
|
+
export function baseUniforms() {
|
|
31
|
+
return {
|
|
32
|
+
uTexA: { value: null }, uTexB: { value: null },
|
|
33
|
+
uFitA: { value: new THREE.Vector2(1, 1) }, uFitB: { value: new THREE.Vector2(1, 1) },
|
|
34
|
+
uP: { value: 1 }, uHasA: { value: 0 }, uSeq: { value: 0 },
|
|
35
|
+
uSize: { value: new THREE.Vector2(2, 1.25) }, uTime: { value: 0 },
|
|
36
|
+
uDir: { value: new THREE.Vector2(1, 0) }, uSpread: { value: 0.5 },
|
|
37
|
+
uBlank: { value: col('#0e1016') },
|
|
38
|
+
uIntensity: { value: 1 }, uOpacity: { value: 1 }, uBreathe: { value: 0.5 },
|
|
39
|
+
uPointer: { value: new THREE.Vector3() }, uPointerVel: { value: new THREE.Vector2() }, uPointerActive: { value: 0 },
|
|
40
|
+
uPointerMode: { value: -1 }, uPointerStrength: { value: 1 }, uPointerRadius: { value: 0.6 }, uPointerColor: { value: col('#9ad7ff') },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** Write one config value into a uniform (colours accept a hex string or a THREE.Color). */
|
|
44
|
+
export function setU(u, k, v) { if (v === undefined)
|
|
45
|
+
return; const o = u[k]; if (o.value && o.value.isColor) {
|
|
46
|
+
if (v.isColor)
|
|
47
|
+
o.value.copy(v);
|
|
48
|
+
else
|
|
49
|
+
o.value.set(v);
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
o.value = v; }
|
|
53
|
+
/** The shared part of the one door: every variant's applyConfig starts here. */
|
|
54
|
+
export function applyBase(u, c, modes) {
|
|
55
|
+
const set = (k, v) => setU(u, k, v);
|
|
56
|
+
set('uIntensity', c.intensity);
|
|
57
|
+
set('uOpacity', c.opacity);
|
|
58
|
+
set('uBreathe', c.breathe);
|
|
59
|
+
set('uSpread', c.spread !== undefined ? Math.max(0.05, c.spread) : undefined);
|
|
60
|
+
set('uPointerStrength', c.pointerStrength);
|
|
61
|
+
set('uPointerRadius', c.pointerRadius);
|
|
62
|
+
set('uPointerColor', c.pointerColor);
|
|
63
|
+
if (c.sweepAngle !== undefined) {
|
|
64
|
+
const a = c.sweepAngle * Math.PI / 180;
|
|
65
|
+
u.uDir.value.set(Math.cos(a), Math.sin(a));
|
|
66
|
+
}
|
|
67
|
+
if (c.pointerMode !== undefined)
|
|
68
|
+
u.uPointerMode.value = modes.indexOf(c.pointerMode);
|
|
69
|
+
}
|
|
70
|
+
/** The picture state machine (see the header). `cfg` is read live (duration, aspect). */
|
|
71
|
+
export function createPicture(u, cfg) {
|
|
72
|
+
const blank = blankTexture();
|
|
73
|
+
const st = { A: null, B: null, aspA: 1.6, aspB: 1.6, p: 0, dir: 0, pending: null, seq: 0, frame: 1.6 };
|
|
74
|
+
u.uTexA.value = blank;
|
|
75
|
+
u.uTexB.value = blank;
|
|
76
|
+
u.uP.value = 0;
|
|
77
|
+
function bind() {
|
|
78
|
+
u.uTexA.value = st.A || blank;
|
|
79
|
+
u.uTexB.value = st.B || blank;
|
|
80
|
+
u.uHasA.value = st.A ? 1 : 0;
|
|
81
|
+
u.uSeq.value = st.seq;
|
|
82
|
+
}
|
|
83
|
+
function begin(tex) { st.A = st.B; st.aspA = st.aspB; st.B = tex; st.aspB = aspectOf(tex); st.p = 0; st.dir = 1; st.seq += 1; bind(); }
|
|
84
|
+
function show(tex) {
|
|
85
|
+
if (!tex)
|
|
86
|
+
return;
|
|
87
|
+
if (!st.B) {
|
|
88
|
+
st.A = null;
|
|
89
|
+
st.B = tex;
|
|
90
|
+
st.aspA = st.aspB = aspectOf(tex);
|
|
91
|
+
st.p = 0;
|
|
92
|
+
st.dir = 1;
|
|
93
|
+
bind();
|
|
94
|
+
return;
|
|
95
|
+
} // entrance
|
|
96
|
+
if (st.dir === 0) {
|
|
97
|
+
if (tex !== st.B)
|
|
98
|
+
begin(tex);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (st.dir > 0 && st.A && tex === st.A) {
|
|
102
|
+
st.dir = -1;
|
|
103
|
+
st.pending = null;
|
|
104
|
+
return;
|
|
105
|
+
} // back half-way
|
|
106
|
+
if (st.dir < 0 && tex === st.B) {
|
|
107
|
+
st.dir = 1;
|
|
108
|
+
st.pending = null;
|
|
109
|
+
return;
|
|
110
|
+
} // forward again
|
|
111
|
+
if (st.dir > 0 && tex === st.B) {
|
|
112
|
+
st.pending = null;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
st.pending = tex; // the newest wins
|
|
116
|
+
}
|
|
117
|
+
function step(dt) {
|
|
118
|
+
if (st.dir) {
|
|
119
|
+
st.p += st.dir * dt / Math.max(0.05, cfg.duration ?? 1.6);
|
|
120
|
+
if (st.p >= 1) {
|
|
121
|
+
st.p = 1;
|
|
122
|
+
st.dir = 0;
|
|
123
|
+
st.A = st.B;
|
|
124
|
+
st.aspA = st.aspB;
|
|
125
|
+
bind();
|
|
126
|
+
flush();
|
|
127
|
+
}
|
|
128
|
+
else if (st.p <= 0) {
|
|
129
|
+
st.dir = 0;
|
|
130
|
+
if (st.A) {
|
|
131
|
+
st.B = st.A;
|
|
132
|
+
st.aspB = st.aspA;
|
|
133
|
+
st.p = 1;
|
|
134
|
+
st.seq -= 1;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
st.B = null;
|
|
138
|
+
st.p = 0;
|
|
139
|
+
} // reversed entrance: back to nothing
|
|
140
|
+
bind();
|
|
141
|
+
flush();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
u.uP.value = st.p;
|
|
145
|
+
// the frame's aspect eases with the change; each picture is cover-fitted into it
|
|
146
|
+
const e = st.p * st.p * (3 - 2 * st.p);
|
|
147
|
+
st.frame = (cfg.aspect > 0) ? cfg.aspect : st.aspA + (st.aspB - st.aspA) * e;
|
|
148
|
+
u.uSize.value.set(WIDTH, WIDTH / st.frame);
|
|
149
|
+
fit(st.aspA, st.frame, u.uFitA.value);
|
|
150
|
+
fit(st.aspB, st.frame, u.uFitB.value);
|
|
151
|
+
}
|
|
152
|
+
/** Show a picture at rest with no change (a rebuild landing on the current picture). */
|
|
153
|
+
function jump(tex) { if (!tex)
|
|
154
|
+
return; st.A = st.B = tex; st.aspA = st.aspB = aspectOf(tex); st.p = 1; st.dir = 0; st.pending = null; bind(); step(0); }
|
|
155
|
+
function flush() { if (st.pending) {
|
|
156
|
+
const t = st.pending;
|
|
157
|
+
st.pending = null;
|
|
158
|
+
show(t);
|
|
159
|
+
} }
|
|
160
|
+
return { st, show, jump, step, get busy() { return st.dir !== 0; }, dispose() { blank.dispose(); } };
|
|
161
|
+
}
|
|
162
|
+
/** cover-fit: uv' = 0.5 + (uv - 0.5) * s, s <= 1 on the axis that overflows. */
|
|
163
|
+
export function fit(texAspect, frameAspect, out) { if (texAspect > frameAspect)
|
|
164
|
+
out.set(frameAspect / texAspect, 1);
|
|
165
|
+
else
|
|
166
|
+
out.set(1, texAspect / frameAspect); }
|
|
167
|
+
/** Pointer in the image's own plane (lab: the stage gives {x, y} on z = 0), with a smoothed velocity and an eased presence. */
|
|
168
|
+
export function stepPointer(u, pointer, dt, st) {
|
|
169
|
+
const k = 1 - Math.exp(-dt * 8);
|
|
170
|
+
if (pointer) {
|
|
171
|
+
const px = pointer.x, py = pointer.y;
|
|
172
|
+
if (st.had) {
|
|
173
|
+
const vx = (px - st.x) / Math.max(dt, 1e-3), vy = (py - st.y) / Math.max(dt, 1e-3);
|
|
174
|
+
u.uPointerVel.value.x += (Math.max(-6, Math.min(6, vx)) - u.uPointerVel.value.x) * k;
|
|
175
|
+
u.uPointerVel.value.y += (Math.max(-6, Math.min(6, vy)) - u.uPointerVel.value.y) * k;
|
|
176
|
+
}
|
|
177
|
+
st.x = px;
|
|
178
|
+
st.y = py;
|
|
179
|
+
st.had = true;
|
|
180
|
+
st.idle = 0;
|
|
181
|
+
u.uPointer.value.set(px, py, 0);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
st.had = false;
|
|
185
|
+
u.uPointerVel.value.multiplyScalar(1 - k);
|
|
186
|
+
}
|
|
187
|
+
const on = pointer && u.uPointerMode.value >= 0 ? 1 : 0;
|
|
188
|
+
u.uPointerActive.value += (on - u.uPointerActive.value) * (1 - Math.exp(-dt * (on ? 7 : 2.5)));
|
|
189
|
+
}
|
|
190
|
+
// ---------------------------------------------------------------- GLSL shared by every variant
|
|
191
|
+
export const GLSL_COMMON = /* glsl */ `
|
|
192
|
+
#ifndef PI
|
|
193
|
+
#define PI 3.141592653589793
|
|
194
|
+
#endif
|
|
195
|
+
uniform sampler2D uTexA, uTexB; uniform vec2 uFitA, uFitB, uSize, uDir;
|
|
196
|
+
uniform float uP, uHasA, uSeq, uTime, uSpread, uIntensity, uOpacity, uBreathe;
|
|
197
|
+
uniform vec3 uBlank;
|
|
198
|
+
uniform vec3 uPointer; uniform vec2 uPointerVel; uniform float uPointerActive, uPointerMode, uPointerStrength, uPointerRadius; uniform vec3 uPointerColor;
|
|
199
|
+
vec2 fitA(vec2 uv){ return 0.5 + (uv - 0.5) * uFitA; }
|
|
200
|
+
vec2 fitB(vec2 uv){ return 0.5 + (uv - 0.5) * uFitB; }
|
|
201
|
+
vec3 picA(vec2 uv){ return mix(uBlank, texture(uTexA, fitA(uv)).rgb, uHasA); }
|
|
202
|
+
vec3 picB(vec2 uv){ return texture(uTexB, fitB(uv)).rgb; }
|
|
203
|
+
vec3 picAL(vec2 uv, float lod){ return mix(uBlank, textureLod(uTexA, fitA(uv), lod).rgb, uHasA); }
|
|
204
|
+
vec3 picBL(vec2 uv, float lod){ return textureLod(uTexB, fitB(uv), lod).rgb; }
|
|
205
|
+
float luma(vec3 c){ return dot(c, vec3(0.2126, 0.7152, 0.0722)); }
|
|
206
|
+
float hash12(vec2 p){ vec3 p3 = fract(vec3(p.xyx) * 0.1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); }
|
|
207
|
+
float vnoise(vec2 p){ vec2 i = floor(p), f = fract(p); vec2 w = f * f * (3.0 - 2.0 * f);
|
|
208
|
+
return mix(mix(hash12(i), hash12(i + vec2(1, 0)), w.x), mix(hash12(i + vec2(0, 1)), hash12(i + vec2(1, 1)), w.x), w.y); }
|
|
209
|
+
float fbm(vec2 p){ float s = 0.0, a = 0.5; for (int i = 0; i < 4; i++){ s += a * vnoise(p); p = p * 2.03 + 17.1; a *= 0.5; } return s; }
|
|
210
|
+
// the travelling front: 0 where the change starts, 1 where it ends (sweep along uDir across the frame, softly warped)
|
|
211
|
+
float frontField(vec2 uv){
|
|
212
|
+
vec2 q = (uv - 0.5) * uSize;
|
|
213
|
+
float ext = 0.5 * (abs(uDir.x) * uSize.x + abs(uDir.y) * uSize.y);
|
|
214
|
+
float f = 0.5 + 0.5 * dot(q, uDir) / ext;
|
|
215
|
+
return clamp(f + 0.05 * (vnoise(uv * 3.0 + 7.0) - 0.5), 0.0, 1.0);
|
|
216
|
+
}
|
|
217
|
+
// local progress of the change at uv (0 = still A, 1 = already B); reversible because it is a pure function of uP
|
|
218
|
+
float localP(vec2 uv){ return clamp((uP * (1.0 + uSpread) - frontField(uv)) / uSpread, 0.0, 1.0); }
|
|
219
|
+
float sstep(float x){ return x * x * (3.0 - 2.0 * x); }
|
|
220
|
+
// pointer bump in plane units (0 outside the radius)
|
|
221
|
+
float pointerBump(vec2 xy){ float d = length(xy - uPointer.xy) / max(uPointerRadius, 1e-3); float b = max(0.0, 1.0 - d * d); return b * b * uPointerActive * uPointerStrength; }
|
|
222
|
+
`;
|
|
223
|
+
/**
|
|
224
|
+
* GLSL injected into a three.js built-in material (Standard / Physical / Depth) through onBeforeCompile, keeping
|
|
225
|
+
* every built-in anchor in place so the object-effect layers can still attach on top.
|
|
226
|
+
* vertex : runs at the top of main() with `vec3 fxP = position; vec3 fxN = normal;` in scope — rewrite them
|
|
227
|
+
* diffuse : replaces map_fragment — set `diffuseColor.rgb` (and may discard)
|
|
228
|
+
* normalFrag / roughness / emissive / clearcoatNormal : after the matching built-in chunk
|
|
229
|
+
*/
|
|
230
|
+
// begin_vertex with our position, keeping the anchor text (as a comment the include pass ignores) so an object-effect
|
|
231
|
+
// layer that splices "after begin_vertex" still lands after our displacement and can move it further.
|
|
232
|
+
const BEGIN_VERTEX = 'vec3 transformed = fxP;\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif\n// #include <begin_vertex>';
|
|
233
|
+
const BEGIN_NORMAL = 'vec3 objectNormal = fxN;\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif\n// #include <beginnormal_vertex>';
|
|
234
|
+
export function patchMaterial(mat, P) {
|
|
235
|
+
mat.onBeforeCompile = (sh) => {
|
|
236
|
+
Object.assign(sh.uniforms, P.uniforms);
|
|
237
|
+
sh.vertexShader = sh.vertexShader
|
|
238
|
+
.replace('#include <common>', '#include <common>\n' + GLSL_COMMON + (P.pars || '') + (P.vertexPars || ''));
|
|
239
|
+
const pre = `vec3 fxP = position; vec3 fxN = normal;\n${P.vertex || ''}\n`;
|
|
240
|
+
sh.vertexShader = sh.vertexShader
|
|
241
|
+
.replace('void main() {', 'void main() {\n' + pre)
|
|
242
|
+
.replace('#include <beginnormal_vertex>', BEGIN_NORMAL)
|
|
243
|
+
.replace('#include <begin_vertex>', BEGIN_VERTEX);
|
|
244
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <common>', '#include <common>\n' + GLSL_COMMON + (P.pars || '') + (P.fragmentPars || ''));
|
|
245
|
+
if (P.depthFrag && sh.fragmentShader.includes('#include <clipping_planes_fragment>'))
|
|
246
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <clipping_planes_fragment>', '#include <clipping_planes_fragment>\n' + P.depthFrag);
|
|
247
|
+
if (P.diffuse)
|
|
248
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <map_fragment>', P.diffuse);
|
|
249
|
+
if (P.roughness)
|
|
250
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <metalnessmap_fragment>', '#include <metalnessmap_fragment>\n' + P.roughness);
|
|
251
|
+
if (P.normalFrag)
|
|
252
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <normal_fragment_maps>', '#include <normal_fragment_maps>\n' + P.normalFrag);
|
|
253
|
+
if (P.clearcoatNormal)
|
|
254
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <clearcoat_normal_fragment_maps>', '#include <clearcoat_normal_fragment_maps>\n' + P.clearcoatNormal);
|
|
255
|
+
if (P.emissive)
|
|
256
|
+
sh.fragmentShader = sh.fragmentShader.replace('#include <emissivemap_fragment>', '#include <emissivemap_fragment>\n' + P.emissive);
|
|
257
|
+
};
|
|
258
|
+
mat.customProgramCacheKey = () => 'image-' + P.key;
|
|
259
|
+
return mat;
|
|
260
|
+
}
|
|
261
|
+
/** The shadow twin of a patched material: the same vertex code (and an optional discard), so shadows follow the shape. */
|
|
262
|
+
export function depthTwin(P) {
|
|
263
|
+
const m = new THREE.MeshDepthMaterial({ depthPacking: THREE.RGBADepthPacking });
|
|
264
|
+
return patchMaterial(m, { key: P.key + '-depth', uniforms: P.uniforms, pars: P.pars, vertexPars: P.vertexPars, fragmentPars: P.fragmentPars, vertex: P.vertex, depthFrag: P.depthDiscard || '' });
|
|
265
|
+
}
|
|
266
|
+
export const fragHead = /* glsl */ `
|
|
267
|
+
layout(location = 0) out highp vec4 pc_fragColor;
|
|
268
|
+
#define gl_FragColor pc_fragColor
|
|
269
|
+
`;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
export declare const POINTER_MODES: string[];
|
|
3
|
+
export declare const STRUCTURAL: string[];
|
|
4
|
+
export declare function createUniforms(): {
|
|
5
|
+
uLenses: {
|
|
6
|
+
value: number;
|
|
7
|
+
};
|
|
8
|
+
uThick: {
|
|
9
|
+
value: number;
|
|
10
|
+
};
|
|
11
|
+
uSharp: {
|
|
12
|
+
value: number;
|
|
13
|
+
};
|
|
14
|
+
uGhost: {
|
|
15
|
+
value: number;
|
|
16
|
+
};
|
|
17
|
+
uRidge: {
|
|
18
|
+
value: number;
|
|
19
|
+
};
|
|
20
|
+
uSelf: {
|
|
21
|
+
value: number;
|
|
22
|
+
};
|
|
23
|
+
uTexP: {
|
|
24
|
+
value: any;
|
|
25
|
+
};
|
|
26
|
+
uFitP: {
|
|
27
|
+
value: THREE.Vector2;
|
|
28
|
+
};
|
|
29
|
+
uHasP: {
|
|
30
|
+
value: number;
|
|
31
|
+
};
|
|
32
|
+
uTexA: {
|
|
33
|
+
value: any;
|
|
34
|
+
};
|
|
35
|
+
uTexB: {
|
|
36
|
+
value: any;
|
|
37
|
+
};
|
|
38
|
+
uFitA: {
|
|
39
|
+
value: THREE.Vector2;
|
|
40
|
+
};
|
|
41
|
+
uFitB: {
|
|
42
|
+
value: THREE.Vector2;
|
|
43
|
+
};
|
|
44
|
+
uP: {
|
|
45
|
+
value: number;
|
|
46
|
+
};
|
|
47
|
+
uHasA: {
|
|
48
|
+
value: number;
|
|
49
|
+
};
|
|
50
|
+
uSeq: {
|
|
51
|
+
value: number;
|
|
52
|
+
};
|
|
53
|
+
uSize: {
|
|
54
|
+
value: THREE.Vector2;
|
|
55
|
+
};
|
|
56
|
+
uTime: {
|
|
57
|
+
value: number;
|
|
58
|
+
};
|
|
59
|
+
uDir: {
|
|
60
|
+
value: THREE.Vector2;
|
|
61
|
+
};
|
|
62
|
+
uSpread: {
|
|
63
|
+
value: number;
|
|
64
|
+
};
|
|
65
|
+
uBlank: {
|
|
66
|
+
value: THREE.Color;
|
|
67
|
+
};
|
|
68
|
+
uIntensity: {
|
|
69
|
+
value: number;
|
|
70
|
+
};
|
|
71
|
+
uOpacity: {
|
|
72
|
+
value: number;
|
|
73
|
+
};
|
|
74
|
+
uBreathe: {
|
|
75
|
+
value: number;
|
|
76
|
+
};
|
|
77
|
+
uPointer: {
|
|
78
|
+
value: THREE.Vector3;
|
|
79
|
+
};
|
|
80
|
+
uPointerVel: {
|
|
81
|
+
value: THREE.Vector2;
|
|
82
|
+
};
|
|
83
|
+
uPointerActive: {
|
|
84
|
+
value: number;
|
|
85
|
+
};
|
|
86
|
+
uPointerMode: {
|
|
87
|
+
value: number;
|
|
88
|
+
};
|
|
89
|
+
uPointerStrength: {
|
|
90
|
+
value: number;
|
|
91
|
+
};
|
|
92
|
+
uPointerRadius: {
|
|
93
|
+
value: number;
|
|
94
|
+
};
|
|
95
|
+
uPointerColor: {
|
|
96
|
+
value: THREE.Color;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
export declare function applyConfig(u: any, c: any): void;
|
|
100
|
+
export declare function build(u: any, c: any): {
|
|
101
|
+
object: THREE.Group<THREE.Object3DEventMap>;
|
|
102
|
+
materials: any[];
|
|
103
|
+
controls: {
|
|
104
|
+
show: (t: any) => void;
|
|
105
|
+
readonly busy: boolean;
|
|
106
|
+
pic: {
|
|
107
|
+
st: {
|
|
108
|
+
A: any;
|
|
109
|
+
B: any;
|
|
110
|
+
aspA: number;
|
|
111
|
+
aspB: number;
|
|
112
|
+
p: number;
|
|
113
|
+
dir: number;
|
|
114
|
+
pending: any;
|
|
115
|
+
seq: number;
|
|
116
|
+
frame: number;
|
|
117
|
+
};
|
|
118
|
+
show: (tex: any) => void;
|
|
119
|
+
jump: (tex: any) => void;
|
|
120
|
+
step: (dt: any) => void;
|
|
121
|
+
readonly busy: boolean;
|
|
122
|
+
dispose(): void;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
apply(k: any): void;
|
|
126
|
+
update(dt: any, pointer: any): void;
|
|
127
|
+
dispose(): void;
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=lenticular.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenticular.d.ts","sourceRoot":"","sources":["../../../../src/components/image/core/lenticular.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,eAAO,MAAM,aAAa,UAAmB,CAAC;AAC9C,eAAO,MAAM,UAAU,UAAgB,CAAC;AAExC,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG7B;AACD,wBAAgB,WAAW,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,QAG/B;AA4DD,wBAAgB,KAAK,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBzB"}
|