layershift 0.1.2 → 0.2.0

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.
@@ -1,11 +1,16 @@
1
1
  /**
2
- * Entry point for the <layershift-parallax> Web Component.
2
+ * Entry point for Layershift Web Components.
3
3
  *
4
- * Importing this module registers the custom element with the browser.
5
- * After registration, <layershift-parallax> can be used in any HTML document.
4
+ * Importing this module registers all effect elements with the browser:
5
+ * - <layershift-parallax> Depth-aware parallax video effect
6
+ * - <layershift-portal> — Logo-shaped video portal with depth parallax
6
7
  */
7
8
  import { LayershiftElement } from './layershift-element';
9
+ import { LayershiftPortalElement } from './portal-element';
8
10
  export { LayershiftElement };
11
+ export { LayershiftPortalElement };
9
12
  export type { LayershiftProps } from './types';
10
13
  export type { LayershiftEventMap, LayershiftReadyDetail, LayershiftPlayDetail, LayershiftPauseDetail, LayershiftLoopDetail, LayershiftFrameDetail, LayershiftErrorDetail, } from './types';
14
+ export type { LayershiftPortalProps } from './types';
15
+ export type { LayershiftPortalEventMap, LayershiftPortalReadyDetail, LayershiftPortalPlayDetail, LayershiftPortalPauseDetail, LayershiftPortalLoopDetail, LayershiftPortalFrameDetail, LayershiftPortalErrorDetail, } from './types';
11
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAMzD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC7B,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAU3D,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,CAAC;AAEnC,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,YAAY,EACV,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,SAAS,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * <layershift-portal> Web Component
3
+ *
4
+ * A self-contained Custom Element that renders video through a logo-shaped
5
+ * portal with depth-aware parallax, emissive interior compositing, geometric
6
+ * chamfer lighting, and dimensional boundary effects. Encapsulates the
7
+ * multi-pass WebGL 2 stencil + FBO pipeline inside a Shadow DOM.
8
+ *
9
+ * Usage:
10
+ * <layershift-portal
11
+ * src="video.mp4"
12
+ * depth-src="depth-data.bin"
13
+ * depth-meta="depth-meta.json"
14
+ * logo-src="logo.svg"
15
+ * ></layershift-portal>
16
+ */
17
+ export declare class LayershiftPortalElement extends HTMLElement {
18
+ static readonly TAG_NAME = "layershift-portal";
19
+ static get observedAttributes(): string[];
20
+ private shadow;
21
+ private container;
22
+ private renderer;
23
+ private inputHandler;
24
+ private depthWorker;
25
+ private video;
26
+ private mesh;
27
+ private initialized;
28
+ private abortController;
29
+ private loopCount;
30
+ constructor();
31
+ private getAttrFloat;
32
+ private getAttrBool;
33
+ private getAttrColor;
34
+ private getAttrVec3;
35
+ private get parallaxX();
36
+ private get parallaxY();
37
+ private get parallaxMax();
38
+ private get overscan();
39
+ private get pomSteps();
40
+ private get rimIntensity();
41
+ private get rimWidth();
42
+ private get rimColor();
43
+ private get refractionStrength();
44
+ private get chromaticStrength();
45
+ private get occlusionIntensity();
46
+ private get depthPower();
47
+ private get depthScale();
48
+ private get depthBias();
49
+ private get fogDensity();
50
+ private get fogColor();
51
+ private get colorShift();
52
+ private get brightnessBias();
53
+ private get contrastLow();
54
+ private get contrastHigh();
55
+ private get verticalReduction();
56
+ private get dofStart();
57
+ private get dofStrength();
58
+ private get bevelIntensity();
59
+ private get bevelWidth();
60
+ private get bevelDarkening();
61
+ private get bevelDesaturation();
62
+ private get bevelLightAngle();
63
+ private get edgeThickness();
64
+ private get edgeSpecular();
65
+ private get edgeColor();
66
+ private get chamferWidth();
67
+ private get chamferAngle();
68
+ private get chamferColor();
69
+ private get chamferAmbient();
70
+ private get chamferSpecular();
71
+ private get chamferShininess();
72
+ private get edgeOcclusionWidth();
73
+ private get edgeOcclusionStrength();
74
+ private get lightDirection3();
75
+ private get shouldAutoplay();
76
+ private get shouldLoop();
77
+ private get shouldMute();
78
+ private emit;
79
+ private attachVideoEventListeners;
80
+ connectedCallback(): void;
81
+ disconnectedCallback(): void;
82
+ attributeChangedCallback(_name: string, _oldVal: string | null, _newVal: string | null): void;
83
+ private setupShadowDOM;
84
+ private init;
85
+ private createVideoElement;
86
+ private dispose;
87
+ }
88
+ //# sourceMappingURL=portal-element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-element.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/portal-element.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAqNH,qBAAa,uBAAwB,SAAQ,WAAW;IACtD,MAAM,CAAC,QAAQ,CAAC,QAAQ,uBAAuB;IAE/C,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAmBxC;IAED,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,SAAS,CAAK;;IAStB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,WAAW;IAUnB,OAAO,KAAK,SAAS,GAA0E;IAC/F,OAAO,KAAK,SAAS,GAA0E;IAC/F,OAAO,KAAK,WAAW,GAA8E;IACrG,OAAO,KAAK,QAAQ,GAAuE;IAC3F,OAAO,KAAK,QAAQ,GAAwE;IAE5F,OAAO,KAAK,YAAY,GAAgF;IACxG,OAAO,KAAK,QAAQ,GAAwE;IAC5F,OAAO,KAAK,QAAQ,GAA0F;IAC9G,OAAO,KAAK,kBAAkB,GAA4F;IAC1H,OAAO,KAAK,iBAAiB,GAA0F;IACvH,OAAO,KAAK,kBAAkB,GAA4F;IAE1H,OAAO,KAAK,UAAU,GAA4E;IAClG,OAAO,KAAK,UAAU,GAA4E;IAClG,OAAO,KAAK,SAAS,GAA0E;IAE/F,OAAO,KAAK,UAAU,GAA4E;IAClG,OAAO,KAAK,QAAQ,GAA0F;IAC9G,OAAO,KAAK,UAAU,GAA4E;IAClG,OAAO,KAAK,cAAc,GAAoF;IAE9G,OAAO,KAAK,WAAW,GAA8E;IACrG,OAAO,KAAK,YAAY,GAAgF;IACxG,OAAO,KAAK,iBAAiB,GAA0F;IACvH,OAAO,KAAK,QAAQ,GAAwE;IAC5F,OAAO,KAAK,WAAW,GAA8E;IAErG,OAAO,KAAK,cAAc,GAAoF;IAC9G,OAAO,KAAK,UAAU,GAA4E;IAClG,OAAO,KAAK,cAAc,GAAoF;IAC9G,OAAO,KAAK,iBAAiB,GAA0F;IACvH,OAAO,KAAK,eAAe,GAAuF;IAElH,OAAO,KAAK,aAAa,GAAkF;IAC3G,OAAO,KAAK,YAAY,GAAgF;IACxG,OAAO,KAAK,SAAS,GAA4F;IAEjH,OAAO,KAAK,YAAY,GAAgF;IACxG,OAAO,KAAK,YAAY,GAAgF;IACxG,OAAO,KAAK,YAAY,GAAkG;IAC1H,OAAO,KAAK,cAAc,GAAoF;IAC9G,OAAO,KAAK,eAAe,GAAsF;IACjH,OAAO,KAAK,gBAAgB,GAAwF;IAEpH,OAAO,KAAK,kBAAkB,GAA6F;IAC3H,OAAO,KAAK,qBAAqB,GAAmG;IACpI,OAAO,KAAK,eAAe,GAAqG;IAChI,OAAO,KAAK,cAAc,GAAuE;IACjG,OAAO,KAAK,UAAU,GAA+D;IACrF,OAAO,KAAK,UAAU,GAAiE;IAIvF,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,yBAAyB;IAyBjC,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAI5B,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAqB7F,OAAO,CAAC,cAAc;YAkCR,IAAI;YAiKJ,kBAAkB;IAsChC,OAAO,CAAC,OAAO;CA0BhB"}
@@ -62,4 +62,134 @@ export interface LayershiftEventMap {
62
62
  'layershift-parallax:frame': CustomEvent<LayershiftFrameDetail>;
63
63
  'layershift-parallax:error': CustomEvent<LayershiftErrorDetail>;
64
64
  }
65
+ /** Props for the <layershift-portal> Web Component. */
66
+ export interface LayershiftPortalProps {
67
+ src: string;
68
+ depthSrc: string;
69
+ depthMeta: string;
70
+ logoSrc: string;
71
+ parallaxX?: number;
72
+ parallaxY?: number;
73
+ parallaxMax?: number;
74
+ overscan?: number;
75
+ /** POM ray-march step count for interior displacement. */
76
+ pomSteps?: number;
77
+ rimIntensity?: number;
78
+ rimColor?: string;
79
+ rimWidth?: number;
80
+ /** Refraction distortion strength. */
81
+ refractionStrength?: number;
82
+ /** Chromatic fringe strength. */
83
+ chromaticStrength?: number;
84
+ /** Volumetric occlusion intensity. */
85
+ occlusionIntensity?: number;
86
+ /** Lens depth power (< 1 = wide-angle). */
87
+ depthPower?: number;
88
+ /** Depth range scale factor. */
89
+ depthScale?: number;
90
+ /** Depth bias (negative = near bias). */
91
+ depthBias?: number;
92
+ /** Interior fog density. */
93
+ fogDensity?: number;
94
+ /** Interior fog color (hex string). */
95
+ fogColor?: string;
96
+ /** Color grading shift intensity. */
97
+ colorShift?: number;
98
+ /** Brightness bias adjustment. */
99
+ brightnessBias?: number;
100
+ /** Depth contrast remap low. */
101
+ contrastLow?: number;
102
+ /** Depth contrast remap high. */
103
+ contrastHigh?: number;
104
+ /** Vertical parallax reduction factor. */
105
+ verticalReduction?: number;
106
+ /** Depth-of-field start distance. */
107
+ dofStart?: number;
108
+ /** Depth-of-field blur strength. */
109
+ dofStrength?: number;
110
+ /** Bevel shading intensity. */
111
+ bevelIntensity?: number;
112
+ /** Bevel effect width in distance field space. */
113
+ bevelWidth?: number;
114
+ /** Bevel darkening at edge. */
115
+ bevelDarkening?: number;
116
+ /** Bevel desaturation at edge. */
117
+ bevelDesaturation?: number;
118
+ /** Bevel light direction in degrees. */
119
+ bevelLightAngle?: number;
120
+ /** Volumetric edge wall thickness. */
121
+ edgeThickness?: number;
122
+ /** Edge wall specular intensity. */
123
+ edgeSpecular?: number;
124
+ /** Edge wall base color (hex string). */
125
+ edgeColor?: string;
126
+ /** Chamfer width in normalized mesh coords (0 = no chamfer). */
127
+ chamferWidth?: number;
128
+ /** Chamfer angle in degrees (0 = face-forward, 90 = wall). */
129
+ chamferAngle?: number;
130
+ /** Chamfer base color (hex string). */
131
+ chamferColor?: string;
132
+ /** Chamfer ambient light level. */
133
+ chamferAmbient?: number;
134
+ /** Chamfer specular highlight intensity. */
135
+ chamferSpecular?: number;
136
+ /** Chamfer specular exponent (shininess). */
137
+ chamferShininess?: number;
138
+ /** Edge occlusion ramp width. */
139
+ edgeOcclusionWidth?: number;
140
+ /** Edge occlusion strength (0 = none, 1 = full). */
141
+ edgeOcclusionStrength?: number;
142
+ /** 3D light direction as "x,y,z" string. */
143
+ lightDirection?: string;
144
+ autoplay?: boolean;
145
+ loop?: boolean;
146
+ muted?: boolean;
147
+ className?: string;
148
+ style?: Record<string, string>;
149
+ }
150
+ /** Fired once after portal initialization completes successfully. */
151
+ export interface LayershiftPortalReadyDetail {
152
+ videoWidth: number;
153
+ videoHeight: number;
154
+ duration: number;
155
+ }
156
+ /** Fired when portal video starts playing. */
157
+ export interface LayershiftPortalPlayDetail {
158
+ currentTime: number;
159
+ }
160
+ /** Fired when portal video pauses. */
161
+ export interface LayershiftPortalPauseDetail {
162
+ currentTime: number;
163
+ }
164
+ /** Fired when portal video loops back to start. */
165
+ export interface LayershiftPortalLoopDetail {
166
+ loopCount: number;
167
+ }
168
+ /** Fired on each new portal video frame. */
169
+ export interface LayershiftPortalFrameDetail {
170
+ currentTime: number;
171
+ frameNumber: number;
172
+ }
173
+ /** Fired on portal initialization errors. */
174
+ export interface LayershiftPortalErrorDetail {
175
+ message: string;
176
+ }
177
+ /**
178
+ * Map of all custom events dispatched by `<layershift-portal>`.
179
+ *
180
+ * Usage with addEventListener:
181
+ * ```ts
182
+ * el.addEventListener('layershift-portal:ready', (e) => {
183
+ * console.log(e.detail.videoWidth, e.detail.duration);
184
+ * });
185
+ * ```
186
+ */
187
+ export interface LayershiftPortalEventMap {
188
+ 'layershift-portal:ready': CustomEvent<LayershiftPortalReadyDetail>;
189
+ 'layershift-portal:play': CustomEvent<LayershiftPortalPlayDetail>;
190
+ 'layershift-portal:pause': CustomEvent<LayershiftPortalPauseDetail>;
191
+ 'layershift-portal:loop': CustomEvent<LayershiftPortalLoopDetail>;
192
+ 'layershift-portal:frame': CustomEvent<LayershiftPortalFrameDetail>;
193
+ 'layershift-portal:error': CustomEvent<LayershiftPortalErrorDetail>;
194
+ }
65
195
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAMD,8DAA8D;AAC9D,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,YAAY,CAAC,EAAE,OAAO,sBAAsB,EAAE,YAAY,CAAC;IAC3D,qFAAqF;IACrF,aAAa,CAAC,EAAE,OAAO,sBAAsB,EAAE,qBAAqB,CAAC;CACtE;AAED,uCAAuC;AACvC,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+BAA+B;AAC/B,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oFAAoF;AACpF,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,sCAAsC;AACtC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,2BAA2B,EAAE,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAChE,0BAA0B,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC;IAC9D,2BAA2B,EAAE,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAChE,0BAA0B,EAAE,WAAW,CAAC,oBAAoB,CAAC,CAAC;IAC9D,2BAA2B,EAAE,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAChE,2BAA2B,EAAE,WAAW,CAAC,qBAAqB,CAAC,CAAC;CACjE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Portal Renderer v4 — Emissive Interior + Geometric Chamfer
3
+ *
4
+ * Renders video through a logo-shaped portal using a multi-pass WebGL 2
5
+ * stencil + FBO compositing pipeline with screen-space distance field
6
+ * for dimensional glyph thickness.
7
+ *
8
+ * ## Render Pipeline
9
+ *
10
+ * 1. **Interior FBO**: Render depth-displaced video into off-screen framebuffer
11
+ * with POM displacement, lens-transformed depth, DOF, fog, color grading.
12
+ * Outputs color + depth textures via MRT.
13
+ *
14
+ * 2a. **Stencil mark**: Render triangulated SVG mesh into stencil buffer.
15
+ *
16
+ * 2b. **Emissive composite**: Draw interior FBO where stencil = 1 as an
17
+ * emissive passthrough (source brightness preserved). Subtle edge
18
+ * occlusion ramp at the chamfer seam driven by JFA distance field.
19
+ *
20
+ * 2c. **Chamfer geometry**: Render geometric chamfer ring around each contour
21
+ * silhouette with Blinn-Phong lighting and frosted-glass video blur.
22
+ * Smooth per-vertex normals, progressive blur via lerpT attribute.
23
+ *
24
+ * 3. **Distance field (JFA)**: Compute screen-space signed distance from every
25
+ * interior pixel to the nearest letter edge. Runs once on resize, cached.
26
+ * Uses Jump Flood Algorithm at half resolution (~10 passes).
27
+ *
28
+ * 4. **Boundary effects**: Depth-reactive volumetric edge wall, rim lighting,
29
+ * refraction, chromatic fringe, occlusion — all driven by distance field
30
+ * and interior depth texture.
31
+ */
32
+ import type { ParallaxInput } from './input-handler';
33
+ import type { ShapeMesh } from './shape-generator';
34
+ export interface PortalRendererConfig {
35
+ parallaxStrength: number;
36
+ overscanPadding: number;
37
+ /** POM step count for interior (default: 16). */
38
+ pomSteps: number;
39
+ rimLightIntensity: number;
40
+ rimLightColor: [number, number, number];
41
+ rimLightWidth: number;
42
+ refractionStrength: number;
43
+ chromaticStrength: number;
44
+ occlusionIntensity: number;
45
+ depthPower: number;
46
+ depthScale: number;
47
+ depthBias: number;
48
+ fogDensity: number;
49
+ fogColor: [number, number, number];
50
+ colorShift: number;
51
+ brightnessBias: number;
52
+ contrastLow: number;
53
+ contrastHigh: number;
54
+ verticalReduction: number;
55
+ dofStart: number;
56
+ dofStrength: number;
57
+ bevelIntensity: number;
58
+ bevelWidth: number;
59
+ bevelDarkening: number;
60
+ bevelDesaturation: number;
61
+ bevelLightAngle: number;
62
+ edgeThickness: number;
63
+ edgeSpecular: number;
64
+ edgeColor: [number, number, number];
65
+ /** Chamfer width in normalized mesh coords (0 = no chamfer). Default: 0.008 */
66
+ chamferWidth: number;
67
+ /** Chamfer angle in degrees (0 = face-forward, 90 = wall). Default: 45 */
68
+ chamferAngle: number;
69
+ /** Chamfer base color [r, g, b] in 0–1 range. Default: [0.15, 0.15, 0.18] */
70
+ chamferColor: [number, number, number];
71
+ /** Chamfer ambient light level. Default: 0.12 */
72
+ chamferAmbient: number;
73
+ /** Chamfer specular highlight intensity. Default: 0.3 */
74
+ chamferSpecular: number;
75
+ /** Chamfer specular exponent (shininess). Default: 24 */
76
+ chamferShininess: number;
77
+ /** Edge occlusion ramp width (UV space). Default: 0.03 */
78
+ edgeOcclusionWidth: number;
79
+ /** Edge occlusion strength (0=none, 1=full black at edge). Default: 0.2 */
80
+ edgeOcclusionStrength: number;
81
+ /** 3D light direction [x, y, z] for chamfer lighting (will be normalized). */
82
+ lightDirection: [number, number, number];
83
+ }
84
+ export declare class PortalRenderer {
85
+ private static readonly RESIZE_DEBOUNCE_MS;
86
+ private readonly canvas;
87
+ private gl;
88
+ private readonly container;
89
+ private stencilProgram;
90
+ private maskProgram;
91
+ private jfaSeedProgram;
92
+ private jfaFloodProgram;
93
+ private jfaDistProgram;
94
+ private interiorProgram;
95
+ private compositeProgram;
96
+ private boundaryProgram;
97
+ private chamferProgram;
98
+ private stencilUniforms;
99
+ private maskUniforms;
100
+ private jfaSeedUniforms;
101
+ private jfaFloodUniforms;
102
+ private jfaDistUniforms;
103
+ private interiorUniforms;
104
+ private compositeUniforms;
105
+ private boundaryUniforms;
106
+ private chamferUniforms;
107
+ private quadVao;
108
+ private stencilVao;
109
+ private stencilIndexCount;
110
+ private maskVao;
111
+ private boundaryVao;
112
+ private boundaryVertexCount;
113
+ private chamferVao;
114
+ private chamferVertexCount;
115
+ private videoTexture;
116
+ private depthTexture;
117
+ private interiorFbo;
118
+ private interiorColorTex;
119
+ private interiorDepthTex;
120
+ private fboWidth;
121
+ private fboHeight;
122
+ private maskFbo;
123
+ private maskTex;
124
+ private jfaPingFbo;
125
+ private jfaPingTex;
126
+ private jfaPongFbo;
127
+ private jfaPongTex;
128
+ private distFbo;
129
+ private distTex;
130
+ private jfaWidth;
131
+ private jfaHeight;
132
+ private distFieldDirty;
133
+ private depthWidth;
134
+ private depthHeight;
135
+ private videoAspect;
136
+ private meshAspect;
137
+ private meshScaleX;
138
+ private meshScaleY;
139
+ private readDepth;
140
+ private readInput;
141
+ private playbackVideo;
142
+ private onVideoFrame;
143
+ private animationFrameHandle;
144
+ private rvfcHandle;
145
+ private rvfcSupported;
146
+ private resizeObserver;
147
+ private resizeTimer;
148
+ private uvOffset;
149
+ private uvScale;
150
+ private lightDirX;
151
+ private lightDirY;
152
+ private lightDir3;
153
+ private readonly config;
154
+ constructor(parent: HTMLElement, config: PortalRendererConfig);
155
+ initialize(video: HTMLVideoElement, depthWidth: number, depthHeight: number, mesh: ShapeMesh): void;
156
+ private uploadStencilMesh;
157
+ private uploadMaskMesh;
158
+ private uploadBoundaryMesh;
159
+ private uploadChamferMesh;
160
+ private disposeChamferGeometry;
161
+ private createFBO;
162
+ private createJFAResources;
163
+ private computeDistanceField;
164
+ start(video: HTMLVideoElement, readDepth: (timeSec: number) => Uint8Array, readInput: () => ParallaxInput, onVideoFrame?: (currentTime: number, frameNumber: number) => void): void;
165
+ stop(): void;
166
+ dispose(): void;
167
+ private initGPUResources;
168
+ private getUniforms;
169
+ private readonly videoFrameLoop;
170
+ private readonly renderLoop;
171
+ private updateDepthTexture;
172
+ private setupResizeHandling;
173
+ private readonly scheduleResizeRecalculate;
174
+ private recalculateViewportLayout;
175
+ private getViewportSize;
176
+ private readonly handleContextLost;
177
+ private readonly handleContextRestored;
178
+ private disposeTextures;
179
+ private disposeFBO;
180
+ private disposeJFA;
181
+ private disposeStencilGeometry;
182
+ private disposeBoundaryGeometry;
183
+ private disposeGPUResources;
184
+ }
185
+ //# sourceMappingURL=portal-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-renderer.d.ts","sourceRoot":"","sources":["../../src/portal-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Shape Generator — SVG → GPU Mesh Pipeline
3
+ *
4
+ * Converts SVG path data into triangulated vertex buffers suitable for
5
+ * WebGL rendering. Used by the portal effect to transform logo SVGs
6
+ * into stencil-buffer geometry.
7
+ *
8
+ * Pipeline:
9
+ * 1. Fetch SVG file
10
+ * 2. Parse with DOMParser
11
+ * 3. Extract <path> elements (and basic shapes like <polygon>, <rect>, <circle>)
12
+ * 4. Parse SVG path commands (M, L, C, Q, A, Z, etc.)
13
+ * 5. Flatten Bezier curves to line segments (adaptive subdivision)
14
+ * 6. Apply SVG transforms if present
15
+ * 7. Normalize coordinates to [-1, 1] range (aspect-ratio preserving)
16
+ * 8. Triangulate polygon via earcut
17
+ * 9. Extract edge outline vertices for rim-light pass
18
+ * 10. Return ShapeMesh
19
+ *
20
+ * ## Zero dependencies
21
+ *
22
+ * Earcut triangulation is vendored inline (~120 LOC) to maintain
23
+ * the library's zero-runtime-dependency constraint.
24
+ */
25
+ /** Triangulated mesh data ready for GPU upload. */
26
+ export interface ShapeMesh {
27
+ /** Flattened vertex positions [x,y, x,y, ...] in normalized [-1,1] coords. */
28
+ vertices: Float32Array;
29
+ /** Triangle indices (from earcut) for gl.drawElements. */
30
+ indices: Uint16Array;
31
+ /** Outline vertices [x,y, x,y, ...] for rim-light edge pass (LINE_STRIP). */
32
+ edgeVertices: Float32Array;
33
+ /**
34
+ * Start index (in floats, not points) of each contour within edgeVertices.
35
+ * Each contour runs from edgeVertices[contourOffsets[i]] to
36
+ * edgeVertices[contourOffsets[i+1]-1] (or end of array for last contour).
37
+ * Each contour is closed: its last point repeats its first point.
38
+ */
39
+ contourOffsets: number[];
40
+ /**
41
+ * Whether each contour is a hole (inner cutout) vs an outer boundary.
42
+ * Parallel array to contourOffsets. Hole contours have opposite winding
43
+ * direction and their edge normals point inward.
44
+ */
45
+ contourIsHole: boolean[];
46
+ /** Bounding box in normalized coordinates. */
47
+ bounds: {
48
+ minX: number;
49
+ maxX: number;
50
+ minY: number;
51
+ maxY: number;
52
+ };
53
+ /** Original SVG width / height aspect ratio (for viewport correction). */
54
+ aspect: number;
55
+ }
56
+ /**
57
+ * Generate a GPU-ready mesh from an SVG file URL.
58
+ *
59
+ * Fetches the SVG, extracts all path data, flattens curves,
60
+ * triangulates, and returns normalized vertices + indices.
61
+ */
62
+ export declare function generateMeshFromSVG(svgUrl: string): Promise<ShapeMesh>;
63
+ /**
64
+ * Generate a GPU-ready mesh from an SVG string.
65
+ * Useful for inline SVGs or testing.
66
+ */
67
+ export declare function generateMeshFromSVGString(svgText: string): ShapeMesh;
68
+ /**
69
+ * Earcut polygon triangulation.
70
+ *
71
+ * Based on mapbox/earcut (ISC license).
72
+ * Minimal vendored implementation for polygon triangulation.
73
+ * Handles holes and complex polygons.
74
+ *
75
+ * @param data - Flat array of vertex coordinates [x0, y0, x1, y1, ...]
76
+ * @param holeIndices - Array of hole start indices (vertex indices, not coord indices)
77
+ * @param dim - Number of coordinates per vertex (default: 2)
78
+ * @returns Array of triangle indices
79
+ *
80
+ * @see https://github.com/mapbox/earcut
81
+ */
82
+ export declare function earcut(data: number[], holeIndices?: number[], dim?: number): number[];
83
+ //# sourceMappingURL=shape-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape-generator.d.ts","sourceRoot":"","sources":["../../src/shape-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,QAAQ,EAAE,YAAY,CAAC;IACvB,0DAA0D;IAC1D,OAAO,EAAE,WAAW,CAAC;IACrB,6EAA6E;IAC7E,YAAY,EAAE,YAAY,CAAC;IAC3B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,aAAa,EAAE,OAAO,EAAE,CAAC;IACzB,8CAA8C;IAC9C,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAO5E;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAiHpE;AAsoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,SAAI,GAAG,MAAM,EAAE,CA+BhF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "layershift",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Embeddable video effects as Web Components. Drop-in parallax, depth-aware motion, and more.",
5
5
  "type": "module",
6
6
  "main": "dist/components/layershift.js",
@@ -60,12 +60,13 @@
60
60
  "url": "https://github.com/jeremysykes/layershift/issues"
61
61
  },
62
62
  "homepage": "https://layershift.io",
63
- "dependencies": {},
64
63
  "devDependencies": {
65
64
  "@playwright/test": "^1.58.2",
65
+ "@types/jsdom": "^27.0.0",
66
66
  "@vitest/browser": "^4.0.18",
67
67
  "@xenova/transformers": "^2.17.2",
68
68
  "happy-dom": "^20.6.1",
69
+ "jsdom": "^28.1.0",
69
70
  "playwright": "^1.58.2",
70
71
  "sharp": "^0.34.5",
71
72
  "tsx": "^4.21.0",