layershift 0.5.1 → 0.7.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.
- package/README.md +33 -12
- package/dist/components/layershift.js +29 -29
- package/dist/npm/layershift.es.js +788 -742
- package/dist/types/components/layershift/global.d.ts +4 -2
- package/dist/types/components/layershift/index.d.ts +1 -1
- package/dist/types/components/layershift/layershift-element.d.ts +13 -2
- package/dist/types/components/layershift/layershift-element.d.ts.map +1 -1
- package/dist/types/components/layershift/lifecycle.d.ts +1 -1
- package/dist/types/components/layershift/portal-element.d.ts +1 -2
- package/dist/types/components/layershift/portal-element.d.ts.map +1 -1
- package/dist/types/components/layershift/types.d.ts +8 -4
- package/dist/types/components/layershift/types.d.ts.map +1 -1
- package/dist/types/depth/precomputed-depth.d.ts +4 -8
- package/dist/types/depth/precomputed-depth.d.ts.map +1 -1
- package/dist/types/renderers/renderer-base.d.ts +11 -0
- package/dist/types/renderers/renderer-base.d.ts.map +1 -1
- package/dist/types/shared/filter-config.d.ts +2 -3
- package/dist/types/shared/filter-config.d.ts.map +1 -1
- package/package.json +11 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var Layershift=(function(
|
|
2
|
-
${
|
|
3
|
-
${
|
|
1
|
+
var Layershift=(function(X){"use strict";var bt=typeof document<"u"?document.currentScript:null;class Dt{constructor(t){this.depthData=t;const e=t.width*t.height;this.uint8Output=new Uint8Array(e)}uint8Output;lastFrameIndex=-1;lastNextFrameIndex=-1;lastLerpFactor=-1;sample(t){const e=ie(t*this.depthData.fps,0,this.depthData.frameCount-1),i=Math.floor(e),n=Math.min(i+1,this.depthData.frameCount-1),r=e-i,o=i!==this.lastFrameIndex||n!==this.lastNextFrameIndex,l=Math.abs(r-this.lastLerpFactor)>.001;if(!o&&!l)return this.uint8Output;this.lastFrameIndex=i,this.lastNextFrameIndex=n,this.lastLerpFactor=r;const a=1-r,h=this.depthData.frames[i],c=this.depthData.frames[n];for(let f=0;f<this.uint8Output.length;f+=1)this.uint8Output[f]=h[f]*a+c[f]*r+.5|0;return this.uint8Output}}async function Ft(s,t=512,e=512,i=5,n){const r=await te(s);return ee(r,t,e,i)}async function te(s,t){const e=await fetch(s);if(!e.ok)throw new Error(`Failed to fetch depth data (${e.status} ${e.statusText}).`);e.headers.get("content-length");const i=e.body;if(!i)return new Uint8Array(await e.arrayBuffer());const n=[];let r=0;const o=i.getReader();for(;;){const{done:h,value:c}=await o.read();if(h)break;c&&(n.push(c),r+=c.byteLength)}const l=new Uint8Array(r);let a=0;for(const h of n)l.set(h,a),a+=h.byteLength;return l}function ee(s,t,e,i){const n=t*e;if(n===0)throw new Error("Depth frame dimensions must be non-zero.");if(s.byteLength%n!==0)throw new Error(`Depth data byte length (${s.byteLength}) is not evenly divisible by frame size (${n} = ${t}×${e}).`);const r=s.byteLength/n,o=new Array(r);for(let l=0;l<r;l+=1){const a=l*n;o[l]=s.subarray(a,a+n)}return{width:t,height:e,fps:i,frameCount:r,frames:o}}function N(s,t){const e=new Uint8Array(s*t);return e.fill(128),{width:s,height:t,fps:1,frameCount:1,frames:[e]}}function ie(s,t,e){return Math.min(e,Math.max(t,s))}const ne={parallaxStrength:.05,contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4,pomSteps:16,overscanPadding:.08};function re(s,t,e){const i=new Float32Array(256);if(s.length===0||t<=0||e<=0)return Ct(i);const n=oe(s.length),r=t*e;let o=0;const l=new Uint32Array(256);for(const m of n){const T=s[m],R=Math.min(T.length,r);for(let A=0;A<R;A+=1)l[T[A]]+=1;o+=R}if(o===0)return Ct(i);const a=1/o;for(let m=0;m<256;m+=1)i[m]=l[m]*a;const h=new Float32Array(256);h[0]=i[0];for(let m=1;m<256;m+=1)h[m]=h[m-1]+i[m];const c=it(h,.05),f=it(h,.25),u=it(h,.5),x=it(h,.75),p=it(h,.95);let d=0;for(let m=0;m<256;m+=1)d+=m/255*i[m];let y=0;for(let m=0;m<256;m+=1){const T=m/255-d;y+=i[m]*T*T}const b=Math.sqrt(y),E=p-c,g=x-f,v=ae(i);return{mean:d,stdDev:b,p5:c,p25:f,median:u,p75:x,p95:p,effectiveRange:E,iqr:g,bimodality:v,histogram:i}}function se(s){if(s.effectiveRange<.05||s.stdDev<.02)return{...ne};const t=s.effectiveRange-.5,e=s.bimodality-.4,i=O(.05-t*.03+e*.01,.035,.065),n=O(s.p5-.03,0,.25),r=O(s.p95+.03,.75,1),o=O((i-.03)/.05,0,1),l=O(.6-o*.25,.35,.6),a=O(.6-t*.2,.5,.7),h=O(.4+t*.2,.25,.5),c=16,f=O(i+.03,.06,.1);return{parallaxStrength:i,contrastLow:n,contrastHigh:r,verticalReduction:l,dofStart:a,dofStrength:h,pomSteps:c,overscanPadding:f}}function oe(s){if(s<=0)return[];if(s===1)return[0];const t=s-1,e=[0,Math.floor(s/4),Math.floor(s/2),Math.floor(3*s/4),t],i=new Set,n=[];for(const r of e)i.has(r)||(i.add(r),n.push(r));return n}function it(s,t){for(let e=0;e<256;e+=1)if(s[e]>=t)return e/255;return 1}function ae(s){const t=new Float32Array(256);for(let u=0;u<256;u+=1){let x=0,p=0;for(let d=u-2;d<=u+2;d+=1)d>=0&&d<256&&(x+=s[d],p+=1);t[u]=x/p}let e=0;for(let u=0;u<256;u+=1)e+=t[u];e/=256;const i=e*2,n=25,r=[];for(let u=1;u<255;u+=1)t[u]>t[u-1]&&t[u]>t[u+1]&&t[u]>=i&&r.push({bin:u,height:t[u]});if(t[0]>t[1]&&t[0]>=i&&r.push({bin:0,height:t[0]}),t[255]>t[254]&&t[255]>=i&&r.push({bin:255,height:t[255]}),r.sort((u,x)=>x.height-u.height),r.length<2)return 0;const o=r[0];let l=null;for(let u=1;u<r.length;u+=1)if(Math.abs(r[u].bin-o.bin)>=n){l=r[u];break}if(!l)return 0;const a=Math.min(o.bin,l.bin),h=Math.max(o.bin,l.bin);let c=1/0;for(let u=a;u<=h;u+=1)t[u]<c&&(c=t[u]);const f=Math.min(o.height,l.height);return f<=0?0:O(1-c/f,0,1)}function Ct(s){return{mean:0,stdDev:0,p5:0,p25:0,median:0,p75:0,p95:0,effectiveRange:0,iqr:0,bimodality:0,histogram:s}}function O(s,t,e){return Math.min(e,Math.max(t,s))}function G(s,t,e){const i=s.createShader(t);if(!i)throw new Error("Failed to create shader.");if(s.shaderSource(i,e),s.compileShader(i),!s.getShaderParameter(i,s.COMPILE_STATUS)){const n=s.getShaderInfoLog(i)??"";throw s.deleteShader(i),new Error(`Shader compilation failed:
|
|
2
|
+
${n}`)}return i}function lt(s,t,e){const i=s.createProgram();if(!i)throw new Error("Failed to create program.");if(s.attachShader(i,t),s.attachShader(i,e),s.linkProgram(i),!s.getProgramParameter(i,s.LINK_STATUS)){const n=s.getProgramInfoLog(i)??"";throw s.deleteProgram(i),new Error(`Program linking failed:
|
|
3
|
+
${n}`)}return s.detachShader(i,t),s.detachShader(i,e),s.deleteShader(t),s.deleteShader(e),i}function ut(s,t,e){const i={};for(const n of e)i[n]=s.getUniformLocation(t,n);return i}const le=new Float32Array([-1,-1,1,-1,-1,1,1,1]);function Ut(s,t){const e=s.createVertexArray();if(!e)throw new Error("Failed to create VAO.");s.bindVertexArray(e);const i=s.createBuffer();s.bindBuffer(s.ARRAY_BUFFER,i),s.bufferData(s.ARRAY_BUFFER,le,s.STATIC_DRAW);const n=s.getAttribLocation(t,"aPosition");return s.enableVertexAttribArray(n),s.vertexAttribPointer(n,2,s.FLOAT,!1,0,0),s.bindVertexArray(null),e}class Lt{slots=new Map;nextUnit=0;register(t){if(this.slots.has(t))throw new Error(`TextureRegistry: slot '${t}' already registered.`);const e={name:t,unit:this.nextUnit++,texture:null};return this.slots.set(t,e),e}get(t){const e=this.slots.get(t);if(!e)throw new Error(`TextureRegistry: slot '${t}' not found.`);return e}disposeAll(t){for(const e of this.slots.values())e.texture&&(t.deleteTexture(e.texture),e.texture=null)}get size(){return this.slots.size}}function H(s,t,e,i,n){const r=G(s,s.VERTEX_SHADER,e),o=G(s,s.FRAGMENT_SHADER,i),l=lt(s,r,o),a=ut(s,l,n);return{name:t,program:l,uniforms:a,dispose(h){h.deleteProgram(l)}}}function _t(s,t,e,i,n,r){const o=G(s,s.VERTEX_SHADER,e),l=G(s,s.FRAGMENT_SHADER,i),a=lt(s,o,l),h=ut(s,a,n),c={texture:null,unit:r.textureUnit,attachment:s.COLOR_ATTACHMENT0},f={name:t,program:a,uniforms:h,fbo:null,outputs:[c],width:0,height:0,resize(u,x,p){f.fbo&&u.deleteFramebuffer(f.fbo),c.texture&&u.deleteTexture(c.texture),f.width=x,f.height=p,c.texture=u.createTexture(),u.activeTexture(u.TEXTURE0+c.unit),u.bindTexture(u.TEXTURE_2D,c.texture),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MIN_FILTER,u.LINEAR),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MAG_FILTER,u.LINEAR),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_WRAP_S,u.CLAMP_TO_EDGE),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_WRAP_T,u.CLAMP_TO_EDGE),u.texImage2D(u.TEXTURE_2D,0,r.internalFormat,x,p,0,r.format,r.type,null),f.fbo=u.createFramebuffer(),u.bindFramebuffer(u.FRAMEBUFFER,f.fbo),u.framebufferTexture2D(u.FRAMEBUFFER,u.COLOR_ATTACHMENT0,u.TEXTURE_2D,c.texture,0),u.bindFramebuffer(u.FRAMEBUFFER,null)},dispose(u){f.fbo&&(u.deleteFramebuffer(f.fbo),f.fbo=null),c.texture&&(u.deleteTexture(c.texture),c.texture=null),u.deleteProgram(a)}};return r.width>0&&r.height>0&&f.resize(s,r.width,r.height),f}const ue={high:{dprCap:2,depthMaxDim:512,pomSteps:16,bilateralRadius:2,jfaDivisor:2},medium:{dprCap:1.5,depthMaxDim:384,pomSteps:12,bilateralRadius:2,jfaDivisor:2},low:{dprCap:1,depthMaxDim:256,pomSteps:8,bilateralRadius:1,jfaDivisor:4}};function ce(s){let t="unknown";const e=s.getExtension("WEBGL_debug_renderer_info");e&&(t=s.getParameter(e.UNMASKED_RENDERER_WEBGL)||"unknown");const i=s.getParameter(s.MAX_TEXTURE_SIZE),n=typeof navigator<"u"&&navigator.hardwareConcurrency||0,r=typeof navigator<"u"&&navigator.deviceMemory||0,o=typeof window<"u"&&window.devicePixelRatio||1,l=typeof screen<"u"?(screen.width||0)*(screen.height||0):0,a=typeof navigator<"u"&&("ontouchstart"in window||navigator.maxTouchPoints>0),h=l>0&&l<1920*1080;return{gpuRenderer:t,maxTextureSize:i,hardwareConcurrency:n,deviceMemory:r,devicePixelRatio:o,screenPixels:l,isMobile:a&&h}}const he=["mali-4","mali-t","adreno 3","adreno 4","adreno 5","powervr sgx","intel hd graphics","intel uhd graphics","intel iris","llvmpipe","swiftshader","software"],fe=["nvidia","geforce","radeon rx","radeon pro","apple m","apple gpu","adreno 7","adreno 6","mali-g7","mali-g6"];function de(s){let t=0;const e=s.gpuRenderer.toLowerCase(),i=he.some(r=>e.includes(r)),n=fe.some(r=>e.includes(r));return i&&(t-=30),n&&(t+=20),s.maxTextureSize>=16384?t+=10:s.maxTextureSize>=8192?t+=5:s.maxTextureSize<=4096&&(t-=15),s.hardwareConcurrency>=8?t+=5:s.hardwareConcurrency>=4?t+=0:s.hardwareConcurrency>0&&s.hardwareConcurrency<4&&(t-=10),s.deviceMemory>=8?t+=5:s.deviceMemory>=4?t+=0:s.deviceMemory>0&&s.deviceMemory<4&&(t-=15),s.isMobile&&(t-=10),t>=0?"high":t>=-25?"medium":"low"}function It(s,t){const e=t&&t!=="auto"?t:de(ce(s));return{tier:e,...ue[e]}}class ct{static RESIZE_DEBOUNCE_MS=100;canvas;container;depthWidth=0;depthHeight=0;sourceDepthWidth=0;sourceDepthHeight=0;depthSubsampleBuffer=null;videoAspect=1.7777777777777777;isCameraSource=!1;uvOffset=[0,0];uvScale=[1,1];readDepth=null;readInput=null;mediaSource=null;onVideoFrame=null;animationFrameHandle=0;rvfcHandle=0;rvfcSupported=!1;resizeObserver=null;resizeTimer=null;qualityParams;constructor(t){this.container=t,this.canvas=document.createElement("canvas"),this.canvas.style.display="block",this.canvas.style.width="100%",this.canvas.style.height="100%",this.container.appendChild(this.canvas),this.canvas.addEventListener("webglcontextlost",this._handleContextLost),this.canvas.addEventListener("webglcontextrestored",this._handleContextRestored)}get canvasElement(){return this.canvas}start(t,e,i,n){this.stop(),this.mediaSource=t,this.readDepth=e,this.readInput=i,this.onVideoFrame=n??null,this.rvfcSupported=t.isLive&&typeof t.requestVideoFrameCallback=="function",this.rvfcSupported?this.rvfcHandle=t.requestVideoFrameCallback(this._videoFrameLoop):t.isLive||this.onDepthUpdate(t.currentTime),this.animationFrameHandle=window.requestAnimationFrame(this._rafLoop)}stop(){this.stopLoops(),this.mediaSource=null,this.readDepth=null,this.readInput=null,this.onVideoFrame=null,this.rvfcSupported=!1}pause(){this.stopLoops()}resume(){this.readInput&&(this.animationFrameHandle||(this.rvfcSupported&&this.mediaSource?.requestVideoFrameCallback&&(this.rvfcHandle=this.mediaSource.requestVideoFrameCallback(this._videoFrameLoop)),this.animationFrameHandle=window.requestAnimationFrame(this._rafLoop)))}get isPaused(){return this.animationFrameHandle===0&&this.readInput!==null}stopLoops(){this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0),this.rvfcHandle&&this.mediaSource?.cancelVideoFrameCallback&&(this.mediaSource.cancelVideoFrameCallback(this.rvfcHandle),this.rvfcHandle=0)}dispose(){this.stop(),this.disposeRenderer(),this.canvas.removeEventListener("webglcontextlost",this._handleContextLost),this.canvas.removeEventListener("webglcontextrestored",this._handleContextRestored),this.canvas.remove(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),window.removeEventListener("resize",this.scheduleResizeRecalculate),this.resizeTimer!==null&&(window.clearTimeout(this.resizeTimer),this.resizeTimer=null)}static isRVFCSupported(){return"requestVideoFrameCallback"in HTMLVideoElement.prototype}_rafLoop=()=>{this.animationFrameHandle=window.requestAnimationFrame(this._rafLoop),this.onRenderFrame()};_videoFrameLoop=(t,e)=>{const i=this.mediaSource;if(!i||!i.requestVideoFrameCallback)return;this.rvfcHandle=i.requestVideoFrameCallback(this._videoFrameLoop);const n=e.mediaTime??i.currentTime;this.onDepthUpdate(n),this.onVideoFrame&&this.onVideoFrame(n,e.presentedFrames??0)};_handleContextLost=t=>{t.preventDefault(),this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0)};_handleContextRestored=()=>{this.onContextRestored()};setupResizeHandling(){typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(()=>{this.scheduleResizeRecalculate()}),this.resizeObserver.observe(this.container)),window.addEventListener("resize",this.scheduleResizeRecalculate),this.recalculateViewportLayout()}scheduleResizeRecalculate=()=>{this.resizeTimer!==null&&window.clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resizeTimer=null,this.recalculateViewportLayout()},ct.RESIZE_DEBOUNCE_MS)};getViewportSize(){const t=Math.max(1,Math.round(this.container.clientWidth||window.innerWidth)),e=Math.max(1,Math.round(this.container.clientHeight||window.innerHeight));return{width:t,height:e}}clampDepthDimensions(t,e,i){this.sourceDepthWidth=t,this.sourceDepthHeight=e;let n=t,r=e;if(n>i||r>i){const o=i/Math.max(n,r);n=Math.max(1,Math.round(n*o)),r=Math.max(1,Math.round(r*o))}this.depthWidth=n,this.depthHeight=r,n!==t||r!==e?this.depthSubsampleBuffer=new Uint8Array(n*r):this.depthSubsampleBuffer=null}subsampleDepth(t){if(!this.depthSubsampleBuffer)return t;const e=this.depthSubsampleBuffer,i=this.sourceDepthWidth,n=this.depthWidth,r=this.depthHeight;for(let o=0;o<r;o++){const a=Math.min(Math.round(o*this.sourceDepthHeight/r),this.sourceDepthHeight-1)*i,h=o*n;for(let c=0;c<n;c++){const f=Math.min(Math.round(c*i/n),i-1);e[h+c]=t[a+f]}}return e}computeCoverFitUV(t,e){const{width:i,height:n}=this.getViewportSize(),r=i/n,o=t+e;let l=1,a=1;r>this.videoAspect?a=this.videoAspect/r:l=r/this.videoAspect;const h=1+o*2;l/=h,a/=h,this.uvOffset=[(1-l)/2,(1-a)/2],this.uvScale=[l,a],this.isCameraSource&&(this.uvOffset[0]+=this.uvScale[0],this.uvScale[0]=-this.uvScale[0])}}const me=`#version 300 es
|
|
4
4
|
in vec2 aPosition;
|
|
5
5
|
|
|
6
6
|
// UV coordinates for cover-fit + overscan.
|
|
@@ -29,7 +29,7 @@ void main() {
|
|
|
29
29
|
vUv = aPosition * 0.5 + 0.5;
|
|
30
30
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
31
31
|
}
|
|
32
|
-
`,
|
|
32
|
+
`,pe=`#version 300 es
|
|
33
33
|
precision highp float;
|
|
34
34
|
|
|
35
35
|
// BILATERAL_RADIUS is injected as a #define at compile time.
|
|
@@ -67,7 +67,7 @@ void main() {
|
|
|
67
67
|
|
|
68
68
|
fragColor = vec4(totalDepth / totalWeight, 0.0, 0.0, 1.0);
|
|
69
69
|
}
|
|
70
|
-
`,
|
|
70
|
+
`,ge=`#version 300 es
|
|
71
71
|
precision highp float;
|
|
72
72
|
|
|
73
73
|
// ---- Uniforms ----
|
|
@@ -505,10 +505,10 @@ void main() {
|
|
|
505
505
|
accum /= 7.0;
|
|
506
506
|
fragColor = vec4(accum, 0.0, 0.0, 1.0);
|
|
507
507
|
}
|
|
508
|
-
`,B={contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4,blurRadius:.01,glowColor:[1,.95,.85],glowRadius:.02,glowSoftness:.6,tiltEnabled:!1,tiltHalfTanFov:Math.tan(50*Math.PI/360),tiltTransitionWidth:.3*4.5,tiltPeakIntensity:.8},
|
|
509
|
-
#define BILATERAL_RADIUS ${t}`),
|
|
510
|
-
#define MAX_POM_STEPS ${ye}`),e=G(s,s.VERTEX_SHADER,ge),n=G(s,s.FRAGMENT_SHADER,t),i=lt(s,e,n),r=ut(s,i,Se);return{name:"depth-effect",program:i,uniforms:r,setStaticUniforms(o,l,a,h){o.useProgram(i),o.uniform1i(r.uImage,0),o.uniform1i(r.uDepth,1),o.uniform1f(r.uStrength,l.parallaxStrength),o.uniform1i(r.uPomEnabled,l.pomEnabled?1:0),o.uniform1i(r.uPomSteps,l.pomSteps),o.uniform1f(r.uContrastLow,l.contrastLow),o.uniform1f(r.uContrastHigh,l.contrastHigh),o.uniform1f(r.uVerticalReduction,l.verticalReduction),o.uniform1f(r.uDofStart,l.dofStart),o.uniform1f(r.uDofStrength,l.dofStrength),o.uniform2f(r.uImageTexelSize,1/a,1/h),o.uniform1i(r.uDisplacementCurve,3),o.uniform1i(r.uBlurCurve,4),o.uniform1i(r.uCurvesEnabled,0),o.uniform1f(r.uBlurRadius,l.blurRadius),o.uniform1f(r.uFocalBandOffset,0),o.uniform1i(r.uGlowCurve,5),o.uniform1i(r.uGlowEnabled,0),o.uniform3f(r.uGlowColor,l.glowColor[0],l.glowColor[1],l.glowColor[2]),o.uniform1f(r.uGlowRadius,l.glowRadius),o.uniform1f(r.uGlowSoftness,l.glowSoftness),o.uniform1i(r.uGlowBlurred,8),o.uniform1i(r.uColorShiftCurve,6),o.uniform1i(r.uColorShiftEnabled,0),o.uniform1f(r.uColorShiftHue,0),o.uniform1f(r.uColorShiftSaturation,1),o.uniform1f(r.uColorShiftBrightness,1),o.uniform1f(r.uColorShiftTintStrength,0),o.uniform3f(r.uColorShiftTintColor,.7,.8,.9),o.uniform1i(r.uTiltEnabled,l.tiltEnabled?1:0),o.uniform1f(r.uTiltHalfTanFov,l.tiltHalfTanFov),o.uniform1f(r.uTiltTransitionWidth,l.tiltTransitionWidth),o.uniform1f(r.uTiltPeakIntensity,l.tiltPeakIntensity),o.uniform3f(r.uTiltPlaneNormal,0,0,1),o.uniform1f(r.uTiltPlaneD,2.75)},updateUvTransform(o,l,a){o.useProgram(i),o.uniform2f(r.uUvOffset,l[0],l[1]),o.uniform2f(r.uUvScale,a[0],a[1])},dispose(o){o.deleteProgram(i)}}}class Re extends ct{gl=null;quadVao=null;bilateralPass=null;effectPass=null;textures=new Lt;videoSlot;filteredDepthSlot;rawDepthSlot;displacementLutSlot;blurLutSlot;glowLutSlot;colorShiftLutSlot;glowBlurHorizSlot;glowBlurResultSlot;glowBlurHPass=null;glowBlurVPass=null;glowEnabled=!1;config;constructor(t,e){super(t),this.videoSlot=this.textures.register("video"),this.filteredDepthSlot=this.textures.register("filteredDepth"),this.rawDepthSlot=this.textures.register("rawDepth"),this.displacementLutSlot=this.textures.register("displacementLut"),this.blurLutSlot=this.textures.register("blurLut"),this.glowLutSlot=this.textures.register("glowLut"),this.colorShiftLutSlot=this.textures.register("colorShiftLut"),this.glowBlurHorizSlot=this.textures.register("glowBlurHoriz"),this.glowBlurResultSlot=this.textures.register("glowBlurResult"),this.config={parallaxStrength:e.parallaxStrength,pomEnabled:e.pomEnabled,pomSteps:e.pomSteps,overscanPadding:e.overscanPadding,contrastLow:e.contrastLow??B.contrastLow,contrastHigh:e.contrastHigh??B.contrastHigh,verticalReduction:e.verticalReduction??B.verticalReduction,dofStart:e.dofStart??B.dofStart,dofStrength:e.dofStrength??B.dofStrength,blurRadius:e.blurRadius??B.blurRadius,glowColor:e.glowColor??[...B.glowColor],glowRadius:e.glowRadius??B.glowRadius,glowSoftness:e.glowSoftness??B.glowSoftness,tiltEnabled:e.tiltEnabled??B.tiltEnabled,tiltHalfTanFov:e.tiltHalfTanFov??B.tiltHalfTanFov,tiltTransitionWidth:e.tiltTransitionWidth??B.tiltTransitionWidth,tiltPeakIntensity:e.tiltPeakIntensity??B.tiltPeakIntensity};const n=this.canvas.getContext("webgl2",{antialias:!1,alpha:!1,desynchronized:!0,powerPreference:"high-performance"});if(!n)throw new Error("WebGL 2 is not supported.");this.gl=n,this.qualityParams=It(n,e.quality),"drawingBufferColorSpace"in n&&(n.drawingBufferColorSpace="srgb"),n.clearColor(0,0,0,1),n.pixelStorei(n.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.setupResizeHandling()}initialize(t,e,n){const i=this.gl;if(i){if(this.disposeTextures(),this.isCameraSource=t.type==="camera",this.videoAspect=t.width/t.height,this.clampDepthDimensions(e,n,this.qualityParams.depthMaxDim),this.videoSlot.texture=i.createTexture(),i.activeTexture(i.TEXTURE0+this.videoSlot.unit),i.bindTexture(i.TEXTURE_2D,this.videoSlot.texture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),this.rawDepthSlot.texture=i.createTexture(),i.activeTexture(i.TEXTURE0+this.rawDepthSlot.unit),i.bindTexture(i.TEXTURE_2D,this.rawDepthSlot.texture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.texStorage2D(i.TEXTURE_2D,1,i.R8,e,n),this.filteredDepthSlot.texture=i.createTexture(),i.activeTexture(i.TEXTURE0+this.filteredDepthSlot.unit),i.bindTexture(i.TEXTURE_2D,this.filteredDepthSlot.texture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.texStorage2D(i.TEXTURE_2D,1,i.R8,e,n),this.bilateralPass&&this.filteredDepthSlot.texture&&this.bilateralPass.initFBO(i,this.filteredDepthSlot.texture,e,n),this.glowBlurHPass&&this.glowBlurVPass){const r=this.depthWidth,o=this.depthHeight;this.glowBlurHPass.resize(i,r,o),this.glowBlurVPass.resize(i,r,o),this.glowBlurHorizSlot.texture=this.glowBlurHPass.outputs[0].texture,this.glowBlurResultSlot.texture=this.glowBlurVPass.outputs[0].texture,i.useProgram(this.glowBlurHPass.program),i.uniform1i(this.glowBlurHPass.uniforms.uDepth,this.filteredDepthSlot.unit),i.uniform1i(this.glowBlurHPass.uniforms.uGlowCurve,this.glowLutSlot.unit),i.uniform2f(this.glowBlurHPass.uniforms.uBlurDir,1,0),i.uniform2f(this.glowBlurHPass.uniforms.uTexelSize,1/r,1/o),i.uniform1f(this.glowBlurHPass.uniforms.uGlowRadius,this.config.glowRadius),i.useProgram(this.glowBlurVPass.program),i.uniform1i(this.glowBlurVPass.uniforms.uHorizResult,this.glowBlurHorizSlot.unit),i.uniform2f(this.glowBlurVPass.uniforms.uBlurDir,0,1),i.uniform2f(this.glowBlurVPass.uniforms.uTexelSize,1/r,1/o),i.uniform1f(this.glowBlurVPass.uniforms.uGlowRadius,this.config.glowRadius)}this.effectPass&&this.effectPass.setStaticUniforms(i,this.config,t.width,t.height),this.recalculateViewportLayout()}}updateConfig(t){const e=this.gl;if(!e||!this.effectPass)return;t.parallaxStrength!==void 0&&(this.config.parallaxStrength=t.parallaxStrength),t.pomEnabled!==void 0&&(this.config.pomEnabled=t.pomEnabled),t.pomSteps!==void 0&&(this.config.pomSteps=t.pomSteps),t.overscanPadding!==void 0&&(this.config.overscanPadding=t.overscanPadding),t.contrastLow!==void 0&&(this.config.contrastLow=t.contrastLow),t.contrastHigh!==void 0&&(this.config.contrastHigh=t.contrastHigh),t.verticalReduction!==void 0&&(this.config.verticalReduction=t.verticalReduction),t.dofStart!==void 0&&(this.config.dofStart=t.dofStart),t.dofStrength!==void 0&&(this.config.dofStrength=t.dofStrength),t.blurRadius!==void 0&&(this.config.blurRadius=t.blurRadius),t.glowColor!==void 0&&(this.config.glowColor=t.glowColor),t.glowRadius!==void 0&&(this.config.glowRadius=t.glowRadius),t.glowSoftness!==void 0&&(this.config.glowSoftness=t.glowSoftness),t.tiltEnabled!==void 0&&(this.config.tiltEnabled=t.tiltEnabled),t.tiltHalfTanFov!==void 0&&(this.config.tiltHalfTanFov=t.tiltHalfTanFov),t.tiltTransitionWidth!==void 0&&(this.config.tiltTransitionWidth=t.tiltTransitionWidth),t.tiltPeakIntensity!==void 0&&(this.config.tiltPeakIntensity=t.tiltPeakIntensity);const{uniforms:n,program:i}=this.effectPass;e.useProgram(i),e.uniform1f(n.uStrength,this.config.parallaxStrength),e.uniform1i(n.uPomEnabled,this.config.pomEnabled?1:0),e.uniform1i(n.uPomSteps,this.config.pomSteps),e.uniform1f(n.uContrastLow,this.config.contrastLow),e.uniform1f(n.uContrastHigh,this.config.contrastHigh),e.uniform1f(n.uVerticalReduction,this.config.verticalReduction),e.uniform1f(n.uDofStart,this.config.dofStart),e.uniform1f(n.uDofStrength,this.config.dofStrength),e.uniform1f(n.uBlurRadius,this.config.blurRadius),e.uniform3f(n.uGlowColor,this.config.glowColor[0],this.config.glowColor[1],this.config.glowColor[2]),e.uniform1f(n.uGlowRadius,this.config.glowRadius),e.uniform1f(n.uGlowSoftness,this.config.glowSoftness),e.uniform1i(n.uTiltEnabled,this.config.tiltEnabled?1:0),e.uniform1f(n.uTiltHalfTanFov,this.config.tiltHalfTanFov),e.uniform1f(n.uTiltTransitionWidth,this.config.tiltTransitionWidth),e.uniform1f(n.uTiltPeakIntensity,this.config.tiltPeakIntensity),t.glowRadius!==void 0&&(this.glowBlurHPass&&(e.useProgram(this.glowBlurHPass.program),e.uniform1f(this.glowBlurHPass.uniforms.uGlowRadius,this.config.glowRadius)),this.glowBlurVPass&&(e.useProgram(this.glowBlurVPass.program),e.uniform1f(this.glowBlurVPass.uniforms.uGlowRadius,this.config.glowRadius)),this.refreshGlowBlur()),(t.parallaxStrength!==void 0||t.overscanPadding!==void 0)&&this.recalculateViewportLayout()}updateCurveLUTs(t,e,n,i,r){const o=this.gl;if(!o||!this.effectPass)return;const l=!!(t||e),a=!!n,h=!!i;t&&this.uploadLUT(this.displacementLutSlot,t),e&&this.uploadLUT(this.blurLutSlot,e),n&&this.uploadLUT(this.glowLutSlot,n),i&&this.uploadLUT(this.colorShiftLutSlot,i),o.useProgram(this.effectPass.program),o.uniform1i(this.effectPass.uniforms.uCurvesEnabled,l?1:0),o.uniform1i(this.effectPass.uniforms.uGlowEnabled,a?1:0),o.uniform1i(this.effectPass.uniforms.uColorShiftEnabled,h?1:0);const c=this.glowEnabled!==a;if(this.glowEnabled=a,a&&(c||n)&&this.refreshGlowBlur(),h&&r){const f=this.effectPass.uniforms;o.uniform1f(f.uColorShiftHue,r.hueShift*(Math.PI/180)),o.uniform1f(f.uColorShiftSaturation,r.saturation),o.uniform1f(f.uColorShiftBrightness,r.brightness),o.uniform1f(f.uColorShiftTintStrength,r.tintStrength),o.uniform3f(f.uColorShiftTintColor,r.tintColor[0],r.tintColor[1],r.tintColor[2])}}initGPUResources(){const t=this.gl;if(!t)return;this.bilateralPass=be(t,this.qualityParams.bilateralRadius),this.effectPass=we(t);const e=Mt.replace("#version 300 es",`#version 300 es
|
|
511
|
-
#define PASS_HORIZONTAL`),n=["uDepth","uGlowCurve","uHorizResult","uTexelSize","uGlowRadius","uBlurDir"];this.glowBlurHPass=_t(t,"glow-blur-h",St,e,n,{internalFormat:t.R8,format:t.RED,type:t.UNSIGNED_BYTE,textureUnit:this.glowBlurHorizSlot.unit,width:0,height:0}),this.glowBlurVPass=_t(t,"glow-blur-v",St,Mt,n,{internalFormat:t.R8,format:t.RED,type:t.UNSIGNED_BYTE,textureUnit:this.glowBlurResultSlot.unit,width:0,height:0}),this.quadVao=Ut(t,this.effectPass.program),t.disable(t.DEPTH_TEST)}uploadLUT(t,e){const n=this.gl;n&&(n.activeTexture(n.TEXTURE0+t.unit),t.texture?n.bindTexture(n.TEXTURE_2D,t.texture):(t.texture=n.createTexture(),n.bindTexture(n.TEXTURE_2D,t.texture),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),n.texStorage2D(n.TEXTURE_2D,1,n.R8,256,1)),n.texSubImage2D(n.TEXTURE_2D,0,0,0,256,1,n.RED,n.UNSIGNED_BYTE,e))}onRenderFrame(){const t=this.gl,e=this.mediaSource;if(!t||!this.effectPass||!this.quadVao)return;const n=e?.getImageSource();if(n){if(!this.rvfcSupported&&e.isLive&&this.onDepthUpdate(e.currentTime),t.useProgram(this.effectPass.program),t.activeTexture(t.TEXTURE0+this.videoSlot.unit),t.bindTexture(t.TEXTURE_2D,this.videoSlot.texture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,n),this.readInput){const i=this.readInput();t.uniform2f(this.effectPass.uniforms.uOffset,-i.x,i.y),i.focalBandOffset!==void 0&&t.uniform1f(this.effectPass.uniforms.uFocalBandOffset,i.focalBandOffset),i.tiltPlaneNormal!==void 0&&t.uniform3f(this.effectPass.uniforms.uTiltPlaneNormal,i.tiltPlaneNormal[0],i.tiltPlaneNormal[1],i.tiltPlaneNormal[2]),i.tiltPlaneD!==void 0&&t.uniform1f(this.effectPass.uniforms.uTiltPlaneD,i.tiltPlaneD)}t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4)}}onDepthUpdate(t){const e=this.gl;if(!e||!this.readDepth||!this.rawDepthSlot.texture||!this.bilateralPass)return;const n=this.subsampleDepth(this.readDepth(t));this.bilateralPass.execute(e,this.quadVao,this.rawDepthSlot.texture,n,this.depthWidth,this.depthHeight,this.canvas.width,this.canvas.height),this.glowEnabled&&this.executeGlowBlur(e)}executeGlowBlur(t){if(!this.glowBlurHPass?.fbo||!this.glowBlurVPass?.fbo||!this.quadVao)return;const e=this.depthWidth,n=this.depthHeight;t.bindFramebuffer(t.FRAMEBUFFER,this.glowBlurHPass.fbo),t.viewport(0,0,e,n),t.useProgram(this.glowBlurHPass.program),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,this.glowBlurVPass.fbo),t.useProgram(this.glowBlurVPass.program),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,null),t.viewport(0,0,this.canvas.width,this.canvas.height)}refreshGlowBlur(){const t=this.gl;!t||!this.glowEnabled||this.depthWidth===0||this.executeGlowBlur(t)}recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:n}=this.getViewportSize(),i=Math.min(window.devicePixelRatio,this.qualityParams.dprCap),r=Math.round(e*i),o=Math.round(n*i);(this.canvas.width!==r||this.canvas.height!==o)&&(this.canvas.width=r,this.canvas.height=o,t.viewport(0,0,r,o)),this.computeCoverFitUV(this.config.parallaxStrength,this.config.overscanPadding),this.effectPass&&this.effectPass.updateUvTransform(t,this.uvOffset,this.uvScale)}disposeRenderer(){this.disposeTextures(),this.disposeGPUResources(),this.gl&&(this.gl.getExtension("WEBGL_lose_context")?.loseContext(),this.gl=null)}onContextRestored(){const t=this.canvas.getContext("webgl2");t&&(this.gl=t,t.clearColor(0,0,0,1),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.mediaSource&&this.depthWidth>0&&this.initialize(this.mediaSource,this.depthWidth,this.depthHeight),this.mediaSource&&(this.animationFrameHandle=window.requestAnimationFrame(()=>this.onRenderFrame())))}disposeTextures(){const t=this.gl;t&&this.textures.disposeAll(t)}disposeGPUResources(){const t=this.gl;t&&(this.bilateralPass&&(this.bilateralPass.dispose(t),this.bilateralPass=null),this.effectPass&&(this.effectPass.dispose(t),this.effectPass=null),this.glowBlurHPass&&(this.glowBlurHPass.dispose(t),this.glowBlurHPass=null),this.glowBlurVPass&&(this.glowBlurVPass.dispose(t),this.glowBlurVPass=null),this.quadVao&&(t.deleteVertexArray(this.quadVao),this.quadVao=null))}}async function ht(s,t={}){const{parent:e=document.body,loop:n=!0,muted:i=!0}=t,r=document.createElement("video");return r.crossOrigin="anonymous",r.setAttribute("crossorigin","anonymous"),r.playsInline=!0,r.setAttribute("playsinline",""),r.setAttribute("webkit-playsinline","true"),r.muted=i,r.defaultMuted=i,i&&r.setAttribute("muted",""),r.loop=n,r.preload="auto",r.style.display="none",r.src=s,e.appendChild(r),await Vt(r),new Ae(r)}class Ae{constructor(t){this.video=t}type="video";isLive=!0;get width(){return this.video.videoWidth}get height(){return this.video.videoHeight}get currentTime(){return this.video.currentTime}get duration(){return this.video.duration}get paused(){return this.video.paused}getImageSource(){return this.video.readyState<HTMLMediaElement.HAVE_CURRENT_DATA?null:this.video}requestVideoFrameCallback(t){return this.video.requestVideoFrameCallback(t)}cancelVideoFrameCallback(t){this.video.cancelVideoFrameCallback(t)}play(){return this.video.play()}pause(){this.video.pause()}addEventListener(t,e){this.video.addEventListener(t,e)}removeEventListener(t,e){this.video.removeEventListener(t,e)}dispose(){this.video.pause(),this.video.removeAttribute("src"),this.video.load(),this.video.remove()}}async function ft(s,t={}){const e=new Image;return e.crossOrigin="anonymous",e.src=s,await new Promise((n,i)=>{if(e.complete&&e.naturalWidth>0){n();return}e.addEventListener("load",()=>n(),{once:!0}),e.addEventListener("error",()=>i(new Error(`Failed to load image: ${s}`)),{once:!0})}),new Pe(e)}class Pe{constructor(t){this.img=t}type="image";isLive=!1;currentTime=0;duration=0;paused=!1;get width(){return this.img.naturalWidth}get height(){return this.img.naturalHeight}getImageSource(){return this.img}dispose(){this.img.removeAttribute("src")}}async function Bt(s={video:!0},t={}){const{parent:e=document.body}=t,n=await navigator.mediaDevices.getUserMedia(s),i=document.createElement("video");return i.playsInline=!0,i.setAttribute("playsinline",""),i.muted=!0,i.defaultMuted=!0,i.style.display="none",i.srcObject=n,e.appendChild(i),await Vt(i),await i.play(),new De(i,n)}class De{constructor(t,e){this.video=t,this.stream=e}type="camera";isLive=!0;duration=1/0;get width(){return this.video.videoWidth}get height(){return this.video.videoHeight}get currentTime(){return this.video.currentTime}get paused(){return this.video.paused}getImageSource(){return this.video.readyState<HTMLMediaElement.HAVE_CURRENT_DATA?null:this.video}requestVideoFrameCallback(t){return this.video.requestVideoFrameCallback(t)}cancelVideoFrameCallback(t){this.video.cancelVideoFrameCallback(t)}play(){return this.video.play()}pause(){this.video.pause()}addEventListener(t,e){this.video.addEventListener(t,e)}removeEventListener(t,e){this.video.removeEventListener(t,e)}dispose(){this.video.pause(),this.video.srcObject=null,this.video.remove();for(const t of this.stream.getTracks())t.stop()}}async function Vt(s){s.readyState>=HTMLMediaElement.HAVE_METADATA||await new Promise((t,e)=>{const n=()=>{r(),t()},i=()=>{r(),e(new Error("Failed to load video metadata."))},r=()=>{s.removeEventListener("loadedmetadata",n),s.removeEventListener("error",i)};s.addEventListener("loadedmetadata",n),s.addEventListener("error",i),s.load()})}const Z=518;async function Fe(){return await import("onnxruntime-web/webgpu")}class Ce{constructor(t,e){this.depthWidth=t,this.depthHeight=e;const n=t*e;this.frontBuffer=new Uint8Array(n),this.frontBuffer.fill(128),this.backBuffer=new Uint8Array(n),this.backBuffer.fill(128),this.readyPromise=new Promise(i=>{this.readyResolve=i})}ort=null;session=null;inputName="";outputName="";frontBuffer;backBuffer;inferenceInFlight=!1;readyResolve=null;readyPromise;captureCanvas=null;captureCtx=null;preprocessWorker=null;disposed=!1;async init(t,e){const n=await Fe();if(this.ort=n,this.captureCanvas=document.createElement("canvas"),this.captureCanvas.width=Z,this.captureCanvas.height=Z,this.captureCtx=this.captureCanvas.getContext("2d",{willReadFrequently:!0}),!this.captureCtx)throw new Error("[DepthEstimator] Failed to create 2D canvas context.");e?.({receivedBytes:0,totalBytes:null,fraction:0,label:"Downloading depth model…"});const i=await Ue(t,e);e?.({receivedBytes:i.byteLength,totalBytes:i.byteLength,fraction:1,label:"Initialising depth model…"});let r;try{r=await n.InferenceSession.create(i,{executionProviders:["webgpu"]}),console.log("[DepthEstimator] Using WebGPU execution provider")}catch(o){console.warn("[DepthEstimator] WebGPU EP unavailable, falling back to WASM:",o),n.env.wasm.proxy=!0,r=await n.InferenceSession.create(i,{executionProviders:["wasm"]}),console.log("[DepthEstimator] Using WASM execution provider (proxy worker)")}this.session=r,this.inputName=r.inputNames[0],this.outputName=r.outputNames[0],this.preprocessWorker=new Worker(new URL("/assets/preprocess-worker-wra-uI6w.js",bt&&bt.tagName.toUpperCase()==="SCRIPT"&&bt.src||new URL("layershift.js",document.baseURI).href),{type:"module"}),this.readyResolve?.(),this.readyResolve=null}waitUntilReady(){return this.readyPromise}submitFrame(t){this.inferenceInFlight||!this.session||this.disposed||(this.inferenceInFlight=!0,this.runInference(t))}async submitFrameAndWait(t){return!this.session||this.disposed?this.frontBuffer:(await this.runInference(t),this.frontBuffer)}getLatestDepth(){return this.frontBuffer}dispose(){this.disposed=!0,this.session?.release(),this.session=null,this.ort=null,this.captureCanvas=null,this.captureCtx=null,this.preprocessWorker?.terminate(),this.preprocessWorker=null}async runInference(t){try{if(!this.session||!this.captureCtx||!this.ort||!this.preprocessWorker)return;this.captureCtx.drawImage(t,0,0,Z,Z);const e=this.captureCtx.getImageData(0,0,Z,Z),n=await this.workerPreprocess(e.data.buffer,e.width,e.height),i=new this.ort.Tensor("float32",new Float32Array(n),[1,3,e.height,e.width]),o=(await this.session.run({[this.inputName]:i}))[this.outputName],l=o.data,a=o.dims,h=a.length===3?a[1]:a[2],c=a.length===3?a[2]:a[3],f=await this.workerPostprocess(l.slice(0).buffer,c,h);this.backBuffer.set(new Uint8Array(f));const u=this.frontBuffer;this.frontBuffer=this.backBuffer,this.backBuffer=u}catch(e){console.error("[DepthEstimator] Inference failed:",e)}finally{this.inferenceInFlight=!1}}workerPreprocess(t,e,n){return new Promise((i,r)=>{if(!this.preprocessWorker){r(new Error("Worker not ready"));return}const o=a=>{this.preprocessWorker?.removeEventListener("message",o),a.data.type==="preprocessed"?i(a.data.float32):a.data.type==="error"&&r(new Error(a.data.message))};this.preprocessWorker.addEventListener("message",o);const l=t.slice(0);this.preprocessWorker.postMessage({type:"preprocess",pixels:l,width:e,height:n},[l])})}workerPostprocess(t,e,n){return new Promise((i,r)=>{if(!this.preprocessWorker){r(new Error("Worker not ready"));return}const o=a=>{this.preprocessWorker?.removeEventListener("message",o),a.data.type==="postprocessed"?i(a.data.depth):a.data.type==="error"&&r(new Error(a.data.message))};this.preprocessWorker.addEventListener("message",o);const l=t.slice(0);this.preprocessWorker.postMessage({type:"postprocess",depthFloat:l,srcW:e,srcH:n,dstW:this.depthWidth,dstH:this.depthHeight},[l])})}}async function dt(s,t,e,n){const i=new Ce(t,e);return await i.init(s,n),i}async function Ue(s,t){const e=await fetch(s);if(!e.ok)throw new Error(`[DepthEstimator] Failed to fetch model (${e.status} ${e.statusText}).`);const n=e.headers.get("content-length"),i=n?Number(n):null,r=e.body;if(!r){const f=await e.arrayBuffer();return t?.({receivedBytes:f.byteLength,totalBytes:f.byteLength,fraction:1,label:"Downloading depth model…"}),f}const o=[];let l=0;const a=r.getReader();for(;;){const{done:f,value:u}=await a.read();if(f)break;u&&(o.push(u),l+=u.byteLength,t?.({receivedBytes:l,totalBytes:i,fraction:i?Math.min(l/i,1):0,label:"Downloading depth model…"}))}const h=new Uint8Array(l);let c=0;for(const f of o)h.set(f,c),c+=f.byteLength;return h.buffer}const kt={sensitivityX:.4,sensitivityY:1,lerpFactor:.08};function yt(s,t){const e=s.points;if(e.length===0)return 0;if(e.length===1||t<=e[0].x)return e[0].y;if(t>=e[e.length-1].x)return e[e.length-1].y;let n=0;for(;n<e.length-1&&e[n+1].x<t;)n++;const i=e[n],r=e[n+1],o=(t-i.x)/(r.x-i.x);switch(s.interpolation){case"step":return i.y;case"linear":return i.y+(r.y-i.y)*o;case"smooth":{const l=o*o*(3-2*o);return i.y+(r.y-i.y)*l}default:return i.y+(r.y-i.y)*o}}function mt(s,t=256){const e=new Uint8Array(t);for(let n=0;n<t;n++){const i=n/(t-1);e[n]=Math.round(yt(s,i)*255)}return e}function q(s,t){return s.find(e=>e.channel===t&&e.enabled)}function Ot(s,t){const e=q(s,"displacement"),n=q(s,"blur"),i=q(s,"glow"),r=e?.params;let o=.6,l=0;if(n){const a=n.curve;for(let h=0;h<=1;h+=.01)if(yt(a,h)>.01){o=h;break}l=yt(a,1)}return{parallaxStrength:r?.strength??.05,pomEnabled:r?.pomEnabled??!0,pomSteps:r?.pomSteps??16,contrastLow:t.contrastLow,contrastHigh:t.contrastHigh,verticalReduction:t.verticalReduction,dofStart:o,dofStrength:l,blurRadius:n?.params?.maxRadius??.01,glowColor:i?.params?.color??[1,.95,.85],glowRadius:i?.params?.radius??.02,glowSoftness:i?.params?.softness??.6,tiltEnabled:n?.params?.tiltEnabled??!1,tiltHalfTanFov:Math.tan((n?.params?.tiltFov??50)*Math.PI/360),tiltTransitionWidth:(n?.params?.focalWidth??.3)*4.5,tiltPeakIntensity:n?.params?.peakIntensity??.8}}function Ht(s){const t=q(s,"displacement"),e=q(s,"blur"),n=q(s,"glow"),i=q(s,"color-shift"),r=i?.params;return{displacementLUT:t?mt(t.curve):null,blurLUT:e?mt(e.curve):null,glowLUT:n?mt(n.curve):null,colorShiftLUT:i?mt(i.curve):null,colorShiftParams:r?{hueShift:r.hueShift??0,saturation:r.saturation??1,brightness:r.brightness??1,tintStrength:r.tintStrength??0,tintColor:r.tintColor??[.7,.8,.9]}:null}}class Nt{abortController=null;initialized=!1;initializing=!1;element;constructor(t){this.element=t}onConnected(){this.element.setupShadowDOM(),this.tryInit()}onDisconnected(){this.cancelInit(),this.element.doDispose(),this.initialized=!1}onAttributeChanged(t,e,n){this.element.reinitAttributes.includes(t)&&e!==n&&(this.initialized?(this.cancelInit(),this.element.doDispose(),this.initialized=!1,this.element.setupShadowDOM(),this.tryInit()):this.initializing||this.tryInit())}get isInitialized(){return this.initialized}markInitialized(){this.initialized=!0,this.initializing=!1}async tryInit(){if(this.initializing)return;const t=this.element;if(!t.isConnected)return;if(t.canInit){if(!t.canInit())return}else for(const n of t.reinitAttributes)if(!t.getAttribute(n))return;this.cancelInit();const e=new AbortController;this.abortController=e,this.initializing=!0;try{if(await t.doInit(e.signal),e.signal.aborted){this.initializing=!1;return}}catch{this.initializing=!1}}cancelInit(){this.abortController?.abort(),this.abortController=null,this.initializing=!1}}const Y={parallaxX:.4,parallaxY:1,parallaxMax:30,overscan:.05,autoplay:!0,loop:!0,muted:!0},$=512,K=512;class pt extends HTMLElement{static TAG_NAME="layershift-effect";static get observedAttributes(){return["src","depth-src","depth-meta","depth-model","source-type","config","parallax-x","parallax-y","parallax-max","layers","overscan","quality","gpu-backend","autoplay","loop","muted"]}reinitAttributes=["src","depth-src","depth-meta","depth-model","source-type","config"];canInit(){if(this.sourceType==="camera")return!0;const t=!!this.getAttribute("src"),e=!!this.getAttribute("depth-src")&&!!this.getAttribute("depth-meta"),n=!!this.getAttribute("depth-model");return t&&(e||n)}shadow;container=null;renderer=null;_input={x:0,y:0};source=null;depthEstimator=null;loopCount=0;lifecycle;depthFallback=null;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.lifecycle=new Nt(this)}get input(){return{x:this._input.x,y:this._input.y}}set input(t){this._input.x=t.x,this._input.y=t.y}getAttrFloat(t,e){const n=this.getAttribute(t);if(n===null)return e;const i=parseFloat(n);return Number.isFinite(i)?i:e}getAttrBool(t,e){if(!this.hasAttribute(t))return e;const n=this.getAttribute(t);return!(n==="false"||n==="0")}get parallaxX(){return this.getAttrFloat("parallax-x",Y.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",Y.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",Y.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",Y.overscan)}get quality(){const t=this.getAttribute("quality");if(t==="auto"||t==="high"||t==="medium"||t==="low")return t}get gpuBackend(){return"webgl2"}get sourceType(){const t=this.getAttribute("source-type");return t==="camera"?"camera":t==="image"?"image":"video"}get depthModel(){return this.getAttribute("depth-model")}get shouldAutoplay(){return this.getAttrBool("autoplay",Y.autoplay)}get shouldLoop(){return this.getAttrBool("loop",Y.loop)}get shouldMute(){return this.getAttrBool("muted",Y.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachSourceEventListeners(t){t.addEventListener&&(t.addEventListener("play",(()=>{this.emit("layershift-effect:play",{currentTime:t.currentTime})})),t.addEventListener("pause",(()=>{this.emit("layershift-effect:pause",{currentTime:t.currentTime})})),t.addEventListener("ended",(()=>{this.loopCount+=1,this.emit("layershift-effect:loop",{loopCount:this.loopCount})})))}connectedCallback(){this.lifecycle.onConnected()}disconnectedCallback(){this.lifecycle.onDisconnected()}attributeChangedCallback(t,e,n){this.lifecycle.onAttributeChanged(t,e,n)}setupShadowDOM(){this.shadow.innerHTML="";const t=document.createElement("style");t.textContent=`
|
|
508
|
+
`,B={contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4,blurRadius:.01,glowColor:[1,.95,.85],glowRadius:.02,glowSoftness:.6,tiltEnabled:!1,tiltHalfTanFov:Math.tan(50*Math.PI/360),tiltTransitionWidth:.3*4.5,tiltPeakIntensity:.8},ve=["uRawDepth","uTexelSize","uSpatialSigma2"],xe={2:2.25,1:.5625};function Te(s,t){const e=pe.replace("#version 300 es",`#version 300 es
|
|
509
|
+
#define BILATERAL_RADIUS ${t}`),i=G(s,s.VERTEX_SHADER,St),n=G(s,s.FRAGMENT_SHADER,e),r=lt(s,i,n),o=ut(s,r,ve),l=xe[t]??2.25;let a=null;const h={name:"bilateral-filter",program:r,uniforms:o,fbo:null,outputs:[],width:0,height:0,resize(c,f,u){},initFBO(c,f,u,x){a&&c.deleteFramebuffer(a),h.width=u,h.height=x,a=c.createFramebuffer(),h.fbo=a,c.bindFramebuffer(c.FRAMEBUFFER,a),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,f,0),c.bindFramebuffer(c.FRAMEBUFFER,null),c.useProgram(r),c.uniform1i(o.uRawDepth,2),c.uniform2f(o.uTexelSize,1/u,1/x),c.uniform1f(o.uSpatialSigma2,l)},execute(c,f,u,x,p,d,y,b){a&&(c.activeTexture(c.TEXTURE2),c.bindTexture(c.TEXTURE_2D,u),c.texSubImage2D(c.TEXTURE_2D,0,0,0,p,d,c.RED,c.UNSIGNED_BYTE,x),c.bindFramebuffer(c.FRAMEBUFFER,a),c.viewport(0,0,p,d),c.useProgram(r),c.bindVertexArray(f),c.drawArrays(c.TRIANGLE_STRIP,0,4),c.bindFramebuffer(c.FRAMEBUFFER,null),c.viewport(0,0,y,b))},dispose(c){a&&(c.deleteFramebuffer(a),a=null,h.fbo=null),c.deleteProgram(r)}};return h}const Ee=["uImage","uDepth","uOffset","uStrength","uPomEnabled","uPomSteps","uContrastLow","uContrastHigh","uVerticalReduction","uDofStart","uDofStrength","uImageTexelSize","uUvOffset","uUvScale","uDisplacementCurve","uBlurCurve","uCurvesEnabled","uBlurRadius","uFocalBandOffset","uGlowCurve","uGlowEnabled","uGlowColor","uGlowRadius","uGlowSoftness","uGlowBlurred","uColorShiftCurve","uColorShiftEnabled","uColorShiftHue","uColorShiftSaturation","uColorShiftBrightness","uColorShiftTintStrength","uColorShiftTintColor","uTiltEnabled","uTiltHalfTanFov","uTiltTransitionWidth","uTiltPeakIntensity","uTiltPlaneNormal","uTiltPlaneD"],be=64;function Se(s){const t=ge.replace("#version 300 es",`#version 300 es
|
|
510
|
+
#define MAX_POM_STEPS ${be}`),e=G(s,s.VERTEX_SHADER,me),i=G(s,s.FRAGMENT_SHADER,t),n=lt(s,e,i),r=ut(s,n,Ee);return{name:"depth-effect",program:n,uniforms:r,setStaticUniforms(o,l,a,h){o.useProgram(n),o.uniform1i(r.uImage,0),o.uniform1i(r.uDepth,1),o.uniform1f(r.uStrength,l.parallaxStrength),o.uniform1i(r.uPomEnabled,l.pomEnabled?1:0),o.uniform1i(r.uPomSteps,l.pomSteps),o.uniform1f(r.uContrastLow,l.contrastLow),o.uniform1f(r.uContrastHigh,l.contrastHigh),o.uniform1f(r.uVerticalReduction,l.verticalReduction),o.uniform1f(r.uDofStart,l.dofStart),o.uniform1f(r.uDofStrength,l.dofStrength),o.uniform2f(r.uImageTexelSize,1/a,1/h),o.uniform1i(r.uDisplacementCurve,3),o.uniform1i(r.uBlurCurve,4),o.uniform1i(r.uCurvesEnabled,0),o.uniform1f(r.uBlurRadius,l.blurRadius),o.uniform1f(r.uFocalBandOffset,0),o.uniform1i(r.uGlowCurve,5),o.uniform1i(r.uGlowEnabled,0),o.uniform3f(r.uGlowColor,l.glowColor[0],l.glowColor[1],l.glowColor[2]),o.uniform1f(r.uGlowRadius,l.glowRadius),o.uniform1f(r.uGlowSoftness,l.glowSoftness),o.uniform1i(r.uGlowBlurred,8),o.uniform1i(r.uColorShiftCurve,6),o.uniform1i(r.uColorShiftEnabled,0),o.uniform1f(r.uColorShiftHue,0),o.uniform1f(r.uColorShiftSaturation,1),o.uniform1f(r.uColorShiftBrightness,1),o.uniform1f(r.uColorShiftTintStrength,0),o.uniform3f(r.uColorShiftTintColor,.7,.8,.9),o.uniform1i(r.uTiltEnabled,l.tiltEnabled?1:0),o.uniform1f(r.uTiltHalfTanFov,l.tiltHalfTanFov),o.uniform1f(r.uTiltTransitionWidth,l.tiltTransitionWidth),o.uniform1f(r.uTiltPeakIntensity,l.tiltPeakIntensity),o.uniform3f(r.uTiltPlaneNormal,0,0,1),o.uniform1f(r.uTiltPlaneD,2.75)},updateUvTransform(o,l,a){o.useProgram(n),o.uniform2f(r.uUvOffset,l[0],l[1]),o.uniform2f(r.uUvScale,a[0],a[1])},dispose(o){o.deleteProgram(n)}}}class ye extends ct{gl=null;quadVao=null;bilateralPass=null;effectPass=null;textures=new Lt;videoSlot;filteredDepthSlot;rawDepthSlot;displacementLutSlot;blurLutSlot;glowLutSlot;colorShiftLutSlot;glowBlurHorizSlot;glowBlurResultSlot;glowBlurHPass=null;glowBlurVPass=null;glowEnabled=!1;config;constructor(t,e){super(t),this.videoSlot=this.textures.register("video"),this.filteredDepthSlot=this.textures.register("filteredDepth"),this.rawDepthSlot=this.textures.register("rawDepth"),this.displacementLutSlot=this.textures.register("displacementLut"),this.blurLutSlot=this.textures.register("blurLut"),this.glowLutSlot=this.textures.register("glowLut"),this.colorShiftLutSlot=this.textures.register("colorShiftLut"),this.glowBlurHorizSlot=this.textures.register("glowBlurHoriz"),this.glowBlurResultSlot=this.textures.register("glowBlurResult"),this.config={parallaxStrength:e.parallaxStrength,pomEnabled:e.pomEnabled,pomSteps:e.pomSteps,overscanPadding:e.overscanPadding,contrastLow:e.contrastLow??B.contrastLow,contrastHigh:e.contrastHigh??B.contrastHigh,verticalReduction:e.verticalReduction??B.verticalReduction,dofStart:e.dofStart??B.dofStart,dofStrength:e.dofStrength??B.dofStrength,blurRadius:e.blurRadius??B.blurRadius,glowColor:e.glowColor??[...B.glowColor],glowRadius:e.glowRadius??B.glowRadius,glowSoftness:e.glowSoftness??B.glowSoftness,tiltEnabled:e.tiltEnabled??B.tiltEnabled,tiltHalfTanFov:e.tiltHalfTanFov??B.tiltHalfTanFov,tiltTransitionWidth:e.tiltTransitionWidth??B.tiltTransitionWidth,tiltPeakIntensity:e.tiltPeakIntensity??B.tiltPeakIntensity};const i=this.canvas.getContext("webgl2",{antialias:!1,alpha:!1,desynchronized:!0,powerPreference:"high-performance"});if(!i)throw new Error("WebGL 2 is not supported.");this.gl=i,this.qualityParams=It(i,e.quality),"drawingBufferColorSpace"in i&&(i.drawingBufferColorSpace="srgb"),i.clearColor(0,0,0,1),i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.setupResizeHandling()}initialize(t,e,i){const n=this.gl;if(n){if(this.disposeTextures(),this.isCameraSource=t.type==="camera",this.videoAspect=t.width/t.height,this.clampDepthDimensions(e,i,this.qualityParams.depthMaxDim),this.videoSlot.texture=n.createTexture(),n.activeTexture(n.TEXTURE0+this.videoSlot.unit),n.bindTexture(n.TEXTURE_2D,this.videoSlot.texture),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),this.rawDepthSlot.texture=n.createTexture(),n.activeTexture(n.TEXTURE0+this.rawDepthSlot.unit),n.bindTexture(n.TEXTURE_2D,this.rawDepthSlot.texture),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),n.texStorage2D(n.TEXTURE_2D,1,n.R8,e,i),this.filteredDepthSlot.texture=n.createTexture(),n.activeTexture(n.TEXTURE0+this.filteredDepthSlot.unit),n.bindTexture(n.TEXTURE_2D,this.filteredDepthSlot.texture),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),n.texStorage2D(n.TEXTURE_2D,1,n.R8,e,i),this.bilateralPass&&this.filteredDepthSlot.texture&&this.bilateralPass.initFBO(n,this.filteredDepthSlot.texture,e,i),this.glowBlurHPass&&this.glowBlurVPass){const r=this.depthWidth,o=this.depthHeight;this.glowBlurHPass.resize(n,r,o),this.glowBlurVPass.resize(n,r,o),this.glowBlurHorizSlot.texture=this.glowBlurHPass.outputs[0].texture,this.glowBlurResultSlot.texture=this.glowBlurVPass.outputs[0].texture,n.useProgram(this.glowBlurHPass.program),n.uniform1i(this.glowBlurHPass.uniforms.uDepth,this.filteredDepthSlot.unit),n.uniform1i(this.glowBlurHPass.uniforms.uGlowCurve,this.glowLutSlot.unit),n.uniform2f(this.glowBlurHPass.uniforms.uBlurDir,1,0),n.uniform2f(this.glowBlurHPass.uniforms.uTexelSize,1/r,1/o),n.uniform1f(this.glowBlurHPass.uniforms.uGlowRadius,this.config.glowRadius),n.useProgram(this.glowBlurVPass.program),n.uniform1i(this.glowBlurVPass.uniforms.uHorizResult,this.glowBlurHorizSlot.unit),n.uniform2f(this.glowBlurVPass.uniforms.uBlurDir,0,1),n.uniform2f(this.glowBlurVPass.uniforms.uTexelSize,1/r,1/o),n.uniform1f(this.glowBlurVPass.uniforms.uGlowRadius,this.config.glowRadius)}this.effectPass&&this.effectPass.setStaticUniforms(n,this.config,t.width,t.height),this.recalculateViewportLayout()}}updateConfig(t){const e=this.gl;if(!e||!this.effectPass)return;t.parallaxStrength!==void 0&&(this.config.parallaxStrength=t.parallaxStrength),t.pomEnabled!==void 0&&(this.config.pomEnabled=t.pomEnabled),t.pomSteps!==void 0&&(this.config.pomSteps=t.pomSteps),t.overscanPadding!==void 0&&(this.config.overscanPadding=t.overscanPadding),t.contrastLow!==void 0&&(this.config.contrastLow=t.contrastLow),t.contrastHigh!==void 0&&(this.config.contrastHigh=t.contrastHigh),t.verticalReduction!==void 0&&(this.config.verticalReduction=t.verticalReduction),t.dofStart!==void 0&&(this.config.dofStart=t.dofStart),t.dofStrength!==void 0&&(this.config.dofStrength=t.dofStrength),t.blurRadius!==void 0&&(this.config.blurRadius=t.blurRadius),t.glowColor!==void 0&&(this.config.glowColor=t.glowColor),t.glowRadius!==void 0&&(this.config.glowRadius=t.glowRadius),t.glowSoftness!==void 0&&(this.config.glowSoftness=t.glowSoftness),t.tiltEnabled!==void 0&&(this.config.tiltEnabled=t.tiltEnabled),t.tiltHalfTanFov!==void 0&&(this.config.tiltHalfTanFov=t.tiltHalfTanFov),t.tiltTransitionWidth!==void 0&&(this.config.tiltTransitionWidth=t.tiltTransitionWidth),t.tiltPeakIntensity!==void 0&&(this.config.tiltPeakIntensity=t.tiltPeakIntensity);const{uniforms:i,program:n}=this.effectPass;e.useProgram(n),e.uniform1f(i.uStrength,this.config.parallaxStrength),e.uniform1i(i.uPomEnabled,this.config.pomEnabled?1:0),e.uniform1i(i.uPomSteps,this.config.pomSteps),e.uniform1f(i.uContrastLow,this.config.contrastLow),e.uniform1f(i.uContrastHigh,this.config.contrastHigh),e.uniform1f(i.uVerticalReduction,this.config.verticalReduction),e.uniform1f(i.uDofStart,this.config.dofStart),e.uniform1f(i.uDofStrength,this.config.dofStrength),e.uniform1f(i.uBlurRadius,this.config.blurRadius),e.uniform3f(i.uGlowColor,this.config.glowColor[0],this.config.glowColor[1],this.config.glowColor[2]),e.uniform1f(i.uGlowRadius,this.config.glowRadius),e.uniform1f(i.uGlowSoftness,this.config.glowSoftness),e.uniform1i(i.uTiltEnabled,this.config.tiltEnabled?1:0),e.uniform1f(i.uTiltHalfTanFov,this.config.tiltHalfTanFov),e.uniform1f(i.uTiltTransitionWidth,this.config.tiltTransitionWidth),e.uniform1f(i.uTiltPeakIntensity,this.config.tiltPeakIntensity),t.glowRadius!==void 0&&(this.glowBlurHPass&&(e.useProgram(this.glowBlurHPass.program),e.uniform1f(this.glowBlurHPass.uniforms.uGlowRadius,this.config.glowRadius)),this.glowBlurVPass&&(e.useProgram(this.glowBlurVPass.program),e.uniform1f(this.glowBlurVPass.uniforms.uGlowRadius,this.config.glowRadius)),this.refreshGlowBlur()),(t.parallaxStrength!==void 0||t.overscanPadding!==void 0)&&this.recalculateViewportLayout()}updateCurveLUTs(t,e,i,n,r){const o=this.gl;if(!o||!this.effectPass)return;const l=!!(t||e),a=!!i,h=!!n;t&&this.uploadLUT(this.displacementLutSlot,t),e&&this.uploadLUT(this.blurLutSlot,e),i&&this.uploadLUT(this.glowLutSlot,i),n&&this.uploadLUT(this.colorShiftLutSlot,n),o.useProgram(this.effectPass.program),o.uniform1i(this.effectPass.uniforms.uCurvesEnabled,l?1:0),o.uniform1i(this.effectPass.uniforms.uGlowEnabled,a?1:0),o.uniform1i(this.effectPass.uniforms.uColorShiftEnabled,h?1:0);const c=this.glowEnabled!==a;if(this.glowEnabled=a,a&&(c||i)&&this.refreshGlowBlur(),h&&r){const f=this.effectPass.uniforms;o.uniform1f(f.uColorShiftHue,r.hueShift*(Math.PI/180)),o.uniform1f(f.uColorShiftSaturation,r.saturation),o.uniform1f(f.uColorShiftBrightness,r.brightness),o.uniform1f(f.uColorShiftTintStrength,r.tintStrength),o.uniform3f(f.uColorShiftTintColor,r.tintColor[0],r.tintColor[1],r.tintColor[2])}}initGPUResources(){const t=this.gl;if(!t)return;this.bilateralPass=Te(t,this.qualityParams.bilateralRadius),this.effectPass=Se(t);const e=Mt.replace("#version 300 es",`#version 300 es
|
|
511
|
+
#define PASS_HORIZONTAL`),i=["uDepth","uGlowCurve","uHorizResult","uTexelSize","uGlowRadius","uBlurDir"];this.glowBlurHPass=_t(t,"glow-blur-h",St,e,i,{internalFormat:t.R8,format:t.RED,type:t.UNSIGNED_BYTE,textureUnit:this.glowBlurHorizSlot.unit,width:0,height:0}),this.glowBlurVPass=_t(t,"glow-blur-v",St,Mt,i,{internalFormat:t.R8,format:t.RED,type:t.UNSIGNED_BYTE,textureUnit:this.glowBlurResultSlot.unit,width:0,height:0}),this.quadVao=Ut(t,this.effectPass.program),t.disable(t.DEPTH_TEST)}uploadLUT(t,e){const i=this.gl;i&&(i.activeTexture(i.TEXTURE0+t.unit),t.texture?i.bindTexture(i.TEXTURE_2D,t.texture):(t.texture=i.createTexture(),i.bindTexture(i.TEXTURE_2D,t.texture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.texStorage2D(i.TEXTURE_2D,1,i.R8,256,1)),i.texSubImage2D(i.TEXTURE_2D,0,0,0,256,1,i.RED,i.UNSIGNED_BYTE,e))}onRenderFrame(){const t=this.gl,e=this.mediaSource;if(!t||!this.effectPass||!this.quadVao)return;const i=e?.getImageSource();if(i){if(!this.rvfcSupported&&e.isLive&&this.onDepthUpdate(e.currentTime),t.useProgram(this.effectPass.program),t.activeTexture(t.TEXTURE0+this.videoSlot.unit),t.bindTexture(t.TEXTURE_2D,this.videoSlot.texture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,i),this.readInput){const n=this.readInput();t.uniform2f(this.effectPass.uniforms.uOffset,-n.x,n.y),n.focalBandOffset!==void 0&&t.uniform1f(this.effectPass.uniforms.uFocalBandOffset,n.focalBandOffset),n.tiltPlaneNormal!==void 0&&t.uniform3f(this.effectPass.uniforms.uTiltPlaneNormal,n.tiltPlaneNormal[0],n.tiltPlaneNormal[1],n.tiltPlaneNormal[2]),n.tiltPlaneD!==void 0&&t.uniform1f(this.effectPass.uniforms.uTiltPlaneD,n.tiltPlaneD)}t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4)}}onDepthUpdate(t){const e=this.gl;if(!e||!this.readDepth||!this.rawDepthSlot.texture||!this.bilateralPass)return;const i=this.subsampleDepth(this.readDepth(t));this.bilateralPass.execute(e,this.quadVao,this.rawDepthSlot.texture,i,this.depthWidth,this.depthHeight,this.canvas.width,this.canvas.height),this.glowEnabled&&this.executeGlowBlur(e)}executeGlowBlur(t){if(!this.glowBlurHPass?.fbo||!this.glowBlurVPass?.fbo||!this.quadVao)return;const e=this.depthWidth,i=this.depthHeight;t.bindFramebuffer(t.FRAMEBUFFER,this.glowBlurHPass.fbo),t.viewport(0,0,e,i),t.useProgram(this.glowBlurHPass.program),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,this.glowBlurVPass.fbo),t.useProgram(this.glowBlurVPass.program),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,null),t.viewport(0,0,this.canvas.width,this.canvas.height)}refreshGlowBlur(){const t=this.gl;!t||!this.glowEnabled||this.depthWidth===0||this.executeGlowBlur(t)}recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:i}=this.getViewportSize(),n=Math.min(window.devicePixelRatio,this.qualityParams.dprCap),r=Math.round(e*n),o=Math.round(i*n);(this.canvas.width!==r||this.canvas.height!==o)&&(this.canvas.width=r,this.canvas.height=o,t.viewport(0,0,r,o)),this.computeCoverFitUV(this.config.parallaxStrength,this.config.overscanPadding),this.effectPass&&this.effectPass.updateUvTransform(t,this.uvOffset,this.uvScale)}disposeRenderer(){this.disposeTextures(),this.disposeGPUResources(),this.gl&&(this.gl.getExtension("WEBGL_lose_context")?.loseContext(),this.gl=null)}onContextRestored(){const t=this.canvas.getContext("webgl2");t&&(this.gl=t,t.clearColor(0,0,0,1),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.mediaSource&&this.depthWidth>0&&this.initialize(this.mediaSource,this.depthWidth,this.depthHeight),this.mediaSource&&(this.animationFrameHandle=window.requestAnimationFrame(()=>this.onRenderFrame())))}disposeTextures(){const t=this.gl;t&&this.textures.disposeAll(t)}disposeGPUResources(){const t=this.gl;t&&(this.bilateralPass&&(this.bilateralPass.dispose(t),this.bilateralPass=null),this.effectPass&&(this.effectPass.dispose(t),this.effectPass=null),this.glowBlurHPass&&(this.glowBlurHPass.dispose(t),this.glowBlurHPass=null),this.glowBlurVPass&&(this.glowBlurVPass.dispose(t),this.glowBlurVPass=null),this.quadVao&&(t.deleteVertexArray(this.quadVao),this.quadVao=null))}}async function ht(s,t={}){const{parent:e=document.body,loop:i=!0,muted:n=!0}=t,r=document.createElement("video");return r.crossOrigin="anonymous",r.setAttribute("crossorigin","anonymous"),r.playsInline=!0,r.setAttribute("playsinline",""),r.setAttribute("webkit-playsinline","true"),r.muted=n,r.defaultMuted=n,n&&r.setAttribute("muted",""),r.loop=i,r.preload="auto",r.style.display="none",r.src=s,e.appendChild(r),await Vt(r),new we(r)}class we{constructor(t){this.video=t}type="video";isLive=!0;get width(){return this.video.videoWidth}get height(){return this.video.videoHeight}get currentTime(){return this.video.currentTime}get duration(){return this.video.duration}get paused(){return this.video.paused}getImageSource(){return this.video.readyState<HTMLMediaElement.HAVE_CURRENT_DATA?null:this.video}requestVideoFrameCallback(t){return this.video.requestVideoFrameCallback(t)}cancelVideoFrameCallback(t){this.video.cancelVideoFrameCallback(t)}play(){return this.video.play()}pause(){this.video.pause()}addEventListener(t,e){this.video.addEventListener(t,e)}removeEventListener(t,e){this.video.removeEventListener(t,e)}dispose(){this.video.pause(),this.video.removeAttribute("src"),this.video.load(),this.video.remove()}}async function ft(s,t={}){const e=new Image;return e.crossOrigin="anonymous",e.src=s,await new Promise((i,n)=>{if(e.complete&&e.naturalWidth>0){i();return}e.addEventListener("load",()=>i(),{once:!0}),e.addEventListener("error",()=>n(new Error(`Failed to load image: ${s}`)),{once:!0})}),new Re(e)}class Re{constructor(t){this.img=t}type="image";isLive=!1;currentTime=0;duration=0;paused=!1;get width(){return this.img.naturalWidth}get height(){return this.img.naturalHeight}getImageSource(){return this.img}dispose(){this.img.removeAttribute("src")}}async function Bt(s={video:!0},t={}){const{parent:e=document.body}=t,i=await navigator.mediaDevices.getUserMedia(s),n=document.createElement("video");return n.playsInline=!0,n.setAttribute("playsinline",""),n.muted=!0,n.defaultMuted=!0,n.style.display="none",n.srcObject=i,e.appendChild(n),await Vt(n),await n.play(),new Ae(n,i)}class Ae{constructor(t,e){this.video=t,this.stream=e}type="camera";isLive=!0;duration=1/0;get width(){return this.video.videoWidth}get height(){return this.video.videoHeight}get currentTime(){return this.video.currentTime}get paused(){return this.video.paused}getImageSource(){return this.video.readyState<HTMLMediaElement.HAVE_CURRENT_DATA?null:this.video}requestVideoFrameCallback(t){return this.video.requestVideoFrameCallback(t)}cancelVideoFrameCallback(t){this.video.cancelVideoFrameCallback(t)}play(){return this.video.play()}pause(){this.video.pause()}addEventListener(t,e){this.video.addEventListener(t,e)}removeEventListener(t,e){this.video.removeEventListener(t,e)}dispose(){this.video.pause(),this.video.srcObject=null,this.video.remove();for(const t of this.stream.getTracks())t.stop()}}async function Vt(s){s.readyState>=HTMLMediaElement.HAVE_METADATA||await new Promise((t,e)=>{const i=()=>{r(),t()},n=()=>{r(),e(new Error("Failed to load video metadata."))},r=()=>{s.removeEventListener("loadedmetadata",i),s.removeEventListener("error",n)};s.addEventListener("loadedmetadata",i),s.addEventListener("error",n),s.load()})}const Z=518;async function Pe(){return await import("onnxruntime-web/webgpu")}class De{constructor(t,e){this.depthWidth=t,this.depthHeight=e;const i=t*e;this.frontBuffer=new Uint8Array(i),this.frontBuffer.fill(128),this.backBuffer=new Uint8Array(i),this.backBuffer.fill(128),this.readyPromise=new Promise(n=>{this.readyResolve=n})}ort=null;session=null;inputName="";outputName="";frontBuffer;backBuffer;inferenceInFlight=!1;readyResolve=null;readyPromise;captureCanvas=null;captureCtx=null;preprocessWorker=null;disposed=!1;async init(t,e){const i=await Pe();if(this.ort=i,this.captureCanvas=document.createElement("canvas"),this.captureCanvas.width=Z,this.captureCanvas.height=Z,this.captureCtx=this.captureCanvas.getContext("2d",{willReadFrequently:!0}),!this.captureCtx)throw new Error("[DepthEstimator] Failed to create 2D canvas context.");e?.({receivedBytes:0,totalBytes:null,fraction:0,label:"Downloading depth model…"});const n=await Fe(t,e);e?.({receivedBytes:n.byteLength,totalBytes:n.byteLength,fraction:1,label:"Initialising depth model…"});let r;try{r=await i.InferenceSession.create(n,{executionProviders:["webgpu"]}),console.log("[DepthEstimator] Using WebGPU execution provider")}catch(o){console.warn("[DepthEstimator] WebGPU EP unavailable, falling back to WASM:",o),i.env.wasm.proxy=!0,r=await i.InferenceSession.create(n,{executionProviders:["wasm"]}),console.log("[DepthEstimator] Using WASM execution provider (proxy worker)")}this.session=r,this.inputName=r.inputNames[0],this.outputName=r.outputNames[0],this.preprocessWorker=new Worker(new URL("/assets/preprocess-worker-wra-uI6w.js",bt&&bt.tagName.toUpperCase()==="SCRIPT"&&bt.src||new URL("layershift.js",document.baseURI).href),{type:"module"}),this.readyResolve?.(),this.readyResolve=null}waitUntilReady(){return this.readyPromise}submitFrame(t){this.inferenceInFlight||!this.session||this.disposed||(this.inferenceInFlight=!0,this.runInference(t))}async submitFrameAndWait(t){return!this.session||this.disposed?this.frontBuffer:(await this.runInference(t),this.frontBuffer)}getLatestDepth(){return this.frontBuffer}dispose(){this.disposed=!0,this.session?.release(),this.session=null,this.ort=null,this.captureCanvas=null,this.captureCtx=null,this.preprocessWorker?.terminate(),this.preprocessWorker=null}async runInference(t){try{if(!this.session||!this.captureCtx||!this.ort||!this.preprocessWorker)return;this.captureCtx.drawImage(t,0,0,Z,Z);const e=this.captureCtx.getImageData(0,0,Z,Z),i=await this.workerPreprocess(e.data.buffer,e.width,e.height),n=new this.ort.Tensor("float32",new Float32Array(i),[1,3,e.height,e.width]),o=(await this.session.run({[this.inputName]:n}))[this.outputName],l=o.data,a=o.dims,h=a.length===3?a[1]:a[2],c=a.length===3?a[2]:a[3],f=await this.workerPostprocess(l.slice(0).buffer,c,h);this.backBuffer.set(new Uint8Array(f));const u=this.frontBuffer;this.frontBuffer=this.backBuffer,this.backBuffer=u}catch(e){console.error("[DepthEstimator] Inference failed:",e)}finally{this.inferenceInFlight=!1}}workerPreprocess(t,e,i){return new Promise((n,r)=>{if(!this.preprocessWorker){r(new Error("Worker not ready"));return}const o=a=>{this.preprocessWorker?.removeEventListener("message",o),a.data.type==="preprocessed"?n(a.data.float32):a.data.type==="error"&&r(new Error(a.data.message))};this.preprocessWorker.addEventListener("message",o);const l=t.slice(0);this.preprocessWorker.postMessage({type:"preprocess",pixels:l,width:e,height:i},[l])})}workerPostprocess(t,e,i){return new Promise((n,r)=>{if(!this.preprocessWorker){r(new Error("Worker not ready"));return}const o=a=>{this.preprocessWorker?.removeEventListener("message",o),a.data.type==="postprocessed"?n(a.data.depth):a.data.type==="error"&&r(new Error(a.data.message))};this.preprocessWorker.addEventListener("message",o);const l=t.slice(0);this.preprocessWorker.postMessage({type:"postprocess",depthFloat:l,srcW:e,srcH:i,dstW:this.depthWidth,dstH:this.depthHeight},[l])})}}async function dt(s,t,e,i){const n=new De(t,e);return await n.init(s,i),n}async function Fe(s,t){const e=await fetch(s);if(!e.ok)throw new Error(`[DepthEstimator] Failed to fetch model (${e.status} ${e.statusText}).`);const i=e.headers.get("content-length"),n=i?Number(i):null,r=e.body;if(!r){const f=await e.arrayBuffer();return t?.({receivedBytes:f.byteLength,totalBytes:f.byteLength,fraction:1,label:"Downloading depth model…"}),f}const o=[];let l=0;const a=r.getReader();for(;;){const{done:f,value:u}=await a.read();if(f)break;u&&(o.push(u),l+=u.byteLength,t?.({receivedBytes:l,totalBytes:n,fraction:n?Math.min(l/n,1):0,label:"Downloading depth model…"}))}const h=new Uint8Array(l);let c=0;for(const f of o)h.set(f,c),c+=f.byteLength;return h.buffer}const kt={sensitivityX:.4,sensitivityY:1,lerpFactor:.08};function yt(s,t){const e=s.points;if(e.length===0)return 0;if(e.length===1||t<=e[0].x)return e[0].y;if(t>=e[e.length-1].x)return e[e.length-1].y;let i=0;for(;i<e.length-1&&e[i+1].x<t;)i++;const n=e[i],r=e[i+1],o=(t-n.x)/(r.x-n.x);switch(s.interpolation){case"step":return n.y;case"linear":return n.y+(r.y-n.y)*o;case"smooth":{const l=o*o*(3-2*o);return n.y+(r.y-n.y)*l}default:return n.y+(r.y-n.y)*o}}function mt(s,t=256){const e=new Uint8Array(t);for(let i=0;i<t;i++){const n=i/(t-1);e[i]=Math.round(yt(s,n)*255)}return e}function q(s,t){return s.find(e=>e.channel===t&&e.enabled)}function Ot(s,t){const e=q(s,"displacement"),i=q(s,"blur"),n=q(s,"glow"),r=e?.params;let o=.6,l=0;if(i){const a=i.curve;for(let h=0;h<=1;h+=.01)if(yt(a,h)>.01){o=h;break}l=yt(a,1)}return{parallaxStrength:r?.strength??.05,pomEnabled:r?.pomEnabled??!0,pomSteps:r?.pomSteps??16,contrastLow:t.contrastLow,contrastHigh:t.contrastHigh,verticalReduction:t.verticalReduction,dofStart:o,dofStrength:l,blurRadius:i?.params?.maxRadius??.01,glowColor:n?.params?.color??[1,.95,.85],glowRadius:n?.params?.radius??.02,glowSoftness:n?.params?.softness??.6,tiltEnabled:i?.params?.tiltEnabled??!1,tiltHalfTanFov:Math.tan((i?.params?.tiltFov??50)*Math.PI/360),tiltTransitionWidth:(i?.params?.focalWidth??.3)*4.5,tiltPeakIntensity:i?.params?.peakIntensity??.8}}function Ht(s){const t=q(s,"displacement"),e=q(s,"blur"),i=q(s,"glow"),n=q(s,"color-shift"),r=n?.params;return{displacementLUT:t?mt(t.curve):null,blurLUT:e?mt(e.curve):null,glowLUT:i?mt(i.curve):null,colorShiftLUT:n?mt(n.curve):null,colorShiftParams:r?{hueShift:r.hueShift??0,saturation:r.saturation??1,brightness:r.brightness??1,tintStrength:r.tintStrength??0,tintColor:r.tintColor??[.7,.8,.9]}:null}}class Xt{abortController=null;initialized=!1;initializing=!1;element;constructor(t){this.element=t}onConnected(){this.element.setupShadowDOM(),this.tryInit()}onDisconnected(){this.cancelInit(),this.element.doDispose(),this.initialized=!1}onAttributeChanged(t,e,i){this.element.reinitAttributes.includes(t)&&e!==i&&(this.initialized?(this.cancelInit(),this.element.doDispose(),this.initialized=!1,this.element.setupShadowDOM(),this.tryInit()):this.initializing||this.tryInit())}get isInitialized(){return this.initialized}markInitialized(){this.initialized=!0,this.initializing=!1}async tryInit(){if(this.initializing)return;const t=this.element;if(!t.isConnected)return;if(t.canInit){if(!t.canInit())return}else for(const i of t.reinitAttributes)if(!t.getAttribute(i))return;this.cancelInit();const e=new AbortController;this.abortController=e,this.initializing=!0;try{if(await t.doInit(e.signal),e.signal.aborted){this.initializing=!1;return}}catch{this.initializing=!1}}cancelInit(){this.abortController?.abort(),this.abortController=null,this.initializing=!1}}const Y={parallaxX:.4,parallaxY:1,parallaxMax:30,overscan:.05,autoplay:!0,loop:!0,muted:!0},$=512,K=512;class pt extends HTMLElement{static TAG_NAME="layershift-effect";static get observedAttributes(){return["src","map-src","map-width","map-height","map-fps","depth-model","source-type","config","parallax-x","parallax-y","parallax-max","layers","overscan","quality","gpu-backend","autoplay","loop","muted"]}reinitAttributes=["src","map-src","map-width","map-height","map-fps","depth-model","source-type","config"];canInit(){if(this.sourceType==="camera")return!0;const t=!!this.getAttribute("src"),e=!!this.getAttribute("map-src"),i=!!this.getAttribute("depth-model");return t&&(e||i)}shadow;container=null;renderer=null;_input={x:0,y:0};source=null;depthEstimator=null;loopCount=0;lifecycle;depthFallback=null;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.lifecycle=new Xt(this)}get input(){return{x:this._input.x,y:this._input.y}}set input(t){this._input.x=t.x,this._input.y=t.y}getAttrFloat(t,e){const i=this.getAttribute(t);if(i===null)return e;const n=parseFloat(i);return Number.isFinite(n)?n:e}getAttrBool(t,e){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return!(i==="false"||i==="0")}get parallaxX(){return this.getAttrFloat("parallax-x",Y.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",Y.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",Y.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",Y.overscan)}get quality(){const t=this.getAttribute("quality");if(t==="auto"||t==="high"||t==="medium"||t==="low")return t}get gpuBackend(){return"webgl2"}get sourceType(){const t=this.getAttribute("source-type");return t==="camera"?"camera":t==="image"?"image":"video"}get depthModel(){return this.getAttribute("depth-model")}get shouldAutoplay(){return this.getAttrBool("autoplay",Y.autoplay)}get shouldLoop(){return this.getAttrBool("loop",Y.loop)}get shouldMute(){return this.getAttrBool("muted",Y.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachSourceEventListeners(t){t.addEventListener&&(t.addEventListener("play",(()=>{this.emit("layershift-effect:play",{currentTime:t.currentTime})})),t.addEventListener("pause",(()=>{this.emit("layershift-effect:pause",{currentTime:t.currentTime})})),t.addEventListener("ended",(()=>{this.loopCount+=1,this.emit("layershift-effect:loop",{loopCount:this.loopCount})})))}connectedCallback(){this.lifecycle.onConnected()}disconnectedCallback(){this.lifecycle.onDisconnected()}attributeChangedCallback(t,e,i){this.lifecycle.onAttributeChanged(t,e,i)}setupShadowDOM(){this.shadow.innerHTML="";const t=document.createElement("style");t.textContent=`
|
|
512
512
|
:host {
|
|
513
513
|
display: block;
|
|
514
514
|
width: 100%;
|
|
@@ -528,34 +528,34 @@ void main() {
|
|
|
528
528
|
width: 100%;
|
|
529
529
|
height: 100%;
|
|
530
530
|
}
|
|
531
|
-
`,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async fetchFilterConfig(t){const e=this.getAttribute("config");if(!e)return null;try{const
|
|
531
|
+
`,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async fetchFilterConfig(t){const e=this.getAttribute("config");if(!e)return null;try{const i=await fetch(e,{signal:t});if(!i.ok)return console.warn(`<layershift-effect>: Failed to fetch config from "${e}" (${i.status})`),null;const n=await i.json();return{channels:n.channels??[],motion:n.motion??kt,overscanPadding:n.overscanPadding??.05,quality:n.quality??"auto"}}catch(i){return i.name==="AbortError"||console.warn("<layershift-effect>: Failed to parse config.",i),null}}buildLegacyConfig(t,e){const i=this.container?.clientWidth||e,n=this.hasAttribute("parallax-max")?this.parallaxMax/Math.max(i,1):t.parallaxStrength,r=this.hasAttribute("overscan")?this.overscan:t.overscanPadding;return{parallaxStrength:n,pomEnabled:!0,pomSteps:t.pomSteps,overscanPadding:r,quality:this.quality,contrastLow:t.contrastLow,contrastHigh:t.contrastHigh,verticalReduction:t.verticalReduction,dofStart:t.dofStart,dofStrength:t.dofStrength}}async doInit(t){if(!this.container)return;const e=this.sourceType==="camera",i=this.depthModel;try{let n,r,o=null;const l=m=>{this.emit("layershift-effect:model-progress",m)};if(e){if(n=await Bt({video:{facingMode:"user"}},{parent:this.shadow}),t.aborted){n.dispose();return}if(i){if(o=await dt(i,$,K,l),t.aborted){o.dispose(),n.dispose();return}r=N($,K)}else r=N(n.width,n.height)}else{const m=this.getAttribute("src"),T=this.getAttribute("map-src"),R=!!T,A=this.sourceType==="image"||/\.(jpe?g|png|webp|gif|avif|bmp)(\?|$)/i.test(m);if(R){const[P,F]=await Promise.all([A?ft(m):ht(m,{parent:this.shadow,loop:this.shouldLoop,muted:this.shouldMute}),Ft(T,this.getAttrFloat("map-width",512),this.getAttrFloat("map-height",512),this.getAttrFloat("map-fps",5))]);if(t.aborted){P.dispose();return}n=P,r=F}else if(i){const[P,F]=await Promise.all([A?ft(m):ht(m,{parent:this.shadow,loop:this.shouldLoop,muted:this.shouldMute}),dt(i,$,K,l)]);if(t.aborted){P.dispose(),F.dispose();return}if(n=P,o=F,A||!n.isLive){const _=n.getImageSource();if(_){const I=await o.submitFrameAndWait(_);r={width:$,height:K,fps:1,frameCount:1,frames:[I]}}else r=N($,K)}else r=N($,K)}else throw new Error("Either map-src or depth-model must be provided.")}this.source=n,this.depthEstimator=o,this.loopCount=0,this.attachSourceEventListeners(n);const a=re(r.frames,r.width,r.height),h=se(a);this.depthFallback={contrastLow:h.contrastLow,contrastHigh:h.contrastHigh,verticalReduction:h.verticalReduction};let c;if(o)c=()=>o.getLatestDepth();else{const m=new Dt(r);c=T=>m.sample(T)}if(t.aborted)return;let f,u=null,x=kt;const p=await this.fetchFilterConfig(t);if(t.aborted)return;if(p&&p.channels.length>0){const m=Ot(p.channels,{contrastLow:h.contrastLow,contrastHigh:h.contrastHigh,verticalReduction:h.verticalReduction});f={parallaxStrength:m.parallaxStrength,pomEnabled:m.pomEnabled,pomSteps:m.pomSteps,overscanPadding:p.overscanPadding,quality:p.quality,contrastLow:m.contrastLow,contrastHigh:m.contrastHigh,verticalReduction:m.verticalReduction,dofStart:m.dofStart,dofStrength:m.dofStrength,blurRadius:m.blurRadius,glowColor:m.glowColor,glowRadius:m.glowRadius,glowSoftness:m.glowSoftness,tiltEnabled:m.tiltEnabled,tiltHalfTanFov:m.tiltHalfTanFov,tiltTransitionWidth:m.tiltTransitionWidth,tiltPeakIntensity:m.tiltPeakIntensity},u=Ht(p.channels),x=p.motion}else f=this.buildLegacyConfig(h,n.width);this.renderer=new ye(this.container,f),this.renderer.initialize(n,r.width,r.height),u&&this.renderer.updateCurveLUTs(u.displacementLUT,u.blurLUT,u.glowLUT,u.colorShiftLUT,u.colorShiftParams??void 0);const d=x.tiltPlaneInput??!1,y=x.tiltPitchSensitivity??.35,b=x.tiltYawSensitivity??.15,g=p?.channels.find(m=>m.channel==="blur"&&m.enabled)?.params?.focalCenter??.5,v=o;if(this.renderer.start(n,c,()=>{const m=this._input;if(d){const A=m.y*y,P=m.x*b,F=Math.cos(A),_=Math.sin(A),I=Math.cos(P),S=Math.sin(P)*F,D=-_,U=I*F,M=.5+g*(5-.5);return{x:m.x*.3,y:m.y*.3,tiltPlaneNormal:[S,D,U],tiltPlaneD:U*M}}return{x:m.x,y:m.y}},(m,T)=>{if(v){const R=n.getImageSource();R&&v.submitFrame(R)}this.emit("layershift-effect:frame",{currentTime:m,frameNumber:T})}),!e&&n.isLive&&this.shouldAutoplay&&n.play)try{await n.play()}catch{}if(t.aborted)return;this.lifecycle.markInitialized(),this.emit("layershift-effect:ready",{videoWidth:n.width,videoHeight:n.height,duration:n.duration,depthProfile:a,derivedParams:h,motionConfig:x})}catch(n){const r=n instanceof Error?n.message:"Failed to initialize.";console.error("<layershift-effect>: Failed to initialize.",n),this.emit("layershift-effect:error",{message:r})}}get paused(){return this.renderer?this.renderer.isPaused:this.source?.paused??!0}pause(){!this.renderer||this.paused||(this.renderer.pause(),this.source?.pause?.(),this.emit("layershift-effect:pause",{currentTime:this.source?.currentTime??0}))}async play(){if(!(!this.renderer||!this.paused)){if(this.renderer.resume(),this.source?.play)try{await this.source.play()}catch{}this.emit("layershift-effect:play",{currentTime:this.source?.currentTime??0})}}updateConfig(t){if(!this.renderer)return;const e=this.depthFallback??{contrastLow:.05,contrastHigh:.95,verticalReduction:.5},i=Ot(t,e);this.renderer.updateConfig(i);const n=Ht(t);this.renderer.updateCurveLUTs(n.displacementLUT,n.blurLUT,n.glowLUT,n.colorShiftLUT,n.colorShiftParams??void 0)}doDispose(){this.renderer?.dispose(),this.renderer=null,this.depthEstimator?.dispose(),this.depthEstimator=null,this.source?.dispose(),this.source=null,this.depthFallback=null,this.loopCount=0,this.container=null}}class wt{gl;hasColorBufferFloat;maskFbo=null;maskTex=null;pingFbo=null;pingTex=null;pongFbo=null;pongTex=null;distFbo=null;distTex=null;_width=0;_height=0;_dirty=!0;constructor(t,e){this.gl=t,this.hasColorBufferFloat=e}get width(){return this._width}get height(){return this._height}get isDirty(){return this._dirty}get distanceTexture(){return this.distTex}get maskTexture(){return this.maskTex}markDirty(){this._dirty=!0}createResources(t,e,i){const n=this.gl;this.dispose();const r=Math.max(1,Math.round(t/i)),o=Math.max(1,Math.round(e/i));this._width=r,this._height=o;const l=(h,c,f,u)=>{const x=n.createFramebuffer();return n.bindFramebuffer(n.FRAMEBUFFER,x),n.bindTexture(n.TEXTURE_2D,h),n.texStorage2D(n.TEXTURE_2D,1,c,f,u),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),n.framebufferTexture2D(n.FRAMEBUFFER,n.COLOR_ATTACHMENT0,n.TEXTURE_2D,h,0),n.bindFramebuffer(n.FRAMEBUFFER,null),x};this.maskTex=n.createTexture(),this.maskFbo=l(this.maskTex,n.R8,r,o);const a=this.hasColorBufferFloat?n.RG16F:n.RGBA8;this.pingTex=n.createTexture(),this.pingFbo=l(this.pingTex,a,r,o),this.pongTex=n.createTexture(),this.pongFbo=l(this.pongTex,a,r,o),this.distTex=n.createTexture(),this.distFbo=l(this.distTex,n.RGBA8,r,o),this._dirty=!0}compute(t){const e=this.gl;if(!this.maskFbo||!this.pingFbo||!this.pongFbo||!this.distFbo)return;const i=this._width,n=this._height;if(i===0||n===0)return;e.viewport(0,0,i,n),e.disable(e.STENCIL_TEST),e.disable(e.BLEND),e.bindFramebuffer(e.FRAMEBUFFER,this.maskFbo),e.clearColor(0,0,0,1),e.clear(e.COLOR_BUFFER_BIT),e.useProgram(t.maskPass.program),e.uniform2f(t.maskPass.uniforms.uMeshScale,t.meshScaleX,t.meshScaleY),e.bindVertexArray(t.maskVao),e.drawElements(e.TRIANGLES,t.stencilIndexCount,e.UNSIGNED_SHORT,0),e.bindFramebuffer(e.FRAMEBUFFER,this.pingFbo),e.clearColor(-1,-1,0,0),e.clear(e.COLOR_BUFFER_BIT),e.useProgram(t.seedPass.program),e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,this.maskTex),e.uniform1i(t.seedPass.uniforms.uMask,5),e.uniform2f(t.seedPass.uniforms.uTexelSize,1/i,1/n),e.bindVertexArray(t.quadVao),e.drawArrays(e.TRIANGLE_STRIP,0,4);const r=wt.computeFloodIterations(i,n);e.useProgram(t.floodPass.program);let o=this.pingTex,l=this.pongFbo,a=this.pongTex;for(let h=0;h<r.length;h++){const c=r[h]/Math.max(i,n);e.bindFramebuffer(e.FRAMEBUFFER,l),e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,o),e.uniform1i(t.floodPass.uniforms.uSeedTex,5),e.uniform1f(t.floodPass.uniforms.uStepSize,c),e.bindVertexArray(t.quadVao),e.drawArrays(e.TRIANGLE_STRIP,0,4);const f=o,u=l;o=a,l=u===this.pongFbo?this.pingFbo:this.pongFbo,a=f}e.bindFramebuffer(e.FRAMEBUFFER,this.distFbo),e.clearColor(0,0,0,1),e.clear(e.COLOR_BUFFER_BIT),e.useProgram(t.distPass.program),e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,o),e.uniform1i(t.distPass.uniforms.uSeedTex,5),e.activeTexture(e.TEXTURE6),e.bindTexture(e.TEXTURE_2D,this.maskTex),e.uniform1i(t.distPass.uniforms.uMask,6),e.uniform1f(t.distPass.uniforms.uBevelWidth,t.distRange),e.bindVertexArray(t.quadVao),e.drawArrays(e.TRIANGLE_STRIP,0,4),e.activeTexture(e.TEXTURE4),e.bindTexture(e.TEXTURE_2D,this.distTex),e.bindFramebuffer(e.FRAMEBUFFER,null),this._dirty=!1}static computeFloodIterations(t,e){const i=Math.max(t,e),n=[];let r=Math.ceil(i/2);for(;r>=1;)n.push(r),r=Math.floor(r/2);return n}dispose(){const t=this.gl;this.maskTex&&(t.deleteTexture(this.maskTex),this.maskTex=null),this.maskFbo&&(t.deleteFramebuffer(this.maskFbo),this.maskFbo=null),this.pingTex&&(t.deleteTexture(this.pingTex),this.pingTex=null),this.pingFbo&&(t.deleteFramebuffer(this.pingFbo),this.pingFbo=null),this.pongTex&&(t.deleteTexture(this.pongTex),this.pongTex=null),this.pongFbo&&(t.deleteFramebuffer(this.pongFbo),this.pongFbo=null),this.distTex&&(t.deleteTexture(this.distTex),this.distTex=null),this.distFbo&&(t.deleteFramebuffer(this.distFbo),this.distFbo=null),this._width=0,this._height=0,this._dirty=!0}}const Ce=`#version 300 es
|
|
532
532
|
in vec2 aPosition;
|
|
533
533
|
uniform vec2 uMeshScale;
|
|
534
534
|
void main() {
|
|
535
535
|
gl_Position = vec4(aPosition * uMeshScale, 0.0, 1.0);
|
|
536
536
|
}
|
|
537
|
-
`,
|
|
537
|
+
`,Ue=`#version 300 es
|
|
538
538
|
precision lowp float;
|
|
539
539
|
out vec4 fragColor;
|
|
540
540
|
void main() { fragColor = vec4(0.0); }
|
|
541
|
-
`,
|
|
541
|
+
`,Le=`#version 300 es
|
|
542
542
|
in vec2 aPosition;
|
|
543
543
|
uniform vec2 uMeshScale;
|
|
544
544
|
void main() {
|
|
545
545
|
gl_Position = vec4(aPosition * uMeshScale, 0.0, 1.0);
|
|
546
546
|
}
|
|
547
|
-
`,
|
|
547
|
+
`,_e=`#version 300 es
|
|
548
548
|
precision lowp float;
|
|
549
549
|
out vec4 fragColor;
|
|
550
550
|
void main() { fragColor = vec4(1.0); }
|
|
551
|
-
`,
|
|
551
|
+
`,Ie=`#version 300 es
|
|
552
552
|
in vec2 aPosition;
|
|
553
553
|
out vec2 vUv;
|
|
554
554
|
void main() {
|
|
555
555
|
vUv = aPosition * 0.5 + 0.5;
|
|
556
556
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
557
557
|
}
|
|
558
|
-
`,
|
|
558
|
+
`,Me=`#version 300 es
|
|
559
559
|
precision highp float;
|
|
560
560
|
uniform sampler2D uMask;
|
|
561
561
|
uniform vec2 uTexelSize;
|
|
@@ -580,14 +580,14 @@ void main() {
|
|
|
580
580
|
fragSeed = vec2(-1.0);
|
|
581
581
|
}
|
|
582
582
|
}
|
|
583
|
-
`,
|
|
583
|
+
`,Be=`#version 300 es
|
|
584
584
|
in vec2 aPosition;
|
|
585
585
|
out vec2 vUv;
|
|
586
586
|
void main() {
|
|
587
587
|
vUv = aPosition * 0.5 + 0.5;
|
|
588
588
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
589
589
|
}
|
|
590
|
-
`,
|
|
590
|
+
`,Ve=`#version 300 es
|
|
591
591
|
precision highp float;
|
|
592
592
|
uniform sampler2D uSeedTex;
|
|
593
593
|
uniform float uStepSize;
|
|
@@ -616,14 +616,14 @@ void main() {
|
|
|
616
616
|
|
|
617
617
|
fragSeed = bestSeed;
|
|
618
618
|
}
|
|
619
|
-
`,
|
|
619
|
+
`,ke=`#version 300 es
|
|
620
620
|
in vec2 aPosition;
|
|
621
621
|
out vec2 vUv;
|
|
622
622
|
void main() {
|
|
623
623
|
vUv = aPosition * 0.5 + 0.5;
|
|
624
624
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
625
625
|
}
|
|
626
|
-
`,
|
|
626
|
+
`,Oe=`#version 300 es
|
|
627
627
|
precision highp float;
|
|
628
628
|
uniform sampler2D uSeedTex;
|
|
629
629
|
uniform sampler2D uMask;
|
|
@@ -648,7 +648,7 @@ void main() {
|
|
|
648
648
|
float normalized = clamp(d / max(uBevelWidth, 0.001), 0.0, 1.0);
|
|
649
649
|
fragDist = vec4(normalized, 0.0, 0.0, 1.0);
|
|
650
650
|
}
|
|
651
|
-
`,
|
|
651
|
+
`,He=`#version 300 es
|
|
652
652
|
in vec2 aPosition;
|
|
653
653
|
uniform vec2 uUvOffset;
|
|
654
654
|
uniform vec2 uUvScale;
|
|
@@ -660,7 +660,7 @@ void main() {
|
|
|
660
660
|
vScreenUv = baseUv;
|
|
661
661
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
662
662
|
}
|
|
663
|
-
`,
|
|
663
|
+
`,Xe=`#version 300 es
|
|
664
664
|
precision highp float;
|
|
665
665
|
|
|
666
666
|
#define MAX_POM_STEPS 32
|
|
@@ -791,14 +791,14 @@ void main() {
|
|
|
791
791
|
// Write lens-transformed depth to second attachment for boundary effects
|
|
792
792
|
fragDepth = vec4(lensD, 0.0, 0.0, 1.0);
|
|
793
793
|
}
|
|
794
|
-
`,
|
|
794
|
+
`,Ne=`#version 300 es
|
|
795
795
|
in vec2 aPosition;
|
|
796
796
|
out vec2 vUv;
|
|
797
797
|
void main() {
|
|
798
798
|
vUv = aPosition * 0.5 + 0.5;
|
|
799
799
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
800
800
|
}
|
|
801
|
-
`,
|
|
801
|
+
`,Ge=`#version 300 es
|
|
802
802
|
precision highp float;
|
|
803
803
|
uniform sampler2D uInteriorColor;
|
|
804
804
|
uniform sampler2D uDistField;
|
|
@@ -828,7 +828,7 @@ void main() {
|
|
|
828
828
|
|
|
829
829
|
fragColor = vec4(toSRGB(linear), color.a);
|
|
830
830
|
}
|
|
831
|
-
`,
|
|
831
|
+
`,We=`#version 300 es
|
|
832
832
|
in vec2 aPosition;
|
|
833
833
|
in vec2 aNormal;
|
|
834
834
|
uniform float uRimWidth;
|
|
@@ -851,7 +851,7 @@ void main() {
|
|
|
851
851
|
|
|
852
852
|
gl_Position = vec4(pos, 0.0, 1.0);
|
|
853
853
|
}
|
|
854
|
-
`,
|
|
854
|
+
`,ze=`#version 300 es
|
|
855
855
|
precision highp float;
|
|
856
856
|
|
|
857
857
|
uniform sampler2D uInteriorColor;
|
|
@@ -953,7 +953,7 @@ void main() {
|
|
|
953
953
|
|
|
954
954
|
fragColor = vec4(color * alpha, alpha);
|
|
955
955
|
}
|
|
956
|
-
`,
|
|
956
|
+
`,qe=`#version 300 es
|
|
957
957
|
in vec2 aPosition;
|
|
958
958
|
in vec3 aNormal3;
|
|
959
959
|
in float aLerpT; // 0 = inner (at silhouette), 1 = outer edge
|
|
@@ -969,7 +969,7 @@ void main() {
|
|
|
969
969
|
vLerpT = aLerpT;
|
|
970
970
|
gl_Position = vec4(sp, 0.0, 1.0);
|
|
971
971
|
}
|
|
972
|
-
`,
|
|
972
|
+
`,Ye=`#version 300 es
|
|
973
973
|
precision highp float;
|
|
974
974
|
uniform vec3 uLightDir3;
|
|
975
975
|
uniform vec3 uChamferColor;
|
|
@@ -1036,7 +1036,7 @@ void main() {
|
|
|
1036
1036
|
vec3 lit = base * (uChamferAmbient + (1.0 - uChamferAmbient) * diff) + vec3(spec);
|
|
1037
1037
|
fragColor = vec4(toSRGB(lit), 1.0);
|
|
1038
1038
|
}
|
|
1039
|
-
`;function $e(s){const t=[];let e=0;for(let n=0;n<s.length-2;n+=2){const i=s[n],r=s[n+1],o=s[n+2],l=s[n+3],a=o-i,h=l-r,c=Math.sqrt(a*a+h*h);if(c<1e-6)continue;const f=-h/c,u=a/c;t.push(i,r,f,u,i,r,-f,-u,o,l,f,u,o,l,f,u,i,r,-f,-u,o,l,-f,-u),e+=6}return{vertices:new Float32Array(t),count:e}}function Ke(s,t,e,n,i){if(n<=0)return{vertices:new Float32Array(0),count:0};const r=i*Math.PI/180,o=-Math.cos(r),l=Math.sin(r),a=[];let h=0;for(let c=0;c<t.length;c++){const f=t[c],p=((c+1<t.length?t[c+1]:s.length)-f)/2;if(p<3)continue;const d=p-1;let y=0;for(let T=0;T<d;T++){const w=f+T*2,A=s[w],P=s[w+1],F=s[w+2],_=s[w+3];y+=A*_-F*P}const E=y>=0?1:-1,b=[],g=[];for(let T=0;T<d;T++){const w=f+T*2,A=s[w+2]-s[w],P=s[w+3]-s[w+1],F=Math.sqrt(A*A+P*P);F<1e-8?(b.push(T>0?b[T-1]:0),g.push(T>0?g[T-1]:0)):(b.push(-P/F*E),g.push(A/F*E))}const v=[],m=[];for(let T=0;T<d;T++){const w=(T-1+d)%d;let A=b[w]+b[T],P=g[w]+g[T];const F=Math.sqrt(A*A+P*P);F>1e-8?(A/=F,P/=F):(A=b[T],P=g[T]),v.push(A),m.push(P)}for(let T=0;T<d;T++){const w=T,A=(T+1)%d,P=f+T*2,F=f+(T+1)%d*2,_=s[P],I=s[P+1],C=s[F],S=s[F+1],D=v[w]*l,U=m[w]*l,M=o,k=v[A]*l,et=m[A]*l,at=o,Et=_+v[w]*n,Qt=I+m[w]*n,Un=C+v[A]*n,Ln=S+m[A]*n;a.push(_,I,D,U,M,0),a.push(Et,Qt,D,U,M,1),a.push(C,S,k,et,at,0),a.push(C,S,k,et,at,0),a.push(Et,Qt,D,U,M,1),a.push(Un,Ln,k,et,at,1),h+=6}}return{vertices:new Float32Array(a),count:h}}class Je extends ct{gl=null;stencilPass=null;maskPass=null;jfaSeedPass=null;jfaFloodPass=null;jfaDistPass=null;interiorPass=null;compositePass=null;boundaryPass=null;chamferPass=null;quadVao=null;stencilVao=null;stencilIndexCount=0;maskVao=null;boundaryVao=null;boundaryVertexCount=0;chamferVao=null;chamferVertexCount=0;textures=new Lt;videoSlot;depthSlot;interiorFbo=null;interiorColorTex=null;interiorDepthTex=null;fboWidth=0;fboHeight=0;jfa=null;hasColorBufferFloat=!1;meshAspect=1;meshScaleX=.65;meshScaleY=.65;lightDirX=-.707;lightDirY=.707;lightDir3=[-.5,.7,-.3];config;constructor(t,e){super(t),this.config={...e},this.videoSlot=this.textures.register("video"),this.depthSlot=this.textures.register("depth");const n=this.config.bevelLightAngle*Math.PI/180;this.lightDirX=Math.cos(n),this.lightDirY=Math.sin(n);const i=this.config.lightDirection,r=Math.sqrt(i[0]*i[0]+i[1]*i[1]+i[2]*i[2]);r>1e-6&&(this.lightDir3=[i[0]/r,i[1]/r,i[2]/r]);const o=this.canvas.getContext("webgl2",{antialias:!0,alpha:!0,premultipliedAlpha:!0,stencil:!0,desynchronized:!0,powerPreference:"high-performance"});if(!o)throw new Error("WebGL 2 is not supported.");this.gl=o,this.qualityParams=It(o,e.quality),"drawingBufferColorSpace"in o&&(o.drawingBufferColorSpace="srgb"),this.hasColorBufferFloat=!!o.getExtension("EXT_color_buffer_float"),o.clearColor(0,0,0,0),o.pixelStorei(o.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.setupResizeHandling()}initialize(t,e,n,i){const r=this.gl;r&&(this.disposeTextures(),this.disposeFBO(),this.jfa&&(this.jfa.dispose(),this.jfa=null),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.isCameraSource=t.type==="camera",this.videoAspect=t.width/t.height,this.meshAspect=i.aspect,this.clampDepthDimensions(e,n,this.qualityParams.depthMaxDim),this.videoSlot.texture=r.createTexture(),r.activeTexture(r.TEXTURE0+this.videoSlot.unit),r.bindTexture(r.TEXTURE_2D,this.videoSlot.texture),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),this.depthSlot.texture=r.createTexture(),r.activeTexture(r.TEXTURE0+this.depthSlot.unit),r.bindTexture(r.TEXTURE_2D,this.depthSlot.texture),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),r.texStorage2D(r.TEXTURE_2D,1,r.R8,this.depthWidth,this.depthHeight),this.uploadStencilMesh(i),this.uploadMaskMesh(i),this.uploadBoundaryMesh(i),this.uploadChamferMesh(i),this.interiorPass&&(r.useProgram(this.interiorPass.program),r.uniform1i(this.interiorPass.uniforms.uImage,0),r.uniform1i(this.interiorPass.uniforms.uDepth,1),r.uniform1f(this.interiorPass.uniforms.uStrength,this.config.parallaxStrength),r.uniform1i(this.interiorPass.uniforms.uPomSteps,this.config.pomSteps),r.uniform1f(this.interiorPass.uniforms.uDepthPower,this.config.depthPower),r.uniform1f(this.interiorPass.uniforms.uDepthScale,this.config.depthScale),r.uniform1f(this.interiorPass.uniforms.uDepthBias,this.config.depthBias),r.uniform1f(this.interiorPass.uniforms.uContrastLow,this.config.contrastLow),r.uniform1f(this.interiorPass.uniforms.uContrastHigh,this.config.contrastHigh),r.uniform1f(this.interiorPass.uniforms.uVerticalReduction,this.config.verticalReduction),r.uniform1f(this.interiorPass.uniforms.uDofStart,this.config.dofStart),r.uniform1f(this.interiorPass.uniforms.uDofStrength,this.config.dofStrength),r.uniform2f(this.interiorPass.uniforms.uImageTexelSize,1/t.width,1/t.height),r.uniform1f(this.interiorPass.uniforms.uFogDensity,this.config.fogDensity),r.uniform3f(this.interiorPass.uniforms.uFogColor,...this.config.fogColor),r.uniform1f(this.interiorPass.uniforms.uColorShift,this.config.colorShift),r.uniform1f(this.interiorPass.uniforms.uBrightnessBias,this.config.brightnessBias)),this.compositePass&&(r.useProgram(this.compositePass.program),r.uniform1i(this.compositePass.uniforms.uInteriorColor,2),r.uniform1i(this.compositePass.uniforms.uDistField,4),r.uniform1f(this.compositePass.uniforms.uEdgeOcclusionWidth,this.config.edgeOcclusionWidth),r.uniform1f(this.compositePass.uniforms.uEdgeOcclusionStrength,this.config.edgeOcclusionStrength)),this.chamferPass&&(r.useProgram(this.chamferPass.program),r.uniform3f(this.chamferPass.uniforms.uLightDir3,...this.lightDir3),r.uniform3f(this.chamferPass.uniforms.uChamferColor,...this.config.chamferColor),r.uniform1f(this.chamferPass.uniforms.uChamferAmbient,this.config.chamferAmbient),r.uniform1f(this.chamferPass.uniforms.uChamferSpecular,this.config.chamferSpecular),r.uniform1f(this.chamferPass.uniforms.uChamferShininess,this.config.chamferShininess),r.uniform1i(this.chamferPass.uniforms.uInteriorColor,2)),this.boundaryPass&&(r.useProgram(this.boundaryPass.program),r.uniform1i(this.boundaryPass.uniforms.uInteriorColor,2),r.uniform1i(this.boundaryPass.uniforms.uInteriorDepth,3),r.uniform1i(this.boundaryPass.uniforms.uDistField,4),r.uniform1f(this.boundaryPass.uniforms.uRimIntensity,this.config.rimLightIntensity),r.uniform3f(this.boundaryPass.uniforms.uRimColor,...this.config.rimLightColor),r.uniform1f(this.boundaryPass.uniforms.uRefractionStrength,this.config.refractionStrength),r.uniform1f(this.boundaryPass.uniforms.uChromaticStrength,this.config.chromaticStrength),r.uniform1f(this.boundaryPass.uniforms.uOcclusionIntensity,this.config.occlusionIntensity),r.uniform1f(this.boundaryPass.uniforms.uEdgeThickness,this.config.edgeThickness),r.uniform1f(this.boundaryPass.uniforms.uEdgeSpecular,this.config.edgeSpecular),r.uniform3f(this.boundaryPass.uniforms.uEdgeColor,...this.config.edgeColor),r.uniform2f(this.boundaryPass.uniforms.uLightDir,this.lightDirX,this.lightDirY),r.uniform1f(this.boundaryPass.uniforms.uBevelIntensity,this.config.bevelIntensity)),this.recalculateViewportLayout())}uploadStencilMesh(t){const e=this.gl;if(!e||!this.stencilPass)return;this.stencilVao=e.createVertexArray(),e.bindVertexArray(this.stencilVao);const n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n),e.bufferData(e.ARRAY_BUFFER,t.vertices,e.STATIC_DRAW);const i=e.getAttribLocation(this.stencilPass.program,"aPosition");e.enableVertexAttribArray(i),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0);const r=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,r),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t.indices,e.STATIC_DRAW),this.stencilIndexCount=t.indices.length,e.bindVertexArray(null)}uploadMaskMesh(t){const e=this.gl;if(!e||!this.maskPass)return;this.maskVao=e.createVertexArray(),e.bindVertexArray(this.maskVao);const n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n),e.bufferData(e.ARRAY_BUFFER,t.vertices,e.STATIC_DRAW);const i=e.getAttribLocation(this.maskPass.program,"aPosition");e.enableVertexAttribArray(i),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0);const r=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,r),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t.indices,e.STATIC_DRAW),e.bindVertexArray(null)}uploadBoundaryMesh(t){const e=this.gl;if(!e||!this.boundaryPass)return;const n=$e(t.edgeVertices);if(n.count===0)return;this.boundaryVao=e.createVertexArray(),e.bindVertexArray(this.boundaryVao);const i=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,i),e.bufferData(e.ARRAY_BUFFER,n.vertices,e.STATIC_DRAW);const r=16,o=e.getAttribLocation(this.boundaryPass.program,"aPosition");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,r,0);const l=e.getAttribLocation(this.boundaryPass.program,"aNormal");l>=0&&(e.enableVertexAttribArray(l),e.vertexAttribPointer(l,2,e.FLOAT,!1,r,8)),this.boundaryVertexCount=n.count,e.bindVertexArray(null)}uploadChamferMesh(t){const e=this.gl;if(!e||!this.chamferPass||this.config.chamferWidth<=0)return;const n=Ke(t.edgeVertices,t.contourOffsets,t.contourIsHole,this.config.chamferWidth,this.config.chamferAngle);if(n.count===0)return;this.chamferVao=e.createVertexArray(),e.bindVertexArray(this.chamferVao);const i=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,i),e.bufferData(e.ARRAY_BUFFER,n.vertices,e.STATIC_DRAW);const r=24,o=e.getAttribLocation(this.chamferPass.program,"aPosition");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,r,0);const l=e.getAttribLocation(this.chamferPass.program,"aNormal3");l>=0&&(e.enableVertexAttribArray(l),e.vertexAttribPointer(l,3,e.FLOAT,!1,r,8));const a=e.getAttribLocation(this.chamferPass.program,"aLerpT");a>=0&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,1,e.FLOAT,!1,r,20)),this.chamferVertexCount=n.count,e.bindVertexArray(null)}disposeChamferGeometry(){const t=this.gl;t&&(this.chamferVao&&(t.deleteVertexArray(this.chamferVao),this.chamferVao=null),this.chamferVertexCount=0)}createFBO(t,e){const n=this.gl;if(!n)return;this.disposeFBO(),this.fboWidth=t,this.fboHeight=e,this.interiorFbo=n.createFramebuffer(),n.bindFramebuffer(n.FRAMEBUFFER,this.interiorFbo),this.interiorColorTex=n.createTexture(),n.activeTexture(n.TEXTURE2),n.bindTexture(n.TEXTURE_2D,this.interiorColorTex),n.texStorage2D(n.TEXTURE_2D,1,n.RGBA8,t,e),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),n.framebufferTexture2D(n.FRAMEBUFFER,n.COLOR_ATTACHMENT0,n.TEXTURE_2D,this.interiorColorTex,0),this.interiorDepthTex=n.createTexture(),n.activeTexture(n.TEXTURE3),n.bindTexture(n.TEXTURE_2D,this.interiorDepthTex),n.texStorage2D(n.TEXTURE_2D,1,n.RGBA8,t,e),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MIN_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_MAG_FILTER,n.LINEAR),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_S,n.CLAMP_TO_EDGE),n.texParameteri(n.TEXTURE_2D,n.TEXTURE_WRAP_T,n.CLAMP_TO_EDGE),n.framebufferTexture2D(n.FRAMEBUFFER,n.COLOR_ATTACHMENT1,n.TEXTURE_2D,this.interiorDepthTex,0),n.drawBuffers([n.COLOR_ATTACHMENT0,n.COLOR_ATTACHMENT1]);const i=n.checkFramebufferStatus(n.FRAMEBUFFER);i!==n.FRAMEBUFFER_COMPLETE&&console.error("Interior FBO incomplete:",i),n.bindFramebuffer(n.FRAMEBUFFER,null)}createJFAResources(t,e){const n=this.gl;n&&(this.jfa||(this.jfa=new wt(n,this.hasColorBufferFloat)),this.jfa.createResources(t,e,this.qualityParams.jfaDivisor))}computeDistanceField(){!this.jfa||!this.maskPass||!this.jfaSeedPass||!this.jfaFloodPass||!this.jfaDistPass||!this.maskVao||!this.quadVao||this.jfa.compute({maskPass:this.maskPass,seedPass:this.jfaSeedPass,floodPass:this.jfaFloodPass,distPass:this.jfaDistPass,maskVao:this.maskVao,quadVao:this.quadVao,meshScaleX:this.meshScaleX,meshScaleY:this.meshScaleY,stencilIndexCount:this.stencilIndexCount,distRange:Math.max(this.config.bevelWidth,this.config.edgeOcclusionWidth)})}initGPUResources(){const t=this.gl;t&&(this.stencilPass=H(t,"stencil",Le,_e,["uMeshScale"]),this.maskPass=H(t,"mask",Ie,Me,["uMeshScale"]),this.jfaSeedPass=H(t,"jfa-seed",Be,Ve,["uMask","uTexelSize"]),this.jfaFloodPass=H(t,"jfa-flood",ke,Oe,["uSeedTex","uStepSize"]),this.jfaDistPass=H(t,"jfa-dist",He,Ne,["uSeedTex","uMask","uBevelWidth"]),this.interiorPass=H(t,"interior",Xe,Ge,["uImage","uDepth","uOffset","uStrength","uPomSteps","uDepthPower","uDepthScale","uDepthBias","uContrastLow","uContrastHigh","uVerticalReduction","uDofStart","uDofStrength","uImageTexelSize","uFogDensity","uFogColor","uColorShift","uBrightnessBias","uUvOffset","uUvScale"]),this.compositePass=H(t,"composite",We,ze,["uInteriorColor","uDistField","uEdgeOcclusionWidth","uEdgeOcclusionStrength"]),this.boundaryPass=H(t,"boundary",qe,Ye,["uInteriorColor","uInteriorDepth","uDistField","uRimIntensity","uRimColor","uRimWidth","uMeshScale","uRefractionStrength","uChromaticStrength","uOcclusionIntensity","uTexelSize","uEdgeThickness","uEdgeSpecular","uEdgeColor","uLightDir","uBevelIntensity"]),this.chamferPass=H(t,"chamfer",je,Ze,["uMeshScale","uLightDir3","uChamferColor","uChamferAmbient","uChamferSpecular","uChamferShininess","uInteriorColor","uTexelSize"]),this.quadVao=Ut(t,this.interiorPass.program),t.disable(t.DEPTH_TEST))}onRenderFrame(){const t=this.gl,e=this.mediaSource;if(!t||!this.interiorPass||!this.quadVao)return;const n=e?.getImageSource();if(!n||!this.interiorFbo||!this.interiorColorTex||!this.interiorDepthTex)return;if(this.jfa?.isDirty&&this.maskVao){const o=this.qualityParams.jfaDivisor,l=Math.max(1,Math.round(this.canvas.width/o)),a=Math.max(1,Math.round(this.canvas.height/o));(this.jfa.width!==l||this.jfa.height!==a)&&this.createJFAResources(this.canvas.width,this.canvas.height),this.computeDistanceField(),t.viewport(0,0,this.canvas.width,this.canvas.height)}t.activeTexture(t.TEXTURE0+this.videoSlot.unit),t.bindTexture(t.TEXTURE_2D,this.videoSlot.texture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,n),this.rvfcSupported||this.onDepthUpdate(e.currentTime);let i=0,r=0;if(this.readInput){const o=this.readInput();i=-o.x,r=o.y}if(t.bindFramebuffer(t.FRAMEBUFFER,this.interiorFbo),t.checkFramebufferStatus(t.FRAMEBUFFER)!==t.FRAMEBUFFER_COMPLETE){t.bindFramebuffer(t.FRAMEBUFFER,null);return}t.viewport(0,0,this.fboWidth,this.fboHeight),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.interiorPass.program),t.uniform2f(this.interiorPass.uniforms.uOffset,i,r),t.activeTexture(t.TEXTURE0+this.videoSlot.unit),t.bindTexture(t.TEXTURE_2D,this.videoSlot.texture),t.activeTexture(t.TEXTURE0+this.depthSlot.unit),t.bindTexture(t.TEXTURE_2D,this.depthSlot.texture),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,null),t.clearColor(0,0,0,0),t.viewport(0,0,this.canvas.width,this.canvas.height),t.clear(t.COLOR_BUFFER_BIT|t.STENCIL_BUFFER_BIT),this.stencilVao&&this.stencilPass&&this.stencilIndexCount>0&&(t.enable(t.STENCIL_TEST),t.stencilFunc(t.ALWAYS,1,255),t.stencilOp(t.KEEP,t.KEEP,t.REPLACE),t.stencilMask(255),t.colorMask(!1,!1,!1,!1),t.useProgram(this.stencilPass.program),t.bindVertexArray(this.stencilVao),t.drawElements(t.TRIANGLES,this.stencilIndexCount,t.UNSIGNED_SHORT,0),t.colorMask(!0,!0,!0,!0)),t.stencilFunc(t.EQUAL,1,255),t.stencilMask(0),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.interiorColorTex),t.activeTexture(t.TEXTURE3),t.bindTexture(t.TEXTURE_2D,this.interiorDepthTex),t.activeTexture(t.TEXTURE4),t.bindTexture(t.TEXTURE_2D,this.jfa?.distanceTexture??null),t.useProgram(this.compositePass.program),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.disable(t.STENCIL_TEST),this.chamferVao&&this.chamferPass&&this.chamferVertexCount>0&&(t.useProgram(this.chamferPass.program),t.uniform2f(this.chamferPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform2f(this.chamferPass.uniforms.uTexelSize,1/this.canvas.width,1/this.canvas.height),t.bindVertexArray(this.chamferVao),t.drawArrays(t.TRIANGLES,0,this.chamferVertexCount)),this.boundaryVao&&this.boundaryPass&&this.boundaryVertexCount>0&&this.config.rimLightIntensity>0&&(t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.useProgram(this.boundaryPass.program),t.bindVertexArray(this.boundaryVao),t.drawArrays(t.TRIANGLES,0,this.boundaryVertexCount),t.disable(t.BLEND))}onDepthUpdate(t){const e=this.gl;if(!e||!this.readDepth||!this.depthSlot.texture)return;const n=this.subsampleDepth(this.readDepth(t));e.activeTexture(e.TEXTURE0+this.depthSlot.unit),e.bindTexture(e.TEXTURE_2D,this.depthSlot.texture),e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.depthWidth,this.depthHeight,e.RED,e.UNSIGNED_BYTE,n),this.jfa&&this.jfa.markDirty()}recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:n}=this.getViewportSize(),i=Math.min(window.devicePixelRatio,this.qualityParams.dprCap),r=Math.round(e*i),o=Math.round(n*i);(this.canvas.width!==r||this.canvas.height!==o)&&(this.canvas.width=r,this.canvas.height=o,t.viewport(0,0,r,o)),(this.fboWidth!==r||this.fboHeight!==o)&&this.createFBO(r,o),this.jfa||this.createJFAResources(r,o),this.computeCoverFitUV(this.config.parallaxStrength,this.config.overscanPadding),this.interiorPass&&(t.useProgram(this.interiorPass.program),t.uniform2f(this.interiorPass.uniforms.uUvOffset,this.uvOffset[0],this.uvOffset[1]),t.uniform2f(this.interiorPass.uniforms.uUvScale,this.uvScale[0],this.uvScale[1]));const l=e/n,a=.65;this.meshScaleX=a,this.meshScaleY=a,l>this.meshAspect?this.meshScaleX=a*(this.meshAspect/l):this.meshScaleY=a*(l/this.meshAspect),this.stencilPass&&(t.useProgram(this.stencilPass.program),t.uniform2f(this.stencilPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY)),this.boundaryPass&&(t.useProgram(this.boundaryPass.program),t.uniform2f(this.boundaryPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform1f(this.boundaryPass.uniforms.uRimWidth,this.config.rimLightWidth),t.uniform2f(this.boundaryPass.uniforms.uTexelSize,1/r,1/o)),this.chamferPass&&(t.useProgram(this.chamferPass.program),t.uniform2f(this.chamferPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY))}onContextRestored(){const t=this.canvas.getContext("webgl2",{alpha:!0,premultipliedAlpha:!0,stencil:!0});t&&(this.gl=t,this.hasColorBufferFloat=!!t.getExtension("EXT_color_buffer_float"),t.clearColor(0,0,0,0),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.recalculateViewportLayout(),this.mediaSource&&(this.animationFrameHandle=window.requestAnimationFrame(()=>this.onRenderFrame())))}disposeTextures(){const t=this.gl;t&&this.textures.disposeAll(t)}disposeFBO(){const t=this.gl;t&&(this.interiorColorTex&&(t.deleteTexture(this.interiorColorTex),this.interiorColorTex=null),this.interiorDepthTex&&(t.deleteTexture(this.interiorDepthTex),this.interiorDepthTex=null),this.interiorFbo&&(t.deleteFramebuffer(this.interiorFbo),this.interiorFbo=null),this.fboWidth=0,this.fboHeight=0)}disposeStencilGeometry(){const t=this.gl;t&&(this.stencilVao&&(t.deleteVertexArray(this.stencilVao),this.stencilVao=null),this.maskVao&&(t.deleteVertexArray(this.maskVao),this.maskVao=null),this.stencilIndexCount=0)}disposeBoundaryGeometry(){const t=this.gl;t&&(this.boundaryVao&&(t.deleteVertexArray(this.boundaryVao),this.boundaryVao=null),this.boundaryVertexCount=0)}disposeRenderer(){this.disposeTextures(),this.disposeFBO(),this.jfa&&(this.jfa.dispose(),this.jfa=null),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.disposeGPUResources(),this.gl&&(this.gl.getExtension("WEBGL_lose_context")?.loseContext(),this.gl=null)}disposeGPUResources(){const t=this.gl;if(!t)return;const e=[this.stencilPass,this.maskPass,this.jfaSeedPass,this.jfaFloodPass,this.jfaDistPass,this.interiorPass,this.compositePass,this.boundaryPass,this.chamferPass];for(const n of e)n&&n.dispose(t);this.stencilPass=null,this.maskPass=null,this.jfaSeedPass=null,this.jfaFloodPass=null,this.jfaDistPass=null,this.interiorPass=null,this.compositePass=null,this.boundaryPass=null,this.chamferPass=null,this.quadVao&&(t.deleteVertexArray(this.quadVao),this.quadVao=null)}}async function Rt(s){const t=await fetch(s);if(!t.ok)throw new Error(`Failed to fetch SVG: ${t.status} ${t.statusText}`);const e=await t.text();return Qe(e)}function Qe(s){const n=new DOMParser().parseFromString(s,"image/svg+xml").querySelector("svg");if(!n)throw new Error("No <svg> element found in document.");const i=tn(n);if(i.length===0)throw new Error("No path data found in SVG.");let r=1/0,o=1/0,l=-1/0,a=-1/0;for(const C of i)for(let S=0;S<C.length;S+=2)r=Math.min(r,C[S]),l=Math.max(l,C[S]),o=Math.min(o,C[S+1]),a=Math.max(a,C[S+1]);const h=l-r,c=a-o,f=(r+l)/2,u=(o+a)/2,x=2/Math.max(h,c),p=h/c,d=i.map(C=>{const S=[];for(let D=0;D<C.length;D+=2)S.push((C[D]-f)*x),S.push(-((C[D+1]-u)*x));return S}),y=un(d),E=[],b=[];for(const C of y){const{flatCoords:S,holeIndices:D}=ln(C),U=cn(S,D),M=E.length/2;for(const k of U)b.push(k+M);for(const k of S)E.push(k)}const g=E,v=b,m=[],T=[],w=[],A=zt(d);for(let C=0;C<d.length;C++){const S=d[C];T.push(m.length),w.push(A[C]);for(let D=0;D<S.length;D++)m.push(S[D]);S.length>=2&&m.push(S[0],S[1])}let P=1/0,F=1/0,_=-1/0,I=-1/0;for(let C=0;C<g.length;C+=2)P=Math.min(P,g[C]),_=Math.max(_,g[C]),F=Math.min(F,g[C+1]),I=Math.max(I,g[C+1]);return{vertices:new Float32Array(g),indices:new Uint16Array(v),edgeVertices:new Float32Array(m),contourOffsets:T,contourIsHole:w,bounds:{minX:P,maxX:_,minY:F,maxY:I},aspect:p}}function tn(s){const t=[];return s.querySelectorAll("path").forEach(a=>{const h=a.getAttribute("d");if(!h)return;const c=rn(h);t.push(...c)}),s.querySelectorAll("polygon").forEach(a=>{const h=a.getAttribute("points");if(!h)return;const c=Xt(h);c.length>=6&&t.push(c)}),s.querySelectorAll("polyline").forEach(a=>{const h=a.getAttribute("points");if(!h)return;const c=Xt(h);c.length>=6&&t.push(c)}),s.querySelectorAll("rect").forEach(a=>{const h=parseFloat(a.getAttribute("x")||"0"),c=parseFloat(a.getAttribute("y")||"0"),f=parseFloat(a.getAttribute("width")||"0"),u=parseFloat(a.getAttribute("height")||"0");f>0&&u>0&&t.push([h,c,h+f,c,h+f,c+u,h,c+u])}),s.querySelectorAll("circle").forEach(a=>{const h=parseFloat(a.getAttribute("cx")||"0"),c=parseFloat(a.getAttribute("cy")||"0"),f=parseFloat(a.getAttribute("r")||"0");f>0&&t.push(en(h,c,f))}),s.querySelectorAll("ellipse").forEach(a=>{const h=parseFloat(a.getAttribute("cx")||"0"),c=parseFloat(a.getAttribute("cy")||"0"),f=parseFloat(a.getAttribute("rx")||"0"),u=parseFloat(a.getAttribute("ry")||"0");f>0&&u>0&&t.push(nn(h,c,f,u))}),t}function Xt(s){const t=[],e=s.trim().split(/[\s,]+/);for(let n=0;n<e.length-1;n+=2){const i=parseFloat(e[n]),r=parseFloat(e[n+1]);Number.isFinite(i)&&Number.isFinite(r)&&t.push(i,r)}return t}function en(s,t,e,n=64){const i=[];for(let r=0;r<n;r++){const o=2*Math.PI*r/n;i.push(s+e*Math.cos(o),t+e*Math.sin(o))}return i}function nn(s,t,e,n,i=64){const r=[];for(let o=0;o<i;o++){const l=2*Math.PI*o/i;r.push(s+e*Math.cos(l),t+n*Math.sin(l))}return r}function rn(s){const t=[];let e=[],n=0,i=0,r=0,o=0,l=0,a=0,h="";const c=sn(s);let f=0;function u(){return f>=c.length?0:parseFloat(c[f++])}for(;f<c.length;){const x=c[f];let p;/^[a-zA-Z]$/.test(x)?(p=x,f++):p=h==="M"?"L":h==="m"?"l":h;const d=p===p.toLowerCase();switch(p.toUpperCase()){case"M":{e.length>0&&t.push(e),e=[];const E=u()+(d?n:0),b=u()+(d?i:0);n=E,i=b,r=E,o=b,e.push(n,i),l=n,a=i;break}case"L":{n=u()+(d?n:0),i=u()+(d?i:0),e.push(n,i),l=n,a=i;break}case"H":{n=u()+(d?n:0),e.push(n,i),l=n,a=i;break}case"V":{i=u()+(d?i:0),e.push(n,i),l=n,a=i;break}case"C":{const E=u()+(d?n:0),b=u()+(d?i:0),g=u()+(d?n:0),v=u()+(d?i:0),m=u()+(d?n:0),T=u()+(d?i:0);it(e,n,i,E,b,g,v,m,T),n=m,i=T,l=g,a=v;break}case"S":{const E=2*n-l,b=2*i-a,g=u()+(d?n:0),v=u()+(d?i:0),m=u()+(d?n:0),T=u()+(d?i:0);it(e,n,i,E,b,g,v,m,T),n=m,i=T,l=g,a=v;break}case"Q":{const E=u()+(d?n:0),b=u()+(d?i:0),g=u()+(d?n:0),v=u()+(d?i:0);Gt(e,n,i,E,b,g,v),n=g,i=v,l=E,a=b;break}case"T":{const E=2*n-l,b=2*i-a,g=u()+(d?n:0),v=u()+(d?i:0);Gt(e,n,i,E,b,g,v),n=g,i=v,l=E,a=b;break}case"A":{const E=u(),b=u(),g=u(),v=u(),m=u(),T=u()+(d?n:0),w=u()+(d?i:0);an(e,n,i,E,b,g,!!v,!!m,T,w),n=T,i=w,l=n,a=i;break}case"Z":{n=r,i=o,e.length>0&&t.push(e),e=[],l=n,a=i;break}default:f++;break}h=p}return e.length>=6&&t.push(e),t}function sn(s){const t=[],e=/([a-zA-Z])|([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)/g;let n;for(;(n=e.exec(s))!==null;)t.push(n[0]);return t}const on=.5;function it(s,t,e,n,i,r,o,l,a,h=0){if(h>12){s.push(l,a);return}const c=l-t,f=a-e,u=Math.sqrt(c*c+f*f);if(u<1e-6){s.push(l,a);return}const x=Math.abs((n-l)*f-(i-a)*c)/u,p=Math.abs((r-l)*f-(o-a)*c)/u;if(x+p<on){s.push(l,a);return}const d=(t+n)/2,y=(e+i)/2,E=(n+r)/2,b=(i+o)/2,g=(r+l)/2,v=(o+a)/2,m=(d+E)/2,T=(y+b)/2,w=(E+g)/2,A=(b+v)/2,P=(m+w)/2,F=(T+A)/2;it(s,t,e,d,y,m,T,P,F,h+1),it(s,P,F,w,A,g,v,l,a,h+1)}function Gt(s,t,e,n,i,r,o){const l=t+.6666666666666666*(n-t),a=e+2/3*(i-e),h=r+2/3*(n-r),c=o+2/3*(i-o);it(s,t,e,l,a,h,c,r,o)}function an(s,t,e,n,i,r,o,l,a,h){if(n===0||i===0){s.push(a,h);return}let c=Math.abs(n),f=Math.abs(i);const u=r*Math.PI/180,x=Math.cos(u),p=Math.sin(u),d=(t-a)/2,y=(e-h)/2,E=x*d+p*y,b=-p*d+x*y;let g=E*E/(c*c)+b*b/(f*f);if(g>1){const U=Math.sqrt(g);c*=U,f*=U,g=1}const v=c*c,m=f*f,T=E*E,w=b*b;let A=Math.max(0,(v*m-v*w-m*T)/(v*w+m*T));A=Math.sqrt(A),o===l&&(A=-A);const P=A*(c*b)/f,F=A*-(f*E)/c,_=x*P-p*F+(t+a)/2,I=p*P+x*F+(e+h)/2,C=Wt(1,0,(E-P)/c,(b-F)/f);let S=Wt((E-P)/c,(b-F)/f,(-E-P)/c,(-b-F)/f);!l&&S>0&&(S-=2*Math.PI),l&&S<0&&(S+=2*Math.PI);const D=Math.max(4,Math.ceil(Math.abs(S)/(Math.PI/16)));for(let U=1;U<=D;U++){const M=C+U/D*S,k=Math.cos(M),et=Math.sin(M),at=x*c*k-p*f*et+_,Et=p*c*k+x*f*et+I;s.push(at,Et)}}function Wt(s,t,e,n){const i=s*n-t*e<0?-1:1,r=s*e+t*n,o=Math.sqrt(s*s+t*t),l=Math.sqrt(e*e+n*n),a=r/(o*l);return i*Math.acos(Math.max(-1,Math.min(1,a)))}function ln(s){const t=[],e=[];for(let n=0;n<s.length;n++){n>0&&e.push(t.length/2);for(const i of s[n])t.push(i)}return{flatCoords:t,holeIndices:e}}function zt(s){const t=s.length,e=s.map(i=>Math.abs(qt(i))),n=new Array(t).fill(!1);for(let i=0;i<t;i++){let r=0;const o=s[i][0],l=s[i][1];for(let a=0;a<t;a++)i!==a&&e[a]>e[i]&&Yt(o,l,s[a])&&r++;n[i]=r%2===1}return n}function un(s){if(s.length<=1)return[s];const t=zt(s),e=s.map((o,l)=>{const a=qt(o);return{index:l,contour:o,area:a,isOuter:!t[l]}}),n=e.filter(o=>o.isOuter),i=e.filter(o=>!o.isOuter);if(n.length===0)return s.map(o=>[o]);const r=n.map(o=>({outer:o.contour,holes:[]}));for(const o of i){const l=o.contour[0],a=o.contour[1];let h=-1,c=1/0;for(let f=0;f<n.length;f++)if(Yt(l,a,n[f].contour)){const u=Math.abs(n[f].area);u<c&&(c=u,h=f)}h>=0?r[h].holes.push(o.contour):r.push({outer:o.contour,holes:[]})}return r.map(o=>[o.outer,...o.holes])}function qt(s){let t=0;const e=s.length;for(let n=0;n<e;n+=2){const i=s[n],r=s[n+1],o=s[(n+2)%e],l=s[(n+3)%e];t+=i*l-o*r}return t/2}function Yt(s,t,e){let n=!1;const i=e.length;for(let r=0,o=i-2;r<i;o=r,r+=2){const l=e[r],a=e[r+1],h=e[o],c=e[o+1];a>t!=c>t&&s<(h-l)*(t-a)/(c-a)+l&&(n=!n)}return n}function cn(s,t,e=2){const n=t&&t.length>0,i=n?t[0]*e:s.length;let r=jt(s,0,i,e,!0);const o=[];if(!r||r.next===r.prev)return o;n&&(r=pn(s,t,r,e));let l=1/0,a=1/0,h=-1/0,c=-1/0,f=0;if(s.length>80*e){for(let u=0;u<i;u+=e){const x=s[u],p=s[u+1];x<l&&(l=x),p<a&&(a=p),x>h&&(h=x),p>c&&(c=p)}f=Math.max(h-l,c-a),f=f!==0?32767/f:0}return rt(r,o,e,l,a,f,0),o}function jt(s,t,e,n,i){let r=null;if(i===Rn(s,t,e,n)>0)for(let o=t;o<e;o+=n)r=Kt(o,s[o],s[o+1],r);else for(let o=e-n;o>=t;o-=n)r=Kt(o,s[o],s[o+1],r);return r&>(r,r.next)&&(ot(r),r=r.next),r?(r.next.prev=r,r.prev.next=r,r.next):null}function j(s,t){t||(t=s);let e=s,n;do if(n=!1,!e.steiner&&(gt(e,e.next)||L(e.prev,e,e.next)===0)){if(ot(e),e=t=e.prev,e===e.next)break;n=!0}else e=e.next;while(n||e!==t);return t}function rt(s,t,e,n,i,r,o){if(!s)return;!o&&r&&Tn(s,n,i,r);let l=s,a,h;for(;s.prev!==s.next;){if(a=s.prev,h=s.next,r?fn(s,n,i,r):hn(s)){t.push(a.i/e,s.i/e,h.i/e),ot(s),s=h.next,l=h.next;continue}if(s=h,s===l){o?o===1?(s=dn(j(s),t,e),rt(s,t,e,n,i,r,2)):o===2&&mn(s,t,e,n,i,r):rt(j(s),t,e,n,i,r,1);break}}}function hn(s){const t=s.prev,e=s,n=s.next;if(L(t,e,n)>=0)return!1;const i=t.x,r=e.x,o=n.x,l=t.y,a=e.y,h=n.y,c=i<r?i<o?i:o:r<o?r:o,f=l<a?l<h?l:h:a<h?a:h,u=i>r?i>o?i:o:r>o?r:o,x=l>a?l>h?l:h:a>h?a:h;let p=n.next;for(;p!==t;){if(p.x>=c&&p.x<=u&&p.y>=f&&p.y<=x&&J(i,l,r,a,o,h,p.x,p.y)&&L(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function fn(s,t,e,n){const i=s.prev,r=s,o=s.next;if(L(i,r,o)>=0)return!1;const l=i.x,a=r.x,h=o.x,c=i.y,f=r.y,u=o.y,x=l<a?l<h?l:h:a<h?a:h,p=c<f?c<u?c:u:f<u?f:u,d=l>a?l>h?l:h:a>h?a:h,y=c>f?c>u?c:u:f>u?f:u,E=At(x,p,t,e,n),b=At(d,y,t,e,n);let g=s.prevZ,v=s.nextZ;for(;g&&g.z>=E&&v&&v.z<=b;){if(g.x>=x&&g.x<=d&&g.y>=p&&g.y<=y&&g!==i&&g!==o&&J(l,c,a,f,h,u,g.x,g.y)&&L(g.prev,g,g.next)>=0||(g=g.prevZ,v.x>=x&&v.x<=d&&v.y>=p&&v.y<=y&&v!==i&&v!==o&&J(l,c,a,f,h,u,v.x,v.y)&&L(v.prev,v,v.next)>=0))return!1;v=v.nextZ}for(;g&&g.z>=E;){if(g.x>=x&&g.x<=d&&g.y>=p&&g.y<=y&&g!==i&&g!==o&&J(l,c,a,f,h,u,g.x,g.y)&&L(g.prev,g,g.next)>=0)return!1;g=g.prevZ}for(;v&&v.z<=b;){if(v.x>=x&&v.x<=d&&v.y>=p&&v.y<=y&&v!==i&&v!==o&&J(l,c,a,f,h,u,v.x,v.y)&&L(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function dn(s,t,e){let n=s;do{const i=n.prev,r=n.next.next;!gt(i,r)&&Zt(i,n,n.next,r)&&st(i,r)&&st(r,i)&&(t.push(i.i/e,n.i/e,r.i/e),ot(n),ot(n.next),n=s=r),n=n.next}while(n!==s);return j(n)}function mn(s,t,e,n,i,r){let o=s;do{let l=o.next.next;for(;l!==o.prev;){if(o.i!==l.i&&Sn(o,l)){let a=$t(o,l);o=j(o,o.next),a=j(a,a.next),rt(o,t,e,n,i,r,0),rt(a,t,e,n,i,r,0);return}l=l.next}o=o.next}while(o!==s)}function pn(s,t,e,n){const i=[];for(let r=0;r<t.length;r++){const o=t[r]*n,l=r<t.length-1?t[r+1]*n:s.length,a=jt(s,o,l,n,!1);a&&(a===a.next&&(a.steiner=!0),i.push(bn(a)))}i.sort((r,o)=>r.x-o.x);for(const r of i)e=gn(r,e);return e}function gn(s,t){const e=vn(s,t);if(!e)return t;const n=$t(e,s);return j(n,n.next),j(e,e.next)}function vn(s,t){let e=t;const n=s.x,i=s.y;let r=-1/0,o=null;do{if(i<=e.y&&i>=e.next.y&&e.next.y!==e.y){const f=e.x+(i-e.y)/(e.next.y-e.y)*(e.next.x-e.x);if(f<=n&&f>r&&(r=f,o=e.x<e.next.x?e:e.next,f===n))return o}e=e.next}while(e!==t);if(!o)return null;const l=o,a=o.x,h=o.y;let c=1/0;e=o;do{if(n>=e.x&&e.x>=a&&n!==e.x&&J(i<h?n:r,i,a,h,i<h?r:n,i,e.x,e.y)){const f=Math.abs(i-e.y)/(n-e.x);st(e,s)&&(f<c||f===c&&(e.x>o.x||xn(o,e)))&&(o=e,c=f)}e=e.next}while(e!==l);return o}function xn(s,t){return L(s.prev,s,t.prev)<0&&L(t.next,s,s.next)<0}function Tn(s,t,e,n){let i=s;do i.z===0&&(i.z=At(i.x,i.y,t,e,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next;while(i!==s);i.prevZ.nextZ=null,i.prevZ=null,En(i)}function En(s){let t=1,e;do{let n=s;s=null;let i=null;for(e=0;n;){e++;let r=n,o=0;for(let a=0;a<t&&(o++,r=r.nextZ,!!r);a++);let l=t;for(;o>0||l>0&&r;){let a;o!==0&&(l===0||!r||n.z<=r.z)?(a=n,n=n.nextZ,o--):(a=r,r=r.nextZ,l--),i?i.nextZ=a:s=a,a.prevZ=i,i=a}n=r}i.nextZ=null,t*=2}while(e>1);return s}function At(s,t,e,n,i){let r=(s-e)*i|0,o=(t-n)*i|0;return r=(r|r<<8)&16711935,r=(r|r<<4)&252645135,r=(r|r<<2)&858993459,r=(r|r<<1)&1431655765,o=(o|o<<8)&16711935,o=(o|o<<4)&252645135,o=(o|o<<2)&858993459,o=(o|o<<1)&1431655765,r|o<<1}function bn(s){let t=s,e=s;do(t.x<e.x||t.x===e.x&&t.y<e.y)&&(e=t),t=t.next;while(t!==s);return e}function J(s,t,e,n,i,r,o,l){return(i-o)*(t-l)-(s-o)*(r-l)>=0&&(s-o)*(n-l)-(e-o)*(t-l)>=0&&(e-o)*(r-l)-(i-o)*(n-l)>=0}function Sn(s,t){return s.next.i!==t.i&&s.prev.i!==t.i&&!yn(s,t)&&(st(s,t)&&st(t,s)&&wn(s,t)&&(L(s.prev,s,t.prev)!==0||L(s,t.prev,t)!==0)||gt(s,t)&&L(s.prev,s,s.next)>0&&L(t.prev,t,t.next)>0)}function L(s,t,e){return(t.y-s.y)*(e.x-t.x)-(t.x-s.x)*(e.y-t.y)}function gt(s,t){return s.x===t.x&&s.y===t.y}function Zt(s,t,e,n){const i=xt(L(s,t,e)),r=xt(L(s,t,n)),o=xt(L(e,n,s)),l=xt(L(e,n,t));return!!(i!==r&&o!==l||i===0&&vt(s,e,t)||r===0&&vt(s,n,t)||o===0&&vt(e,s,n)||l===0&&vt(e,t,n))}function vt(s,t,e){return t.x<=Math.max(s.x,e.x)&&t.x>=Math.min(s.x,e.x)&&t.y<=Math.max(s.y,e.y)&&t.y>=Math.min(s.y,e.y)}function xt(s){return s>0?1:s<0?-1:0}function yn(s,t){let e=s;do{if(e.i!==s.i&&e.next.i!==s.i&&e.i!==t.i&&e.next.i!==t.i&&Zt(e,e.next,s,t))return!0;e=e.next}while(e!==s);return!1}function st(s,t){return L(s.prev,s,s.next)<0?L(s,t,s.next)>=0&&L(s,s.prev,t)>=0:L(s,t,s.prev)<0||L(s,s.next,t)<0}function wn(s,t){let e=s,n=!1;const i=(s.x+t.x)/2,r=(s.y+t.y)/2;do e.y>r!=e.next.y>r&&e.next.y!==e.y&&i<(e.next.x-e.x)*(r-e.y)/(e.next.y-e.y)+e.x&&(n=!n),e=e.next;while(e!==s);return n}function $t(s,t){const e=Pt(s.i,s.x,s.y),n=Pt(t.i,t.x,t.y),i=s.next,r=t.prev;return s.next=t,t.prev=s,e.next=i,i.prev=e,n.next=e,e.prev=n,r.next=n,n.prev=r,n}function Kt(s,t,e,n){const i=Pt(s,t,e);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function ot(s){s.next.prev=s.prev,s.prev.next=s.next,s.prevZ&&(s.prevZ.nextZ=s.nextZ),s.nextZ&&(s.nextZ.prevZ=s.prevZ)}function Pt(s,t,e){return{i:s,x:t,y:e,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function Rn(s,t,e,n){let i=0;for(let r=t,o=e-n;r<e;r+=n)i+=(s[o]-s[r])*(s[r+1]+s[o+1]),o=r;return i}const R={parallaxX:.4,parallaxY:.8,parallaxMax:30,overscan:.06,pomSteps:16,rimIntensity:.6,rimColor:"#ffffff",rimWidth:.025,refractionStrength:.015,chromaticStrength:.008,occlusionIntensity:.4,depthPower:.7,depthScale:1.2,depthBias:-.05,fogDensity:.15,fogColor:"#1a1a2e",colorShift:.6,brightnessBias:.05,contrastLow:.02,contrastHigh:.98,verticalReduction:.5,dofStart:.5,dofStrength:.5,bevelIntensity:.5,bevelWidth:.04,bevelDarkening:.2,bevelDesaturation:.12,bevelLightAngle:135,edgeThickness:.01,edgeSpecular:.35,edgeColor:"#a0a0a0",chamferWidth:.025,chamferAngle:45,chamferColor:"#262630",chamferAmbient:.12,chamferSpecular:.3,chamferShininess:24,edgeOcclusionWidth:.03,edgeOcclusionStrength:.2,lightDirection:"-0.5,0.7,-0.3",autoplay:!0,loop:!0,muted:!0},Q=512,tt=512;class Tt extends HTMLElement{static TAG_NAME="layershift-portal";static get observedAttributes(){return["src","depth-src","depth-meta","depth-model","logo-src","source-type","parallax-x","parallax-y","parallax-max","overscan","pom-steps","quality","gpu-backend","rim-intensity","rim-color","rim-width","refraction-strength","chromatic-strength","occlusion-intensity","depth-power","depth-scale","depth-bias","fog-density","fog-color","color-shift","brightness-bias","contrast-low","contrast-high","vertical-reduction","dof-start","dof-strength","bevel-intensity","bevel-width","bevel-darkening","bevel-desaturation","bevel-light-angle","edge-thickness","edge-specular","edge-color","chamfer-width","chamfer-angle","chamfer-color","chamfer-ambient","chamfer-specular","chamfer-shininess","edge-occlusion-width","edge-occlusion-strength","light-direction","autoplay","loop","muted"]}reinitAttributes=["src","depth-src","depth-meta","depth-model","logo-src","source-type"];canInit(){const t=!!this.getAttribute("logo-src");if(this.sourceType==="camera")return t;const e=!!this.getAttribute("src"),n=!!this.getAttribute("depth-src")&&!!this.getAttribute("depth-meta"),i=!!this.getAttribute("depth-model");return e&&t&&(n||i)}_input={x:0,y:0};get input(){return{x:this._input.x,y:this._input.y}}set input(t){this._input.x=t.x,this._input.y=t.y}shadow;container=null;renderer=null;source=null;depthEstimator=null;mesh=null;loopCount=0;lifecycle;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.lifecycle=new Nt(this)}getAttrFloat(t,e){const n=this.getAttribute(t);if(n===null)return e;const i=parseFloat(n);return Number.isFinite(i)?i:e}getAttrBool(t,e){if(!this.hasAttribute(t))return e;const n=this.getAttribute(t);return!(n==="false"||n==="0")}getAttrColor(t,e){const n=this.getAttribute(t)??e;return An(n)}getAttrVec3(t,e){const i=(this.getAttribute(t)??e).split(",").map(o=>parseFloat(o.trim()));if(i.length>=3&&i.every(Number.isFinite))return[i[0],i[1],i[2]];const r=e.split(",").map(o=>parseFloat(o.trim()));return[r[0],r[1],r[2]]}get sourceType(){const t=this.getAttribute("source-type");return t==="camera"?"camera":t==="image"?"image":"video"}get parallaxX(){return this.getAttrFloat("parallax-x",R.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",R.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",R.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",R.overscan)}get pomSteps(){return this.getAttrFloat("pom-steps",R.pomSteps)}get quality(){const t=this.getAttribute("quality");if(t==="auto"||t==="high"||t==="medium"||t==="low")return t}get gpuBackend(){return"webgl2"}get rimIntensity(){return this.getAttrFloat("rim-intensity",R.rimIntensity)}get rimWidth(){return this.getAttrFloat("rim-width",R.rimWidth)}get rimColor(){return this.getAttrColor("rim-color",R.rimColor)}get refractionStrength(){return this.getAttrFloat("refraction-strength",R.refractionStrength)}get chromaticStrength(){return this.getAttrFloat("chromatic-strength",R.chromaticStrength)}get occlusionIntensity(){return this.getAttrFloat("occlusion-intensity",R.occlusionIntensity)}get depthPower(){return this.getAttrFloat("depth-power",R.depthPower)}get depthScale(){return this.getAttrFloat("depth-scale",R.depthScale)}get depthBias(){return this.getAttrFloat("depth-bias",R.depthBias)}get fogDensity(){return this.getAttrFloat("fog-density",R.fogDensity)}get fogColor(){return this.getAttrColor("fog-color",R.fogColor)}get colorShift(){return this.getAttrFloat("color-shift",R.colorShift)}get brightnessBias(){return this.getAttrFloat("brightness-bias",R.brightnessBias)}get contrastLow(){return this.getAttrFloat("contrast-low",R.contrastLow)}get contrastHigh(){return this.getAttrFloat("contrast-high",R.contrastHigh)}get verticalReduction(){return this.getAttrFloat("vertical-reduction",R.verticalReduction)}get dofStart(){return this.getAttrFloat("dof-start",R.dofStart)}get dofStrength(){return this.getAttrFloat("dof-strength",R.dofStrength)}get bevelIntensity(){return this.getAttrFloat("bevel-intensity",R.bevelIntensity)}get bevelWidth(){return this.getAttrFloat("bevel-width",R.bevelWidth)}get bevelDarkening(){return this.getAttrFloat("bevel-darkening",R.bevelDarkening)}get bevelDesaturation(){return this.getAttrFloat("bevel-desaturation",R.bevelDesaturation)}get bevelLightAngle(){return this.getAttrFloat("bevel-light-angle",R.bevelLightAngle)}get edgeThickness(){return this.getAttrFloat("edge-thickness",R.edgeThickness)}get edgeSpecular(){return this.getAttrFloat("edge-specular",R.edgeSpecular)}get edgeColor(){return this.getAttrColor("edge-color",R.edgeColor)}get chamferWidth(){return this.getAttrFloat("chamfer-width",R.chamferWidth)}get chamferAngle(){return this.getAttrFloat("chamfer-angle",R.chamferAngle)}get chamferColor(){return this.getAttrColor("chamfer-color",R.chamferColor)}get chamferAmbient(){return this.getAttrFloat("chamfer-ambient",R.chamferAmbient)}get chamferSpecular(){return this.getAttrFloat("chamfer-specular",R.chamferSpecular)}get chamferShininess(){return this.getAttrFloat("chamfer-shininess",R.chamferShininess)}get edgeOcclusionWidth(){return this.getAttrFloat("edge-occlusion-width",R.edgeOcclusionWidth)}get edgeOcclusionStrength(){return this.getAttrFloat("edge-occlusion-strength",R.edgeOcclusionStrength)}get lightDirection3(){return this.getAttrVec3("light-direction",R.lightDirection)}get depthModel(){return this.getAttribute("depth-model")}get shouldAutoplay(){return this.getAttrBool("autoplay",R.autoplay)}get shouldLoop(){return this.getAttrBool("loop",R.loop)}get shouldMute(){return this.getAttrBool("muted",R.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachSourceEventListeners(t){t.addEventListener&&(t.addEventListener("play",(()=>{this.emit("layershift-portal:play",{currentTime:t.currentTime})})),t.addEventListener("pause",(()=>{this.emit("layershift-portal:pause",{currentTime:t.currentTime})})),t.addEventListener("ended",(()=>{this.loopCount+=1,this.emit("layershift-portal:loop",{loopCount:this.loopCount})})))}connectedCallback(){console.warn("[layershift] <layershift-portal> is deprecated and will be removed in a future major version. Use <layershift-effect> with a filter-config.json instead. See https://layershift.io/docs/migration"),this.lifecycle.onConnected()}disconnectedCallback(){this.lifecycle.onDisconnected()}attributeChangedCallback(t,e,n){this.lifecycle.onAttributeChanged(t,e,n)}setupShadowDOM(){this.shadow.innerHTML="";const t=document.createElement("style");t.textContent=`
|
|
1039
|
+
`;function je(s){const t=[];let e=0;for(let i=0;i<s.length-2;i+=2){const n=s[i],r=s[i+1],o=s[i+2],l=s[i+3],a=o-n,h=l-r,c=Math.sqrt(a*a+h*h);if(c<1e-6)continue;const f=-h/c,u=a/c;t.push(n,r,f,u,n,r,-f,-u,o,l,f,u,o,l,f,u,n,r,-f,-u,o,l,-f,-u),e+=6}return{vertices:new Float32Array(t),count:e}}function Ze(s,t,e,i,n){if(i<=0)return{vertices:new Float32Array(0),count:0};const r=n*Math.PI/180,o=-Math.cos(r),l=Math.sin(r),a=[];let h=0;for(let c=0;c<t.length;c++){const f=t[c],p=((c+1<t.length?t[c+1]:s.length)-f)/2;if(p<3)continue;const d=p-1;let y=0;for(let T=0;T<d;T++){const R=f+T*2,A=s[R],P=s[R+1],F=s[R+2],_=s[R+3];y+=A*_-F*P}const b=y>=0?1:-1,E=[],g=[];for(let T=0;T<d;T++){const R=f+T*2,A=s[R+2]-s[R],P=s[R+3]-s[R+1],F=Math.sqrt(A*A+P*P);F<1e-8?(E.push(T>0?E[T-1]:0),g.push(T>0?g[T-1]:0)):(E.push(-P/F*b),g.push(A/F*b))}const v=[],m=[];for(let T=0;T<d;T++){const R=(T-1+d)%d;let A=E[R]+E[T],P=g[R]+g[T];const F=Math.sqrt(A*A+P*P);F>1e-8?(A/=F,P/=F):(A=E[T],P=g[T]),v.push(A),m.push(P)}for(let T=0;T<d;T++){const R=T,A=(T+1)%d,P=f+T*2,F=f+(T+1)%d*2,_=s[P],I=s[P+1],C=s[F],S=s[F+1],D=v[R]*l,U=m[R]*l,M=o,k=v[A]*l,et=m[A]*l,at=o,Et=_+v[R]*i,Qt=I+m[R]*i,Di=C+v[A]*i,Fi=S+m[A]*i;a.push(_,I,D,U,M,0),a.push(Et,Qt,D,U,M,1),a.push(C,S,k,et,at,0),a.push(C,S,k,et,at,0),a.push(Et,Qt,D,U,M,1),a.push(Di,Fi,k,et,at,1),h+=6}}return{vertices:new Float32Array(a),count:h}}class $e extends ct{gl=null;stencilPass=null;maskPass=null;jfaSeedPass=null;jfaFloodPass=null;jfaDistPass=null;interiorPass=null;compositePass=null;boundaryPass=null;chamferPass=null;quadVao=null;stencilVao=null;stencilIndexCount=0;maskVao=null;boundaryVao=null;boundaryVertexCount=0;chamferVao=null;chamferVertexCount=0;textures=new Lt;videoSlot;depthSlot;interiorFbo=null;interiorColorTex=null;interiorDepthTex=null;fboWidth=0;fboHeight=0;jfa=null;hasColorBufferFloat=!1;meshAspect=1;meshScaleX=.65;meshScaleY=.65;lightDirX=-.707;lightDirY=.707;lightDir3=[-.5,.7,-.3];config;constructor(t,e){super(t),this.config={...e},this.videoSlot=this.textures.register("video"),this.depthSlot=this.textures.register("depth");const i=this.config.bevelLightAngle*Math.PI/180;this.lightDirX=Math.cos(i),this.lightDirY=Math.sin(i);const n=this.config.lightDirection,r=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);r>1e-6&&(this.lightDir3=[n[0]/r,n[1]/r,n[2]/r]);const o=this.canvas.getContext("webgl2",{antialias:!0,alpha:!0,premultipliedAlpha:!0,stencil:!0,desynchronized:!0,powerPreference:"high-performance"});if(!o)throw new Error("WebGL 2 is not supported.");this.gl=o,this.qualityParams=It(o,e.quality),"drawingBufferColorSpace"in o&&(o.drawingBufferColorSpace="srgb"),this.hasColorBufferFloat=!!o.getExtension("EXT_color_buffer_float"),o.clearColor(0,0,0,0),o.pixelStorei(o.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.setupResizeHandling()}initialize(t,e,i,n){const r=this.gl;r&&(this.disposeTextures(),this.disposeFBO(),this.jfa&&(this.jfa.dispose(),this.jfa=null),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.isCameraSource=t.type==="camera",this.videoAspect=t.width/t.height,this.meshAspect=n.aspect,this.clampDepthDimensions(e,i,this.qualityParams.depthMaxDim),this.videoSlot.texture=r.createTexture(),r.activeTexture(r.TEXTURE0+this.videoSlot.unit),r.bindTexture(r.TEXTURE_2D,this.videoSlot.texture),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),this.depthSlot.texture=r.createTexture(),r.activeTexture(r.TEXTURE0+this.depthSlot.unit),r.bindTexture(r.TEXTURE_2D,this.depthSlot.texture),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,r.LINEAR),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,r.CLAMP_TO_EDGE),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,r.CLAMP_TO_EDGE),r.texStorage2D(r.TEXTURE_2D,1,r.R8,this.depthWidth,this.depthHeight),this.uploadStencilMesh(n),this.uploadMaskMesh(n),this.uploadBoundaryMesh(n),this.uploadChamferMesh(n),this.interiorPass&&(r.useProgram(this.interiorPass.program),r.uniform1i(this.interiorPass.uniforms.uImage,0),r.uniform1i(this.interiorPass.uniforms.uDepth,1),r.uniform1f(this.interiorPass.uniforms.uStrength,this.config.parallaxStrength),r.uniform1i(this.interiorPass.uniforms.uPomSteps,this.config.pomSteps),r.uniform1f(this.interiorPass.uniforms.uDepthPower,this.config.depthPower),r.uniform1f(this.interiorPass.uniforms.uDepthScale,this.config.depthScale),r.uniform1f(this.interiorPass.uniforms.uDepthBias,this.config.depthBias),r.uniform1f(this.interiorPass.uniforms.uContrastLow,this.config.contrastLow),r.uniform1f(this.interiorPass.uniforms.uContrastHigh,this.config.contrastHigh),r.uniform1f(this.interiorPass.uniforms.uVerticalReduction,this.config.verticalReduction),r.uniform1f(this.interiorPass.uniforms.uDofStart,this.config.dofStart),r.uniform1f(this.interiorPass.uniforms.uDofStrength,this.config.dofStrength),r.uniform2f(this.interiorPass.uniforms.uImageTexelSize,1/t.width,1/t.height),r.uniform1f(this.interiorPass.uniforms.uFogDensity,this.config.fogDensity),r.uniform3f(this.interiorPass.uniforms.uFogColor,...this.config.fogColor),r.uniform1f(this.interiorPass.uniforms.uColorShift,this.config.colorShift),r.uniform1f(this.interiorPass.uniforms.uBrightnessBias,this.config.brightnessBias)),this.compositePass&&(r.useProgram(this.compositePass.program),r.uniform1i(this.compositePass.uniforms.uInteriorColor,2),r.uniform1i(this.compositePass.uniforms.uDistField,4),r.uniform1f(this.compositePass.uniforms.uEdgeOcclusionWidth,this.config.edgeOcclusionWidth),r.uniform1f(this.compositePass.uniforms.uEdgeOcclusionStrength,this.config.edgeOcclusionStrength)),this.chamferPass&&(r.useProgram(this.chamferPass.program),r.uniform3f(this.chamferPass.uniforms.uLightDir3,...this.lightDir3),r.uniform3f(this.chamferPass.uniforms.uChamferColor,...this.config.chamferColor),r.uniform1f(this.chamferPass.uniforms.uChamferAmbient,this.config.chamferAmbient),r.uniform1f(this.chamferPass.uniforms.uChamferSpecular,this.config.chamferSpecular),r.uniform1f(this.chamferPass.uniforms.uChamferShininess,this.config.chamferShininess),r.uniform1i(this.chamferPass.uniforms.uInteriorColor,2)),this.boundaryPass&&(r.useProgram(this.boundaryPass.program),r.uniform1i(this.boundaryPass.uniforms.uInteriorColor,2),r.uniform1i(this.boundaryPass.uniforms.uInteriorDepth,3),r.uniform1i(this.boundaryPass.uniforms.uDistField,4),r.uniform1f(this.boundaryPass.uniforms.uRimIntensity,this.config.rimLightIntensity),r.uniform3f(this.boundaryPass.uniforms.uRimColor,...this.config.rimLightColor),r.uniform1f(this.boundaryPass.uniforms.uRefractionStrength,this.config.refractionStrength),r.uniform1f(this.boundaryPass.uniforms.uChromaticStrength,this.config.chromaticStrength),r.uniform1f(this.boundaryPass.uniforms.uOcclusionIntensity,this.config.occlusionIntensity),r.uniform1f(this.boundaryPass.uniforms.uEdgeThickness,this.config.edgeThickness),r.uniform1f(this.boundaryPass.uniforms.uEdgeSpecular,this.config.edgeSpecular),r.uniform3f(this.boundaryPass.uniforms.uEdgeColor,...this.config.edgeColor),r.uniform2f(this.boundaryPass.uniforms.uLightDir,this.lightDirX,this.lightDirY),r.uniform1f(this.boundaryPass.uniforms.uBevelIntensity,this.config.bevelIntensity)),this.recalculateViewportLayout())}uploadStencilMesh(t){const e=this.gl;if(!e||!this.stencilPass)return;this.stencilVao=e.createVertexArray(),e.bindVertexArray(this.stencilVao);const i=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,i),e.bufferData(e.ARRAY_BUFFER,t.vertices,e.STATIC_DRAW);const n=e.getAttribLocation(this.stencilPass.program,"aPosition");e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,0,0);const r=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,r),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t.indices,e.STATIC_DRAW),this.stencilIndexCount=t.indices.length,e.bindVertexArray(null)}uploadMaskMesh(t){const e=this.gl;if(!e||!this.maskPass)return;this.maskVao=e.createVertexArray(),e.bindVertexArray(this.maskVao);const i=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,i),e.bufferData(e.ARRAY_BUFFER,t.vertices,e.STATIC_DRAW);const n=e.getAttribLocation(this.maskPass.program,"aPosition");e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,0,0);const r=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,r),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t.indices,e.STATIC_DRAW),e.bindVertexArray(null)}uploadBoundaryMesh(t){const e=this.gl;if(!e||!this.boundaryPass)return;const i=je(t.edgeVertices);if(i.count===0)return;this.boundaryVao=e.createVertexArray(),e.bindVertexArray(this.boundaryVao);const n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n),e.bufferData(e.ARRAY_BUFFER,i.vertices,e.STATIC_DRAW);const r=16,o=e.getAttribLocation(this.boundaryPass.program,"aPosition");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,r,0);const l=e.getAttribLocation(this.boundaryPass.program,"aNormal");l>=0&&(e.enableVertexAttribArray(l),e.vertexAttribPointer(l,2,e.FLOAT,!1,r,8)),this.boundaryVertexCount=i.count,e.bindVertexArray(null)}uploadChamferMesh(t){const e=this.gl;if(!e||!this.chamferPass||this.config.chamferWidth<=0)return;const i=Ze(t.edgeVertices,t.contourOffsets,t.contourIsHole,this.config.chamferWidth,this.config.chamferAngle);if(i.count===0)return;this.chamferVao=e.createVertexArray(),e.bindVertexArray(this.chamferVao);const n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n),e.bufferData(e.ARRAY_BUFFER,i.vertices,e.STATIC_DRAW);const r=24,o=e.getAttribLocation(this.chamferPass.program,"aPosition");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,r,0);const l=e.getAttribLocation(this.chamferPass.program,"aNormal3");l>=0&&(e.enableVertexAttribArray(l),e.vertexAttribPointer(l,3,e.FLOAT,!1,r,8));const a=e.getAttribLocation(this.chamferPass.program,"aLerpT");a>=0&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,1,e.FLOAT,!1,r,20)),this.chamferVertexCount=i.count,e.bindVertexArray(null)}disposeChamferGeometry(){const t=this.gl;t&&(this.chamferVao&&(t.deleteVertexArray(this.chamferVao),this.chamferVao=null),this.chamferVertexCount=0)}createFBO(t,e){const i=this.gl;if(!i)return;this.disposeFBO(),this.fboWidth=t,this.fboHeight=e,this.interiorFbo=i.createFramebuffer(),i.bindFramebuffer(i.FRAMEBUFFER,this.interiorFbo),this.interiorColorTex=i.createTexture(),i.activeTexture(i.TEXTURE2),i.bindTexture(i.TEXTURE_2D,this.interiorColorTex),i.texStorage2D(i.TEXTURE_2D,1,i.RGBA8,t,e),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,this.interiorColorTex,0),this.interiorDepthTex=i.createTexture(),i.activeTexture(i.TEXTURE3),i.bindTexture(i.TEXTURE_2D,this.interiorDepthTex),i.texStorage2D(i.TEXTURE_2D,1,i.RGBA8,t,e),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT1,i.TEXTURE_2D,this.interiorDepthTex,0),i.drawBuffers([i.COLOR_ATTACHMENT0,i.COLOR_ATTACHMENT1]);const n=i.checkFramebufferStatus(i.FRAMEBUFFER);n!==i.FRAMEBUFFER_COMPLETE&&console.error("Interior FBO incomplete:",n),i.bindFramebuffer(i.FRAMEBUFFER,null)}createJFAResources(t,e){const i=this.gl;i&&(this.jfa||(this.jfa=new wt(i,this.hasColorBufferFloat)),this.jfa.createResources(t,e,this.qualityParams.jfaDivisor))}computeDistanceField(){!this.jfa||!this.maskPass||!this.jfaSeedPass||!this.jfaFloodPass||!this.jfaDistPass||!this.maskVao||!this.quadVao||this.jfa.compute({maskPass:this.maskPass,seedPass:this.jfaSeedPass,floodPass:this.jfaFloodPass,distPass:this.jfaDistPass,maskVao:this.maskVao,quadVao:this.quadVao,meshScaleX:this.meshScaleX,meshScaleY:this.meshScaleY,stencilIndexCount:this.stencilIndexCount,distRange:Math.max(this.config.bevelWidth,this.config.edgeOcclusionWidth)})}initGPUResources(){const t=this.gl;t&&(this.stencilPass=H(t,"stencil",Ce,Ue,["uMeshScale"]),this.maskPass=H(t,"mask",Le,_e,["uMeshScale"]),this.jfaSeedPass=H(t,"jfa-seed",Ie,Me,["uMask","uTexelSize"]),this.jfaFloodPass=H(t,"jfa-flood",Be,Ve,["uSeedTex","uStepSize"]),this.jfaDistPass=H(t,"jfa-dist",ke,Oe,["uSeedTex","uMask","uBevelWidth"]),this.interiorPass=H(t,"interior",He,Xe,["uImage","uDepth","uOffset","uStrength","uPomSteps","uDepthPower","uDepthScale","uDepthBias","uContrastLow","uContrastHigh","uVerticalReduction","uDofStart","uDofStrength","uImageTexelSize","uFogDensity","uFogColor","uColorShift","uBrightnessBias","uUvOffset","uUvScale"]),this.compositePass=H(t,"composite",Ne,Ge,["uInteriorColor","uDistField","uEdgeOcclusionWidth","uEdgeOcclusionStrength"]),this.boundaryPass=H(t,"boundary",We,ze,["uInteriorColor","uInteriorDepth","uDistField","uRimIntensity","uRimColor","uRimWidth","uMeshScale","uRefractionStrength","uChromaticStrength","uOcclusionIntensity","uTexelSize","uEdgeThickness","uEdgeSpecular","uEdgeColor","uLightDir","uBevelIntensity"]),this.chamferPass=H(t,"chamfer",qe,Ye,["uMeshScale","uLightDir3","uChamferColor","uChamferAmbient","uChamferSpecular","uChamferShininess","uInteriorColor","uTexelSize"]),this.quadVao=Ut(t,this.interiorPass.program),t.disable(t.DEPTH_TEST))}onRenderFrame(){const t=this.gl,e=this.mediaSource;if(!t||!this.interiorPass||!this.quadVao)return;const i=e?.getImageSource();if(!i||!this.interiorFbo||!this.interiorColorTex||!this.interiorDepthTex)return;if(this.jfa?.isDirty&&this.maskVao){const o=this.qualityParams.jfaDivisor,l=Math.max(1,Math.round(this.canvas.width/o)),a=Math.max(1,Math.round(this.canvas.height/o));(this.jfa.width!==l||this.jfa.height!==a)&&this.createJFAResources(this.canvas.width,this.canvas.height),this.computeDistanceField(),t.viewport(0,0,this.canvas.width,this.canvas.height)}t.activeTexture(t.TEXTURE0+this.videoSlot.unit),t.bindTexture(t.TEXTURE_2D,this.videoSlot.texture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,i),this.rvfcSupported||this.onDepthUpdate(e.currentTime);let n=0,r=0;if(this.readInput){const o=this.readInput();n=-o.x,r=o.y}if(t.bindFramebuffer(t.FRAMEBUFFER,this.interiorFbo),t.checkFramebufferStatus(t.FRAMEBUFFER)!==t.FRAMEBUFFER_COMPLETE){t.bindFramebuffer(t.FRAMEBUFFER,null);return}t.viewport(0,0,this.fboWidth,this.fboHeight),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.interiorPass.program),t.uniform2f(this.interiorPass.uniforms.uOffset,n,r),t.activeTexture(t.TEXTURE0+this.videoSlot.unit),t.bindTexture(t.TEXTURE_2D,this.videoSlot.texture),t.activeTexture(t.TEXTURE0+this.depthSlot.unit),t.bindTexture(t.TEXTURE_2D,this.depthSlot.texture),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,null),t.clearColor(0,0,0,0),t.viewport(0,0,this.canvas.width,this.canvas.height),t.clear(t.COLOR_BUFFER_BIT|t.STENCIL_BUFFER_BIT),this.stencilVao&&this.stencilPass&&this.stencilIndexCount>0&&(t.enable(t.STENCIL_TEST),t.stencilFunc(t.ALWAYS,1,255),t.stencilOp(t.KEEP,t.KEEP,t.REPLACE),t.stencilMask(255),t.colorMask(!1,!1,!1,!1),t.useProgram(this.stencilPass.program),t.bindVertexArray(this.stencilVao),t.drawElements(t.TRIANGLES,this.stencilIndexCount,t.UNSIGNED_SHORT,0),t.colorMask(!0,!0,!0,!0)),t.stencilFunc(t.EQUAL,1,255),t.stencilMask(0),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.interiorColorTex),t.activeTexture(t.TEXTURE3),t.bindTexture(t.TEXTURE_2D,this.interiorDepthTex),t.activeTexture(t.TEXTURE4),t.bindTexture(t.TEXTURE_2D,this.jfa?.distanceTexture??null),t.useProgram(this.compositePass.program),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.disable(t.STENCIL_TEST),this.chamferVao&&this.chamferPass&&this.chamferVertexCount>0&&(t.useProgram(this.chamferPass.program),t.uniform2f(this.chamferPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform2f(this.chamferPass.uniforms.uTexelSize,1/this.canvas.width,1/this.canvas.height),t.bindVertexArray(this.chamferVao),t.drawArrays(t.TRIANGLES,0,this.chamferVertexCount)),this.boundaryVao&&this.boundaryPass&&this.boundaryVertexCount>0&&this.config.rimLightIntensity>0&&(t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.useProgram(this.boundaryPass.program),t.bindVertexArray(this.boundaryVao),t.drawArrays(t.TRIANGLES,0,this.boundaryVertexCount),t.disable(t.BLEND))}onDepthUpdate(t){const e=this.gl;if(!e||!this.readDepth||!this.depthSlot.texture)return;const i=this.subsampleDepth(this.readDepth(t));e.activeTexture(e.TEXTURE0+this.depthSlot.unit),e.bindTexture(e.TEXTURE_2D,this.depthSlot.texture),e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.depthWidth,this.depthHeight,e.RED,e.UNSIGNED_BYTE,i),this.jfa&&this.jfa.markDirty()}recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:i}=this.getViewportSize(),n=Math.min(window.devicePixelRatio,this.qualityParams.dprCap),r=Math.round(e*n),o=Math.round(i*n);(this.canvas.width!==r||this.canvas.height!==o)&&(this.canvas.width=r,this.canvas.height=o,t.viewport(0,0,r,o)),(this.fboWidth!==r||this.fboHeight!==o)&&this.createFBO(r,o),this.jfa||this.createJFAResources(r,o),this.computeCoverFitUV(this.config.parallaxStrength,this.config.overscanPadding),this.interiorPass&&(t.useProgram(this.interiorPass.program),t.uniform2f(this.interiorPass.uniforms.uUvOffset,this.uvOffset[0],this.uvOffset[1]),t.uniform2f(this.interiorPass.uniforms.uUvScale,this.uvScale[0],this.uvScale[1]));const l=e/i,a=.65;this.meshScaleX=a,this.meshScaleY=a,l>this.meshAspect?this.meshScaleX=a*(this.meshAspect/l):this.meshScaleY=a*(l/this.meshAspect),this.stencilPass&&(t.useProgram(this.stencilPass.program),t.uniform2f(this.stencilPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY)),this.boundaryPass&&(t.useProgram(this.boundaryPass.program),t.uniform2f(this.boundaryPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform1f(this.boundaryPass.uniforms.uRimWidth,this.config.rimLightWidth),t.uniform2f(this.boundaryPass.uniforms.uTexelSize,1/r,1/o)),this.chamferPass&&(t.useProgram(this.chamferPass.program),t.uniform2f(this.chamferPass.uniforms.uMeshScale,this.meshScaleX,this.meshScaleY))}onContextRestored(){const t=this.canvas.getContext("webgl2",{alpha:!0,premultipliedAlpha:!0,stencil:!0});t&&(this.gl=t,this.hasColorBufferFloat=!!t.getExtension("EXT_color_buffer_float"),t.clearColor(0,0,0,0),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.recalculateViewportLayout(),this.mediaSource&&(this.animationFrameHandle=window.requestAnimationFrame(()=>this.onRenderFrame())))}disposeTextures(){const t=this.gl;t&&this.textures.disposeAll(t)}disposeFBO(){const t=this.gl;t&&(this.interiorColorTex&&(t.deleteTexture(this.interiorColorTex),this.interiorColorTex=null),this.interiorDepthTex&&(t.deleteTexture(this.interiorDepthTex),this.interiorDepthTex=null),this.interiorFbo&&(t.deleteFramebuffer(this.interiorFbo),this.interiorFbo=null),this.fboWidth=0,this.fboHeight=0)}disposeStencilGeometry(){const t=this.gl;t&&(this.stencilVao&&(t.deleteVertexArray(this.stencilVao),this.stencilVao=null),this.maskVao&&(t.deleteVertexArray(this.maskVao),this.maskVao=null),this.stencilIndexCount=0)}disposeBoundaryGeometry(){const t=this.gl;t&&(this.boundaryVao&&(t.deleteVertexArray(this.boundaryVao),this.boundaryVao=null),this.boundaryVertexCount=0)}disposeRenderer(){this.disposeTextures(),this.disposeFBO(),this.jfa&&(this.jfa.dispose(),this.jfa=null),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.disposeGPUResources(),this.gl&&(this.gl.getExtension("WEBGL_lose_context")?.loseContext(),this.gl=null)}disposeGPUResources(){const t=this.gl;if(!t)return;const e=[this.stencilPass,this.maskPass,this.jfaSeedPass,this.jfaFloodPass,this.jfaDistPass,this.interiorPass,this.compositePass,this.boundaryPass,this.chamferPass];for(const i of e)i&&i.dispose(t);this.stencilPass=null,this.maskPass=null,this.jfaSeedPass=null,this.jfaFloodPass=null,this.jfaDistPass=null,this.interiorPass=null,this.compositePass=null,this.boundaryPass=null,this.chamferPass=null,this.quadVao&&(t.deleteVertexArray(this.quadVao),this.quadVao=null)}}async function Rt(s){const t=await fetch(s);if(!t.ok)throw new Error(`Failed to fetch SVG: ${t.status} ${t.statusText}`);const e=await t.text();return Ke(e)}function Ke(s){const i=new DOMParser().parseFromString(s,"image/svg+xml").querySelector("svg");if(!i)throw new Error("No <svg> element found in document.");const n=Je(i);if(n.length===0)throw new Error("No path data found in SVG.");let r=1/0,o=1/0,l=-1/0,a=-1/0;for(const C of n)for(let S=0;S<C.length;S+=2)r=Math.min(r,C[S]),l=Math.max(l,C[S]),o=Math.min(o,C[S+1]),a=Math.max(a,C[S+1]);const h=l-r,c=a-o,f=(r+l)/2,u=(o+a)/2,x=2/Math.max(h,c),p=h/c,d=n.map(C=>{const S=[];for(let D=0;D<C.length;D+=2)S.push((C[D]-f)*x),S.push(-((C[D+1]-u)*x));return S}),y=oi(d),b=[],E=[];for(const C of y){const{flatCoords:S,holeIndices:D}=si(C),U=ai(S,D),M=b.length/2;for(const k of U)E.push(k+M);for(const k of S)b.push(k)}const g=b,v=E,m=[],T=[],R=[],A=zt(d);for(let C=0;C<d.length;C++){const S=d[C];T.push(m.length),R.push(A[C]);for(let D=0;D<S.length;D++)m.push(S[D]);S.length>=2&&m.push(S[0],S[1])}let P=1/0,F=1/0,_=-1/0,I=-1/0;for(let C=0;C<g.length;C+=2)P=Math.min(P,g[C]),_=Math.max(_,g[C]),F=Math.min(F,g[C+1]),I=Math.max(I,g[C+1]);return{vertices:new Float32Array(g),indices:new Uint16Array(v),edgeVertices:new Float32Array(m),contourOffsets:T,contourIsHole:R,bounds:{minX:P,maxX:_,minY:F,maxY:I},aspect:p}}function Je(s){const t=[];return s.querySelectorAll("path").forEach(a=>{const h=a.getAttribute("d");if(!h)return;const c=ei(h);t.push(...c)}),s.querySelectorAll("polygon").forEach(a=>{const h=a.getAttribute("points");if(!h)return;const c=Nt(h);c.length>=6&&t.push(c)}),s.querySelectorAll("polyline").forEach(a=>{const h=a.getAttribute("points");if(!h)return;const c=Nt(h);c.length>=6&&t.push(c)}),s.querySelectorAll("rect").forEach(a=>{const h=parseFloat(a.getAttribute("x")||"0"),c=parseFloat(a.getAttribute("y")||"0"),f=parseFloat(a.getAttribute("width")||"0"),u=parseFloat(a.getAttribute("height")||"0");f>0&&u>0&&t.push([h,c,h+f,c,h+f,c+u,h,c+u])}),s.querySelectorAll("circle").forEach(a=>{const h=parseFloat(a.getAttribute("cx")||"0"),c=parseFloat(a.getAttribute("cy")||"0"),f=parseFloat(a.getAttribute("r")||"0");f>0&&t.push(Qe(h,c,f))}),s.querySelectorAll("ellipse").forEach(a=>{const h=parseFloat(a.getAttribute("cx")||"0"),c=parseFloat(a.getAttribute("cy")||"0"),f=parseFloat(a.getAttribute("rx")||"0"),u=parseFloat(a.getAttribute("ry")||"0");f>0&&u>0&&t.push(ti(h,c,f,u))}),t}function Nt(s){const t=[],e=s.trim().split(/[\s,]+/);for(let i=0;i<e.length-1;i+=2){const n=parseFloat(e[i]),r=parseFloat(e[i+1]);Number.isFinite(n)&&Number.isFinite(r)&&t.push(n,r)}return t}function Qe(s,t,e,i=64){const n=[];for(let r=0;r<i;r++){const o=2*Math.PI*r/i;n.push(s+e*Math.cos(o),t+e*Math.sin(o))}return n}function ti(s,t,e,i,n=64){const r=[];for(let o=0;o<n;o++){const l=2*Math.PI*o/n;r.push(s+e*Math.cos(l),t+i*Math.sin(l))}return r}function ei(s){const t=[];let e=[],i=0,n=0,r=0,o=0,l=0,a=0,h="";const c=ii(s);let f=0;function u(){return f>=c.length?0:parseFloat(c[f++])}for(;f<c.length;){const x=c[f];let p;/^[a-zA-Z]$/.test(x)?(p=x,f++):p=h==="M"?"L":h==="m"?"l":h;const d=p===p.toLowerCase();switch(p.toUpperCase()){case"M":{e.length>0&&t.push(e),e=[];const b=u()+(d?i:0),E=u()+(d?n:0);i=b,n=E,r=b,o=E,e.push(i,n),l=i,a=n;break}case"L":{i=u()+(d?i:0),n=u()+(d?n:0),e.push(i,n),l=i,a=n;break}case"H":{i=u()+(d?i:0),e.push(i,n),l=i,a=n;break}case"V":{n=u()+(d?n:0),e.push(i,n),l=i,a=n;break}case"C":{const b=u()+(d?i:0),E=u()+(d?n:0),g=u()+(d?i:0),v=u()+(d?n:0),m=u()+(d?i:0),T=u()+(d?n:0);nt(e,i,n,b,E,g,v,m,T),i=m,n=T,l=g,a=v;break}case"S":{const b=2*i-l,E=2*n-a,g=u()+(d?i:0),v=u()+(d?n:0),m=u()+(d?i:0),T=u()+(d?n:0);nt(e,i,n,b,E,g,v,m,T),i=m,n=T,l=g,a=v;break}case"Q":{const b=u()+(d?i:0),E=u()+(d?n:0),g=u()+(d?i:0),v=u()+(d?n:0);Gt(e,i,n,b,E,g,v),i=g,n=v,l=b,a=E;break}case"T":{const b=2*i-l,E=2*n-a,g=u()+(d?i:0),v=u()+(d?n:0);Gt(e,i,n,b,E,g,v),i=g,n=v,l=b,a=E;break}case"A":{const b=u(),E=u(),g=u(),v=u(),m=u(),T=u()+(d?i:0),R=u()+(d?n:0);ri(e,i,n,b,E,g,!!v,!!m,T,R),i=T,n=R,l=i,a=n;break}case"Z":{i=r,n=o,e.length>0&&t.push(e),e=[],l=i,a=n;break}default:f++;break}h=p}return e.length>=6&&t.push(e),t}function ii(s){const t=[],e=/([a-zA-Z])|([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)/g;let i;for(;(i=e.exec(s))!==null;)t.push(i[0]);return t}const ni=.5;function nt(s,t,e,i,n,r,o,l,a,h=0){if(h>12){s.push(l,a);return}const c=l-t,f=a-e,u=Math.sqrt(c*c+f*f);if(u<1e-6){s.push(l,a);return}const x=Math.abs((i-l)*f-(n-a)*c)/u,p=Math.abs((r-l)*f-(o-a)*c)/u;if(x+p<ni){s.push(l,a);return}const d=(t+i)/2,y=(e+n)/2,b=(i+r)/2,E=(n+o)/2,g=(r+l)/2,v=(o+a)/2,m=(d+b)/2,T=(y+E)/2,R=(b+g)/2,A=(E+v)/2,P=(m+R)/2,F=(T+A)/2;nt(s,t,e,d,y,m,T,P,F,h+1),nt(s,P,F,R,A,g,v,l,a,h+1)}function Gt(s,t,e,i,n,r,o){const l=t+.6666666666666666*(i-t),a=e+2/3*(n-e),h=r+2/3*(i-r),c=o+2/3*(n-o);nt(s,t,e,l,a,h,c,r,o)}function ri(s,t,e,i,n,r,o,l,a,h){if(i===0||n===0){s.push(a,h);return}let c=Math.abs(i),f=Math.abs(n);const u=r*Math.PI/180,x=Math.cos(u),p=Math.sin(u),d=(t-a)/2,y=(e-h)/2,b=x*d+p*y,E=-p*d+x*y;let g=b*b/(c*c)+E*E/(f*f);if(g>1){const U=Math.sqrt(g);c*=U,f*=U,g=1}const v=c*c,m=f*f,T=b*b,R=E*E;let A=Math.max(0,(v*m-v*R-m*T)/(v*R+m*T));A=Math.sqrt(A),o===l&&(A=-A);const P=A*(c*E)/f,F=A*-(f*b)/c,_=x*P-p*F+(t+a)/2,I=p*P+x*F+(e+h)/2,C=Wt(1,0,(b-P)/c,(E-F)/f);let S=Wt((b-P)/c,(E-F)/f,(-b-P)/c,(-E-F)/f);!l&&S>0&&(S-=2*Math.PI),l&&S<0&&(S+=2*Math.PI);const D=Math.max(4,Math.ceil(Math.abs(S)/(Math.PI/16)));for(let U=1;U<=D;U++){const M=C+U/D*S,k=Math.cos(M),et=Math.sin(M),at=x*c*k-p*f*et+_,Et=p*c*k+x*f*et+I;s.push(at,Et)}}function Wt(s,t,e,i){const n=s*i-t*e<0?-1:1,r=s*e+t*i,o=Math.sqrt(s*s+t*t),l=Math.sqrt(e*e+i*i),a=r/(o*l);return n*Math.acos(Math.max(-1,Math.min(1,a)))}function si(s){const t=[],e=[];for(let i=0;i<s.length;i++){i>0&&e.push(t.length/2);for(const n of s[i])t.push(n)}return{flatCoords:t,holeIndices:e}}function zt(s){const t=s.length,e=s.map(n=>Math.abs(qt(n))),i=new Array(t).fill(!1);for(let n=0;n<t;n++){let r=0;const o=s[n][0],l=s[n][1];for(let a=0;a<t;a++)n!==a&&e[a]>e[n]&&Yt(o,l,s[a])&&r++;i[n]=r%2===1}return i}function oi(s){if(s.length<=1)return[s];const t=zt(s),e=s.map((o,l)=>{const a=qt(o);return{index:l,contour:o,area:a,isOuter:!t[l]}}),i=e.filter(o=>o.isOuter),n=e.filter(o=>!o.isOuter);if(i.length===0)return s.map(o=>[o]);const r=i.map(o=>({outer:o.contour,holes:[]}));for(const o of n){const l=o.contour[0],a=o.contour[1];let h=-1,c=1/0;for(let f=0;f<i.length;f++)if(Yt(l,a,i[f].contour)){const u=Math.abs(i[f].area);u<c&&(c=u,h=f)}h>=0?r[h].holes.push(o.contour):r.push({outer:o.contour,holes:[]})}return r.map(o=>[o.outer,...o.holes])}function qt(s){let t=0;const e=s.length;for(let i=0;i<e;i+=2){const n=s[i],r=s[i+1],o=s[(i+2)%e],l=s[(i+3)%e];t+=n*l-o*r}return t/2}function Yt(s,t,e){let i=!1;const n=e.length;for(let r=0,o=n-2;r<n;o=r,r+=2){const l=e[r],a=e[r+1],h=e[o],c=e[o+1];a>t!=c>t&&s<(h-l)*(t-a)/(c-a)+l&&(i=!i)}return i}function ai(s,t,e=2){const i=t&&t.length>0,n=i?t[0]*e:s.length;let r=jt(s,0,n,e,!0);const o=[];if(!r||r.next===r.prev)return o;i&&(r=fi(s,t,r,e));let l=1/0,a=1/0,h=-1/0,c=-1/0,f=0;if(s.length>80*e){for(let u=0;u<n;u+=e){const x=s[u],p=s[u+1];x<l&&(l=x),p<a&&(a=p),x>h&&(h=x),p>c&&(c=p)}f=Math.max(h-l,c-a),f=f!==0?32767/f:0}return rt(r,o,e,l,a,f,0),o}function jt(s,t,e,i,n){let r=null;if(n===Si(s,t,e,i)>0)for(let o=t;o<e;o+=i)r=Kt(o,s[o],s[o+1],r);else for(let o=e-i;o>=t;o-=i)r=Kt(o,s[o],s[o+1],r);return r&>(r,r.next)&&(ot(r),r=r.next),r?(r.next.prev=r,r.prev.next=r,r.next):null}function j(s,t){t||(t=s);let e=s,i;do if(i=!1,!e.steiner&&(gt(e,e.next)||L(e.prev,e,e.next)===0)){if(ot(e),e=t=e.prev,e===e.next)break;i=!0}else e=e.next;while(i||e!==t);return t}function rt(s,t,e,i,n,r,o){if(!s)return;!o&&r&&gi(s,i,n,r);let l=s,a,h;for(;s.prev!==s.next;){if(a=s.prev,h=s.next,r?ui(s,i,n,r):li(s)){t.push(a.i/e,s.i/e,h.i/e),ot(s),s=h.next,l=h.next;continue}if(s=h,s===l){o?o===1?(s=ci(j(s),t,e),rt(s,t,e,i,n,r,2)):o===2&&hi(s,t,e,i,n,r):rt(j(s),t,e,i,n,r,1);break}}}function li(s){const t=s.prev,e=s,i=s.next;if(L(t,e,i)>=0)return!1;const n=t.x,r=e.x,o=i.x,l=t.y,a=e.y,h=i.y,c=n<r?n<o?n:o:r<o?r:o,f=l<a?l<h?l:h:a<h?a:h,u=n>r?n>o?n:o:r>o?r:o,x=l>a?l>h?l:h:a>h?a:h;let p=i.next;for(;p!==t;){if(p.x>=c&&p.x<=u&&p.y>=f&&p.y<=x&&J(n,l,r,a,o,h,p.x,p.y)&&L(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function ui(s,t,e,i){const n=s.prev,r=s,o=s.next;if(L(n,r,o)>=0)return!1;const l=n.x,a=r.x,h=o.x,c=n.y,f=r.y,u=o.y,x=l<a?l<h?l:h:a<h?a:h,p=c<f?c<u?c:u:f<u?f:u,d=l>a?l>h?l:h:a>h?a:h,y=c>f?c>u?c:u:f>u?f:u,b=At(x,p,t,e,i),E=At(d,y,t,e,i);let g=s.prevZ,v=s.nextZ;for(;g&&g.z>=b&&v&&v.z<=E;){if(g.x>=x&&g.x<=d&&g.y>=p&&g.y<=y&&g!==n&&g!==o&&J(l,c,a,f,h,u,g.x,g.y)&&L(g.prev,g,g.next)>=0||(g=g.prevZ,v.x>=x&&v.x<=d&&v.y>=p&&v.y<=y&&v!==n&&v!==o&&J(l,c,a,f,h,u,v.x,v.y)&&L(v.prev,v,v.next)>=0))return!1;v=v.nextZ}for(;g&&g.z>=b;){if(g.x>=x&&g.x<=d&&g.y>=p&&g.y<=y&&g!==n&&g!==o&&J(l,c,a,f,h,u,g.x,g.y)&&L(g.prev,g,g.next)>=0)return!1;g=g.prevZ}for(;v&&v.z<=E;){if(v.x>=x&&v.x<=d&&v.y>=p&&v.y<=y&&v!==n&&v!==o&&J(l,c,a,f,h,u,v.x,v.y)&&L(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function ci(s,t,e){let i=s;do{const n=i.prev,r=i.next.next;!gt(n,r)&&Zt(n,i,i.next,r)&&st(n,r)&&st(r,n)&&(t.push(n.i/e,i.i/e,r.i/e),ot(i),ot(i.next),i=s=r),i=i.next}while(i!==s);return j(i)}function hi(s,t,e,i,n,r){let o=s;do{let l=o.next.next;for(;l!==o.prev;){if(o.i!==l.i&&Ti(o,l)){let a=$t(o,l);o=j(o,o.next),a=j(a,a.next),rt(o,t,e,i,n,r,0),rt(a,t,e,i,n,r,0);return}l=l.next}o=o.next}while(o!==s)}function fi(s,t,e,i){const n=[];for(let r=0;r<t.length;r++){const o=t[r]*i,l=r<t.length-1?t[r+1]*i:s.length,a=jt(s,o,l,i,!1);a&&(a===a.next&&(a.steiner=!0),n.push(xi(a)))}n.sort((r,o)=>r.x-o.x);for(const r of n)e=di(r,e);return e}function di(s,t){const e=mi(s,t);if(!e)return t;const i=$t(e,s);return j(i,i.next),j(e,e.next)}function mi(s,t){let e=t;const i=s.x,n=s.y;let r=-1/0,o=null;do{if(n<=e.y&&n>=e.next.y&&e.next.y!==e.y){const f=e.x+(n-e.y)/(e.next.y-e.y)*(e.next.x-e.x);if(f<=i&&f>r&&(r=f,o=e.x<e.next.x?e:e.next,f===i))return o}e=e.next}while(e!==t);if(!o)return null;const l=o,a=o.x,h=o.y;let c=1/0;e=o;do{if(i>=e.x&&e.x>=a&&i!==e.x&&J(n<h?i:r,n,a,h,n<h?r:i,n,e.x,e.y)){const f=Math.abs(n-e.y)/(i-e.x);st(e,s)&&(f<c||f===c&&(e.x>o.x||pi(o,e)))&&(o=e,c=f)}e=e.next}while(e!==l);return o}function pi(s,t){return L(s.prev,s,t.prev)<0&&L(t.next,s,s.next)<0}function gi(s,t,e,i){let n=s;do n.z===0&&(n.z=At(n.x,n.y,t,e,i)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next;while(n!==s);n.prevZ.nextZ=null,n.prevZ=null,vi(n)}function vi(s){let t=1,e;do{let i=s;s=null;let n=null;for(e=0;i;){e++;let r=i,o=0;for(let a=0;a<t&&(o++,r=r.nextZ,!!r);a++);let l=t;for(;o>0||l>0&&r;){let a;o!==0&&(l===0||!r||i.z<=r.z)?(a=i,i=i.nextZ,o--):(a=r,r=r.nextZ,l--),n?n.nextZ=a:s=a,a.prevZ=n,n=a}i=r}n.nextZ=null,t*=2}while(e>1);return s}function At(s,t,e,i,n){let r=(s-e)*n|0,o=(t-i)*n|0;return r=(r|r<<8)&16711935,r=(r|r<<4)&252645135,r=(r|r<<2)&858993459,r=(r|r<<1)&1431655765,o=(o|o<<8)&16711935,o=(o|o<<4)&252645135,o=(o|o<<2)&858993459,o=(o|o<<1)&1431655765,r|o<<1}function xi(s){let t=s,e=s;do(t.x<e.x||t.x===e.x&&t.y<e.y)&&(e=t),t=t.next;while(t!==s);return e}function J(s,t,e,i,n,r,o,l){return(n-o)*(t-l)-(s-o)*(r-l)>=0&&(s-o)*(i-l)-(e-o)*(t-l)>=0&&(e-o)*(r-l)-(n-o)*(i-l)>=0}function Ti(s,t){return s.next.i!==t.i&&s.prev.i!==t.i&&!Ei(s,t)&&(st(s,t)&&st(t,s)&&bi(s,t)&&(L(s.prev,s,t.prev)!==0||L(s,t.prev,t)!==0)||gt(s,t)&&L(s.prev,s,s.next)>0&&L(t.prev,t,t.next)>0)}function L(s,t,e){return(t.y-s.y)*(e.x-t.x)-(t.x-s.x)*(e.y-t.y)}function gt(s,t){return s.x===t.x&&s.y===t.y}function Zt(s,t,e,i){const n=xt(L(s,t,e)),r=xt(L(s,t,i)),o=xt(L(e,i,s)),l=xt(L(e,i,t));return!!(n!==r&&o!==l||n===0&&vt(s,e,t)||r===0&&vt(s,i,t)||o===0&&vt(e,s,i)||l===0&&vt(e,t,i))}function vt(s,t,e){return t.x<=Math.max(s.x,e.x)&&t.x>=Math.min(s.x,e.x)&&t.y<=Math.max(s.y,e.y)&&t.y>=Math.min(s.y,e.y)}function xt(s){return s>0?1:s<0?-1:0}function Ei(s,t){let e=s;do{if(e.i!==s.i&&e.next.i!==s.i&&e.i!==t.i&&e.next.i!==t.i&&Zt(e,e.next,s,t))return!0;e=e.next}while(e!==s);return!1}function st(s,t){return L(s.prev,s,s.next)<0?L(s,t,s.next)>=0&&L(s,s.prev,t)>=0:L(s,t,s.prev)<0||L(s,s.next,t)<0}function bi(s,t){let e=s,i=!1;const n=(s.x+t.x)/2,r=(s.y+t.y)/2;do e.y>r!=e.next.y>r&&e.next.y!==e.y&&n<(e.next.x-e.x)*(r-e.y)/(e.next.y-e.y)+e.x&&(i=!i),e=e.next;while(e!==s);return i}function $t(s,t){const e=Pt(s.i,s.x,s.y),i=Pt(t.i,t.x,t.y),n=s.next,r=t.prev;return s.next=t,t.prev=s,e.next=n,n.prev=e,i.next=e,e.prev=i,r.next=i,i.prev=r,i}function Kt(s,t,e,i){const n=Pt(s,t,e);return i?(n.next=i.next,n.prev=i,i.next.prev=n,i.next=n):(n.prev=n,n.next=n),n}function ot(s){s.next.prev=s.prev,s.prev.next=s.next,s.prevZ&&(s.prevZ.nextZ=s.nextZ),s.nextZ&&(s.nextZ.prevZ=s.prevZ)}function Pt(s,t,e){return{i:s,x:t,y:e,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function Si(s,t,e,i){let n=0;for(let r=t,o=e-i;r<e;r+=i)n+=(s[o]-s[r])*(s[r+1]+s[o+1]),o=r;return n}const w={parallaxX:.4,parallaxY:.8,parallaxMax:30,overscan:.06,pomSteps:16,rimIntensity:.6,rimColor:"#ffffff",rimWidth:.025,refractionStrength:.015,chromaticStrength:.008,occlusionIntensity:.4,depthPower:.7,depthScale:1.2,depthBias:-.05,fogDensity:.15,fogColor:"#1a1a2e",colorShift:.6,brightnessBias:.05,contrastLow:.02,contrastHigh:.98,verticalReduction:.5,dofStart:.5,dofStrength:.5,bevelIntensity:.5,bevelWidth:.04,bevelDarkening:.2,bevelDesaturation:.12,bevelLightAngle:135,edgeThickness:.01,edgeSpecular:.35,edgeColor:"#a0a0a0",chamferWidth:.025,chamferAngle:45,chamferColor:"#262630",chamferAmbient:.12,chamferSpecular:.3,chamferShininess:24,edgeOcclusionWidth:.03,edgeOcclusionStrength:.2,lightDirection:"-0.5,0.7,-0.3",autoplay:!0,loop:!0,muted:!0},Q=512,tt=512;class Tt extends HTMLElement{static TAG_NAME="layershift-portal";static get observedAttributes(){return["src","map-src","map-width","map-height","map-fps","depth-model","logo-src","source-type","parallax-x","parallax-y","parallax-max","overscan","pom-steps","quality","gpu-backend","rim-intensity","rim-color","rim-width","refraction-strength","chromatic-strength","occlusion-intensity","depth-power","depth-scale","depth-bias","fog-density","fog-color","color-shift","brightness-bias","contrast-low","contrast-high","vertical-reduction","dof-start","dof-strength","bevel-intensity","bevel-width","bevel-darkening","bevel-desaturation","bevel-light-angle","edge-thickness","edge-specular","edge-color","chamfer-width","chamfer-angle","chamfer-color","chamfer-ambient","chamfer-specular","chamfer-shininess","edge-occlusion-width","edge-occlusion-strength","light-direction","autoplay","loop","muted"]}reinitAttributes=["src","map-src","map-width","map-height","map-fps","depth-model","logo-src","source-type"];canInit(){const t=!!this.getAttribute("logo-src");if(this.sourceType==="camera")return t;const e=!!this.getAttribute("src"),i=!!this.getAttribute("map-src"),n=!!this.getAttribute("depth-model");return e&&t&&(i||n)}_input={x:0,y:0};get input(){return{x:this._input.x,y:this._input.y}}set input(t){this._input.x=t.x,this._input.y=t.y}shadow;container=null;renderer=null;source=null;depthEstimator=null;mesh=null;loopCount=0;lifecycle;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.lifecycle=new Xt(this)}getAttrFloat(t,e){const i=this.getAttribute(t);if(i===null)return e;const n=parseFloat(i);return Number.isFinite(n)?n:e}getAttrBool(t,e){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return!(i==="false"||i==="0")}getAttrColor(t,e){const i=this.getAttribute(t)??e;return yi(i)}getAttrVec3(t,e){const n=(this.getAttribute(t)??e).split(",").map(o=>parseFloat(o.trim()));if(n.length>=3&&n.every(Number.isFinite))return[n[0],n[1],n[2]];const r=e.split(",").map(o=>parseFloat(o.trim()));return[r[0],r[1],r[2]]}get sourceType(){const t=this.getAttribute("source-type");return t==="camera"?"camera":t==="image"?"image":"video"}get parallaxX(){return this.getAttrFloat("parallax-x",w.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",w.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",w.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",w.overscan)}get pomSteps(){return this.getAttrFloat("pom-steps",w.pomSteps)}get quality(){const t=this.getAttribute("quality");if(t==="auto"||t==="high"||t==="medium"||t==="low")return t}get gpuBackend(){return"webgl2"}get rimIntensity(){return this.getAttrFloat("rim-intensity",w.rimIntensity)}get rimWidth(){return this.getAttrFloat("rim-width",w.rimWidth)}get rimColor(){return this.getAttrColor("rim-color",w.rimColor)}get refractionStrength(){return this.getAttrFloat("refraction-strength",w.refractionStrength)}get chromaticStrength(){return this.getAttrFloat("chromatic-strength",w.chromaticStrength)}get occlusionIntensity(){return this.getAttrFloat("occlusion-intensity",w.occlusionIntensity)}get depthPower(){return this.getAttrFloat("depth-power",w.depthPower)}get depthScale(){return this.getAttrFloat("depth-scale",w.depthScale)}get depthBias(){return this.getAttrFloat("depth-bias",w.depthBias)}get fogDensity(){return this.getAttrFloat("fog-density",w.fogDensity)}get fogColor(){return this.getAttrColor("fog-color",w.fogColor)}get colorShift(){return this.getAttrFloat("color-shift",w.colorShift)}get brightnessBias(){return this.getAttrFloat("brightness-bias",w.brightnessBias)}get contrastLow(){return this.getAttrFloat("contrast-low",w.contrastLow)}get contrastHigh(){return this.getAttrFloat("contrast-high",w.contrastHigh)}get verticalReduction(){return this.getAttrFloat("vertical-reduction",w.verticalReduction)}get dofStart(){return this.getAttrFloat("dof-start",w.dofStart)}get dofStrength(){return this.getAttrFloat("dof-strength",w.dofStrength)}get bevelIntensity(){return this.getAttrFloat("bevel-intensity",w.bevelIntensity)}get bevelWidth(){return this.getAttrFloat("bevel-width",w.bevelWidth)}get bevelDarkening(){return this.getAttrFloat("bevel-darkening",w.bevelDarkening)}get bevelDesaturation(){return this.getAttrFloat("bevel-desaturation",w.bevelDesaturation)}get bevelLightAngle(){return this.getAttrFloat("bevel-light-angle",w.bevelLightAngle)}get edgeThickness(){return this.getAttrFloat("edge-thickness",w.edgeThickness)}get edgeSpecular(){return this.getAttrFloat("edge-specular",w.edgeSpecular)}get edgeColor(){return this.getAttrColor("edge-color",w.edgeColor)}get chamferWidth(){return this.getAttrFloat("chamfer-width",w.chamferWidth)}get chamferAngle(){return this.getAttrFloat("chamfer-angle",w.chamferAngle)}get chamferColor(){return this.getAttrColor("chamfer-color",w.chamferColor)}get chamferAmbient(){return this.getAttrFloat("chamfer-ambient",w.chamferAmbient)}get chamferSpecular(){return this.getAttrFloat("chamfer-specular",w.chamferSpecular)}get chamferShininess(){return this.getAttrFloat("chamfer-shininess",w.chamferShininess)}get edgeOcclusionWidth(){return this.getAttrFloat("edge-occlusion-width",w.edgeOcclusionWidth)}get edgeOcclusionStrength(){return this.getAttrFloat("edge-occlusion-strength",w.edgeOcclusionStrength)}get lightDirection3(){return this.getAttrVec3("light-direction",w.lightDirection)}get depthModel(){return this.getAttribute("depth-model")}get shouldAutoplay(){return this.getAttrBool("autoplay",w.autoplay)}get shouldLoop(){return this.getAttrBool("loop",w.loop)}get shouldMute(){return this.getAttrBool("muted",w.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachSourceEventListeners(t){t.addEventListener&&(t.addEventListener("play",(()=>{this.emit("layershift-portal:play",{currentTime:t.currentTime})})),t.addEventListener("pause",(()=>{this.emit("layershift-portal:pause",{currentTime:t.currentTime})})),t.addEventListener("ended",(()=>{this.loopCount+=1,this.emit("layershift-portal:loop",{loopCount:this.loopCount})})))}connectedCallback(){console.warn("[layershift] <layershift-portal> is deprecated and will be removed in a future major version. Use <layershift-effect> with a filter-config.json instead. See https://layershift.io/docs/migration"),this.lifecycle.onConnected()}disconnectedCallback(){this.lifecycle.onDisconnected()}attributeChangedCallback(t,e,i){this.lifecycle.onAttributeChanged(t,e,i)}setupShadowDOM(){this.shadow.innerHTML="";const t=document.createElement("style");t.textContent=`
|
|
1040
1040
|
:host {
|
|
1041
1041
|
display: block;
|
|
1042
1042
|
width: 100%;
|
|
@@ -1056,4 +1056,4 @@ void main() {
|
|
|
1056
1056
|
width: 100%;
|
|
1057
1057
|
height: 100%;
|
|
1058
1058
|
}
|
|
1059
|
-
`,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async doInit(t){const e=this.getAttribute("logo-src");if(!this.container)return;const
|
|
1059
|
+
`,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async doInit(t){const e=this.getAttribute("logo-src");if(!this.container)return;const i=this.sourceType==="camera",n=this.depthModel;try{let r,o,l,a=null;const h=d=>{this.emit("layershift-portal:model-progress",d)};if(i){const[d,y]=await Promise.all([Bt({video:{facingMode:"user"}},{parent:this.shadow}),Rt(e)]);if(t.aborted){d.dispose();return}if(r=d,l=y,n){if(a=await dt(n,Q,tt,h),t.aborted){a.dispose(),r.dispose();return}o=N(Q,tt)}else o=N(r.width,r.height)}else{const d=this.getAttribute("src"),y=this.getAttribute("map-src"),b=!!y,E=this.sourceType==="image"||/\.(jpe?g|png|webp|gif|avif|bmp)(\?|$)/i.test(d);if(b){const[g,v,m]=await Promise.all([E?ft(d):ht(d,{parent:this.shadow,loop:this.shouldLoop,muted:this.shouldMute}),Ft(y,this.getAttrFloat("map-width",512),this.getAttrFloat("map-height",512),this.getAttrFloat("map-fps",5)),Rt(e)]);if(t.aborted){g.dispose();return}r=g,o=v,l=m}else if(n){const[g,v,m]=await Promise.all([E?ft(d):ht(d,{parent:this.shadow,loop:this.shouldLoop,muted:this.shouldMute}),dt(n,Q,tt,h),Rt(e)]);if(t.aborted){g.dispose(),v.dispose();return}if(r=g,a=v,l=m,E||!r.isLive){const T=r.getImageSource();if(T){const R=await a.submitFrameAndWait(T);o={width:Q,height:tt,fps:1,frameCount:1,frames:[R]}}else o=N(Q,tt)}else o=N(Q,tt)}else throw new Error("Either map-src or depth-model must be provided.")}this.source=r,this.depthEstimator=a,this.mesh=l,this.loopCount=0,this.attachSourceEventListeners(r);const c=this.container?.clientWidth||r.width,f=this.parallaxMax/Math.max(c,1);let u;if(a)u=()=>a.getLatestDepth();else{const d=new Dt(o);u=y=>d.sample(y)}const x={parallaxStrength:f,overscanPadding:this.overscan,pomSteps:this.pomSteps,quality:this.quality,rimLightIntensity:this.rimIntensity,rimLightColor:this.rimColor,rimLightWidth:this.rimWidth,refractionStrength:this.refractionStrength,chromaticStrength:this.chromaticStrength,occlusionIntensity:this.occlusionIntensity,depthPower:this.depthPower,depthScale:this.depthScale,depthBias:this.depthBias,fogDensity:this.fogDensity,fogColor:this.fogColor,colorShift:this.colorShift,brightnessBias:this.brightnessBias,contrastLow:this.contrastLow,contrastHigh:this.contrastHigh,verticalReduction:this.verticalReduction,dofStart:this.dofStart,dofStrength:this.dofStrength,bevelIntensity:this.bevelIntensity,bevelWidth:this.bevelWidth,bevelDarkening:this.bevelDarkening,bevelDesaturation:this.bevelDesaturation,bevelLightAngle:this.bevelLightAngle,edgeThickness:this.edgeThickness,edgeSpecular:this.edgeSpecular,edgeColor:this.edgeColor,chamferWidth:this.chamferWidth,chamferAngle:this.chamferAngle,chamferColor:this.chamferColor,chamferAmbient:this.chamferAmbient,chamferSpecular:this.chamferSpecular,chamferShininess:this.chamferShininess,edgeOcclusionWidth:this.edgeOcclusionWidth,edgeOcclusionStrength:this.edgeOcclusionStrength,lightDirection:this.lightDirection3};if(t.aborted)return;this.renderer=new $e(this.container,x),this.renderer.initialize(r,o.width,o.height,l);const p=a;if(this.renderer.start(r,u,()=>({x:this._input.x,y:this._input.y}),(d,y)=>{if(p){const b=r.getImageSource();b&&p.submitFrame(b)}this.emit("layershift-portal:frame",{currentTime:d,frameNumber:y})}),!i&&r.isLive&&this.shouldAutoplay&&r.play)try{await r.play()}catch{}if(t.aborted)return;this.lifecycle.markInitialized(),this.emit("layershift-portal:ready",{videoWidth:r.width,videoHeight:r.height,duration:r.duration})}catch(r){const o=r instanceof Error?r.message:"Failed to initialize.";console.error("<layershift-portal>: Failed to initialize.",r),this.emit("layershift-portal:error",{message:o})}}doDispose(){this.renderer?.dispose(),this.renderer=null,this.depthEstimator?.dispose(),this.depthEstimator=null,this.source?.dispose(),this.source=null,this.mesh=null,this.loopCount=0,this.container=null}}function yi(s){const t=s.replace("#","");if(t.length===3){const e=parseInt(t[0]+t[0],16)/255,i=parseInt(t[1]+t[1],16)/255,n=parseInt(t[2]+t[2],16)/255;return[e,i,n]}if(t.length===6){const e=parseInt(t.substring(0,2),16)/255,i=parseInt(t.substring(2,4),16)/255,n=parseInt(t.substring(4,6),16)/255;return[e,i,n]}return[0,0,0]}function V(s,t,e){return Math.min(e,Math.max(t,s))}function W(s,t,e){return s+(t-s)*e}const z=100,Jt=.06;function wi(s,t){const e=t?.sensitivityX??1,i=t?.sensitivityY??1,n=t?.lerpFactor??.08;let r=0,o=0,l=0,a=0,h=0,c=!0;const f=p=>{const d=s.getBoundingClientRect(),y=(p.clientX-d.left)/d.width*2-1,b=(p.clientY-d.top)/d.height*2-1;r=V(y,-1,1),o=V(b,-1,1)},u=()=>{r=0,o=0},x=()=>{c&&(l=W(l,r,n),a=W(a,o,n),s.input={x:l*e,y:a*i},h=requestAnimationFrame(x))};return s.addEventListener("mousemove",f),s.addEventListener("mouseleave",u),h=requestAnimationFrame(x),()=>{c=!1,cancelAnimationFrame(h),s.removeEventListener("mousemove",f),s.removeEventListener("mouseleave",u)}}function Ri(s,t){const e=t?.sensitivityX??1,i=t?.sensitivityY??1,n=t?.lerpFactor??.08;let r=0,o=0,l=0,a=0,h=0,c=0,f=0,u=!0;const x=b=>{const E=b.touches[0];E&&(h=E.clientX-l*z,c=E.clientY-a*z,r=l,o=a)},p=b=>{const E=b.touches[0];if(!E)return;const g=E.clientX-h,v=E.clientY-c;r=V(g/z,-1,1),o=V(v/z,-1,1)},d=()=>{r=0,o=0},y=()=>{u&&(l=W(l,r,n),a=W(a,o,n),s.input={x:l*e,y:a*i},f=requestAnimationFrame(y))};return s.addEventListener("touchstart",x,{passive:!0}),s.addEventListener("touchmove",p,{passive:!0}),s.addEventListener("touchend",d,{passive:!0}),s.addEventListener("touchcancel",d,{passive:!0}),f=requestAnimationFrame(y),()=>{u=!1,cancelAnimationFrame(f),s.removeEventListener("touchstart",x),s.removeEventListener("touchmove",p),s.removeEventListener("touchend",d),s.removeEventListener("touchcancel",d)}}function Ai(s,t){const e=t?.sensitivityX??1,i=t?.sensitivityY??1,n=t?.lerpFactor??Jt;let r=0,o=0,l=0,a=0,h=0,c=!0,f=!1;const u=y=>{r=V((y.gamma??0)/45,-1,1),o=V((y.beta??0)/45,-1,1)},x=()=>{c&&(l=W(l,r,n),a=W(a,o,n),s.input={x:l*e,y:a*i},h=requestAnimationFrame(x))},p=()=>{c&&!f&&(window.addEventListener("deviceorientation",u),f=!0)},d=DeviceOrientationEvent;return typeof d.requestPermission=="function"?d.requestPermission().then(y=>{y==="granted"&&p()}).catch(()=>{}):p(),h=requestAnimationFrame(x),()=>{c=!1,cancelAnimationFrame(h),f&&(window.removeEventListener("deviceorientation",u),f=!1)}}function Pi(s,t){const e=t?.sensitivityX??1,i=t?.sensitivityY??1,n=t?.lerpFactor??.08,r=t?.lerpFactor??Jt;let o=0,l=0,a=0,h=0,c=0,f=0,u=0,x=0,p=!1,d=!1,y=!1,b=0,E=0,g=0,v=!0;const m=S=>{const D=s.getBoundingClientRect(),U=(S.clientX-D.left)/D.width*2-1,M=(S.clientY-D.top)/D.height*2-1;o=V(U,-1,1),l=V(M,-1,1)},T=()=>{o=0,l=0},R=S=>{const D=S.touches[0];D&&(p=!0,b=D.clientX-u*z,E=D.clientY-x*z,a=u,h=x,!d&&!y&&I())},A=S=>{const D=S.touches[0];if(!D)return;const U=D.clientX-b,M=D.clientY-E;a=V(U/z,-1,1),h=V(M/z,-1,1)},P=()=>{p=!1,a=0,h=0},F=S=>{c=V((S.gamma??0)/45,-1,1),f=V((S.beta??0)/45,-1,1)},_=()=>{v&&!y&&(window.addEventListener("deviceorientation",F),y=!0,d=!0)},I=()=>{if(typeof DeviceOrientationEvent>"u")return;const S=DeviceOrientationEvent;typeof S.requestPermission=="function"?S.requestPermission().then(D=>{D==="granted"&&_()}).catch(()=>{}):_()},C=()=>{if(!v)return;let S,D,U;p?(S=a,D=h,U=n):d?(S=c,D=f,U=r):(S=o,D=l,U=n),u=W(u,S,U),x=W(x,D,U),s.input={x:u*e,y:x*i},g=requestAnimationFrame(C)};return s.addEventListener("mousemove",m),s.addEventListener("mouseleave",T),s.addEventListener("touchstart",R,{passive:!0}),s.addEventListener("touchmove",A,{passive:!0}),s.addEventListener("touchend",P,{passive:!0}),s.addEventListener("touchcancel",P,{passive:!0}),g=requestAnimationFrame(C),()=>{v=!1,cancelAnimationFrame(g),s.removeEventListener("mousemove",m),s.removeEventListener("mouseleave",T),s.removeEventListener("touchstart",R),s.removeEventListener("touchmove",A),s.removeEventListener("touchend",P),s.removeEventListener("touchcancel",P),y&&(window.removeEventListener("deviceorientation",F),y=!1)}}return customElements.get(pt.TAG_NAME)||customElements.define(pt.TAG_NAME,pt),customElements.get(Tt.TAG_NAME)||customElements.define(Tt.TAG_NAME,Tt),X.LayershiftElement=pt,X.LayershiftPortalElement=Tt,X.connectGyro=Ai,X.connectMouse=wi,X.connectPointer=Pi,X.connectTouch=Ri,Object.defineProperty(X,Symbol.toStringTag,{value:"Module"}),X})({});
|