layershift 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/layershift.js +28 -28
- package/dist/npm/layershift.es.js +895 -851
- package/dist/types/components/layershift/layershift-element.d.ts +8 -7
- package/dist/types/components/layershift/layershift-element.d.ts.map +1 -1
- package/dist/types/components/layershift/lifecycle.d.ts +77 -0
- package/dist/types/components/layershift/lifecycle.d.ts.map +1 -0
- package/dist/types/components/layershift/portal-element.d.ts +8 -7
- package/dist/types/components/layershift/portal-element.d.ts.map +1 -1
- package/dist/types/parallax-renderer.d.ts.map +1 -1
- package/dist/types/portal-renderer.d.ts +1 -0
- package/dist/types/portal-renderer.d.ts.map +1 -1
- package/package.json +15 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var Layershift=(function(et){"use strict";var ut=typeof document<"u"?document.currentScript:null;class it{worker;currentBuffer;pendingTimeSec=null;workerBusy=!1;disposed=!1;constructor(t,e){this.worker=t,this.currentBuffer=new Uint8Array(e)}static async create(t,e,i){const
|
|
1
|
+
var Layershift=(function(et){"use strict";var ut=typeof document<"u"?document.currentScript:null;class it{worker;currentBuffer;pendingTimeSec=null;workerBusy=!1;disposed=!1;constructor(t,e){this.worker=t,this.currentBuffer=new Uint8Array(e)}static async create(t,e,i){const o=new Worker(new URL("/assets/depth-worker-CMcEa805.js",ut&&ut.tagName.toUpperCase()==="SCRIPT"&&ut.src||new URL("layershift.js",document.baseURI).href),{type:"module"}),n=e*i,s=new it(o,n),h=t.frames.map(a=>{const l=new Uint8Array(a.length);return l.set(a),l.buffer});return await new Promise((a,l)=>{const u=setTimeout(()=>l(new Error("Worker init timeout")),1e4);o.onmessage=f=>{f.data.type==="ready"&&(clearTimeout(u),a())},o.onerror=f=>{clearTimeout(u),l(f)},o.postMessage({type:"init",frames:h,meta:{frameCount:t.meta.frameCount,fps:t.meta.fps,width:t.meta.width,height:t.meta.height},targetWidth:e,targetHeight:i},h)}),o.onmessage=a=>{if(a.data.type==="result"&&(s.currentBuffer=a.data.data,s.workerBusy=!1,s.pendingTimeSec!==null)){const l=s.pendingTimeSec;s.pendingTimeSec=null,s.requestSample(l)}},s}sample(t){return this.requestSample(t),this.currentBuffer}requestSample(t){if(!this.disposed){if(this.workerBusy){this.pendingTimeSec=t;return}this.workerBusy=!0,this.worker.postMessage({type:"sample",timeSec:t})}}dispose(){this.disposed=!0,this.worker.terminate()}}class gt{constructor(t,e,i){this.depthData=t,this.targetWidth=e,this.targetHeight=i;const o=t.meta.width*t.meta.height,n=e*i;this.interpolatedDepth=new Float32Array(o),this.bilateralOutput=new Float32Array(o),this.resizedDepth=new Float32Array(n),this.uint8Output=new Uint8Array(n)}interpolatedDepth;resizedDepth;bilateralOutput;uint8Output;lastFrameIndex=-1;lastNextFrameIndex=-1;lastLerpFactor=-1;sample(t){const e=j(t*this.depthData.meta.fps,0,this.depthData.meta.frameCount-1),i=Math.floor(e),o=Math.min(i+1,this.depthData.meta.frameCount-1),n=e-i,s=i!==this.lastFrameIndex||o!==this.lastNextFrameIndex,h=Math.abs(n-this.lastLerpFactor)>.001;if(!s&&!h)return this.uint8Output;this.lastFrameIndex=i,this.lastNextFrameIndex=o,this.lastLerpFactor=n;const a=1-n,l=this.depthData.frames[i],u=this.depthData.frames[o];for(let g=0;g<this.interpolatedDepth.length;g+=1)this.interpolatedDepth[g]=(l[g]*a+u[g]*n)/255;kt(this.interpolatedDepth,this.depthData.meta.width,this.depthData.meta.height,this.bilateralOutput);const f=this.targetWidth!==this.depthData.meta.width||this.targetHeight!==this.depthData.meta.height;f&&Ot(this.bilateralOutput,this.depthData.meta.width,this.depthData.meta.height,this.targetWidth,this.targetHeight,this.resizedDepth);const c=f?this.resizedDepth:this.bilateralOutput;for(let g=0;g<this.uint8Output.length;g+=1)this.uint8Output[g]=c[g]*255+.5|0;return this.uint8Output}}async function vt(r,t,e){const[i,o]=await Promise.all([Mt(t),_t(r)]);return It(o,i)}async function Mt(r){const t=await fetch(r);if(!t.ok)throw new Error(`Failed to fetch depth metadata (${t.status} ${t.statusText}).`);const e=await t.json();return Vt(e),{frameCount:e.frameCount,fps:e.fps,width:e.width,height:e.height,sourceFps:e.sourceFps}}async function _t(r,t){const e=await fetch(r);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 o=[];let n=0;const s=i.getReader();for(;;){const{done:l,value:u}=await s.read();if(l)break;u&&(o.push(u),n+=u.byteLength)}const h=new Uint8Array(n);let a=0;for(const l of o)h.set(l,a),a+=l.byteLength;return h}function It(r,t){if(r.byteLength<4)throw new Error("Depth data binary is missing the frame-count header.");const i=new DataView(r.buffer,r.byteOffset,r.byteLength).getUint32(0,!0),o=t.width*t.height,n=4+i*o;if(r.byteLength!==n)throw new Error(`Depth data byte length mismatch. Expected ${n} bytes, received ${r.byteLength}.`);if(i!==t.frameCount)throw new Error(`Depth frame count mismatch between metadata (${t.frameCount}) and binary header (${i}).`);const s=r.subarray(4),h=new Array(i);for(let a=0;a<i;a+=1){const l=a*o;h[a]=s.subarray(l,l+o)}return{meta:t,frames:h}}function Vt(r){if(!r||typeof r.frameCount!="number"||typeof r.fps!="number"||typeof r.width!="number"||typeof r.height!="number"||typeof r.sourceFps!="number")throw new Error("Depth metadata is malformed.");if(!Number.isFinite(r.frameCount)||!Number.isFinite(r.fps)||!Number.isFinite(r.width)||!Number.isFinite(r.height)||!Number.isFinite(r.sourceFps)||r.frameCount<=0||r.fps<=0||r.width<=0||r.height<=0||r.sourceFps<=0)throw new Error("Depth metadata contains invalid numeric values.")}function Ot(r,t,e,i,o,n){const s=t/i,h=e/o;for(let a=0;a<o;a+=1){const l=(a+.5)*h-.5,u=j(Math.floor(l),0,e-1),f=j(u+1,0,e-1),c=l-u;for(let g=0;g<i;g+=1){const d=(g+.5)*s-.5,m=j(Math.floor(d),0,t-1),U=j(m+1,0,t-1),y=d-m,E=r[u*t+m],p=r[u*t+U],v=r[f*t+m],T=r[f*t+U],x=E+(p-E)*y,A=v+(T-v)*y;n[a*i+g]=x+(A-x)*c}}}function kt(r,t,e,i){for(let s=0;s<e;s+=1)for(let h=0;h<t;h+=1){const a=s*t+h,l=r[a];let u=1,f=l;for(let c=-2;c<=2;c+=1){const g=s+c;if(!(g<0||g>=e))for(let d=-2;d<=2;d+=1){if(d===0&&c===0)continue;const m=h+d;if(m<0||m>=t)continue;const U=r[g*t+m],y=d*d+c*c,E=U-l,p=Math.exp(-y/2.25-E*E/.01);u+=p,f+=U*p}}i[a]=f/u}}function j(r,t,e){return Math.min(e,Math.max(t,r))}const Bt={parallaxStrength:.05,contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4,pomSteps:16,overscanPadding:.08};function Ht(r,t,e){const i=new Float32Array(256);if(r.length===0||t<=0||e<=0)return xt(i);const o=Nt(r.length),n=t*e;let s=0;const h=new Uint32Array(256);for(const T of o){const x=r[T],A=Math.min(x.length,n);for(let S=0;S<A;S+=1)h[x[S]]+=1;s+=A}if(s===0)return xt(i);const a=1/s;for(let T=0;T<256;T+=1)i[T]=h[T]*a;const l=new Float32Array(256);l[0]=i[0];for(let T=1;T<256;T+=1)l[T]=l[T-1]+i[T];const u=Y(l,.05),f=Y(l,.25),c=Y(l,.5),g=Y(l,.75),d=Y(l,.95);let m=0;for(let T=0;T<256;T+=1)m+=T/255*i[T];let U=0;for(let T=0;T<256;T+=1){const x=T/255-m;U+=i[T]*x*x}const y=Math.sqrt(U),E=d-u,p=g-f,v=zt(i);return{mean:m,stdDev:y,p5:u,p25:f,median:c,p75:g,p95:d,effectiveRange:E,iqr:p,bimodality:v,histogram:i}}function Xt(r){if(r.effectiveRange<.05||r.stdDev<.02)return{...Bt};const t=r.effectiveRange-.5,e=r.bimodality-.4,i=V(.05-t*.03+e*.01,.035,.065),o=V(r.p5-.03,0,.25),n=V(r.p95+.03,.75,1),s=V((i-.03)/.05,0,1),h=V(.6-s*.25,.35,.6),a=V(.6-t*.2,.5,.7),l=V(.4+t*.2,.25,.5),u=16,f=V(i+.03,.06,.1);return{parallaxStrength:i,contrastLow:o,contrastHigh:n,verticalReduction:h,dofStart:a,dofStrength:l,pomSteps:u,overscanPadding:f}}function Nt(r){if(r<=0)return[];if(r===1)return[0];const t=r-1,e=[0,Math.floor(r/4),Math.floor(r/2),Math.floor(3*r/4),t],i=new Set,o=[];for(const n of e)i.has(n)||(i.add(n),o.push(n));return o}function Y(r,t){for(let e=0;e<256;e+=1)if(r[e]>=t)return e/255;return 1}function zt(r){const t=new Float32Array(256);for(let c=0;c<256;c+=1){let g=0,d=0;for(let m=c-2;m<=c+2;m+=1)m>=0&&m<256&&(g+=r[m],d+=1);t[c]=g/d}let e=0;for(let c=0;c<256;c+=1)e+=t[c];e/=256;const i=e*2,o=25,n=[];for(let c=1;c<255;c+=1)t[c]>t[c-1]&&t[c]>t[c+1]&&t[c]>=i&&n.push({bin:c,height:t[c]});if(t[0]>t[1]&&t[0]>=i&&n.push({bin:0,height:t[0]}),t[255]>t[254]&&t[255]>=i&&n.push({bin:255,height:t[255]}),n.sort((c,g)=>g.height-c.height),n.length<2)return 0;const s=n[0];let h=null;for(let c=1;c<n.length;c+=1)if(Math.abs(n[c].bin-s.bin)>=o){h=n[c];break}if(!h)return 0;const a=Math.min(s.bin,h.bin),l=Math.max(s.bin,h.bin);let u=1/0;for(let c=a;c<=l;c+=1)t[c]<u&&(u=t[c]);const f=Math.min(s.height,h.height);return f<=0?0:V(1-u/f,0,1)}function xt(r){return{mean:0,stdDev:0,p5:0,p25:0,median:0,p75:0,p95:0,effectiveRange:0,iqr:0,bimodality:0,histogram:r}}function V(r,t,e){return Math.min(e,Math.max(t,r))}const Wt=`#version 300 es
|
|
2
2
|
in vec2 aPosition;
|
|
3
3
|
|
|
4
4
|
// UV coordinates for cover-fit + overscan.
|
|
@@ -19,7 +19,7 @@ var Layershift=(function(et){"use strict";var ut=typeof document<"u"?document.cu
|
|
|
19
19
|
vScreenUv = baseUv;
|
|
20
20
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
21
21
|
}
|
|
22
|
-
`,
|
|
22
|
+
`,Gt=`#version 300 es
|
|
23
23
|
precision highp float;
|
|
24
24
|
|
|
25
25
|
// ---- Uniforms ----
|
|
@@ -187,10 +187,10 @@ var Layershift=(function(et){"use strict";var ut=typeof document<"u"?document.cu
|
|
|
187
187
|
|
|
188
188
|
fragColor = color;
|
|
189
189
|
}
|
|
190
|
-
`,q={contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4};function Tt(
|
|
191
|
-
${
|
|
192
|
-
${
|
|
193
|
-
#define MAX_POM_STEPS ${Z.MAX_POM_STEPS}`),i=Tt(t,t.VERTEX_SHADER,zt),r=Tt(t,t.FRAGMENT_SHADER,e);this.program=Gt(t,i,r),this.uniforms=jt(t,this.program);const o=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.vao=t.createVertexArray(),t.bindVertexArray(this.vao);const s=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,s),t.bufferData(t.ARRAY_BUFFER,o,t.STATIC_DRAW);const a=t.getAttribLocation(this.program,"aPosition");t.enableVertexAttribArray(a),t.vertexAttribPointer(a,2,t.FLOAT,!1,0,0),t.bindVertexArray(null),t.disable(t.DEPTH_TEST)}static isRVFCSupported(){return"requestVideoFrameCallback"in HTMLVideoElement.prototype}videoFrameLoop=(t,e)=>{const i=this.playbackVideo;if(!i)return;this.rvfcHandle=i.requestVideoFrameCallback(this.videoFrameLoop);const r=e.mediaTime??i.currentTime;this.updateDepthTexture(r),this.onVideoFrame&&this.onVideoFrame(r,e.presentedFrames??0)};renderLoop=()=>{this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop);const t=this.gl,e=this.playbackVideo;if(!(!t||!this.program||!this.uniforms||!this.vao)&&!(!e||e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)){if(t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),this.rvfcSupported||this.updateDepthTexture(e.currentTime),this.readInput){const i=this.readInput();t.uniform2f(this.uniforms.uOffset,-i.x,i.y)}t.bindVertexArray(this.vao),t.drawArrays(t.TRIANGLE_STRIP,0,4)}};updateDepthTexture(t){const e=this.gl;if(!e||!this.readDepth||!this.depthTexture)return;const i=this.readDepth(t);e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.depthTexture),e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.depthWidth,this.depthHeight,e.RED,e.UNSIGNED_BYTE,i)}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()},Z.RESIZE_DEBOUNCE_MS)};recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:i}=this.getViewportSize(),r=Math.min(window.devicePixelRatio,2),o=Math.round(e*r),s=Math.round(i*r);(this.canvas.width!==o||this.canvas.height!==s)&&(this.canvas.width=o,this.canvas.height=s,t.viewport(0,0,o,s));const a=e/i,h=this.config.parallaxStrength+this.config.overscanPadding;let l=1,u=1;a>this.videoAspect?u=this.videoAspect/a:l=a/this.videoAspect;const f=1+h*2;l/=f,u/=f,this.uvOffset=[(1-l)/2,(1-u)/2],this.uvScale=[l,u],this.program&&this.uniforms&&(t.useProgram(this.program),t.uniform2f(this.uniforms.uUvOffset,this.uvOffset[0],this.uvOffset[1]),t.uniform2f(this.uniforms.uUvScale,this.uvScale[0],this.uvScale[1]))}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}}handleContextLost=t=>{t.preventDefault(),this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0)};handleContextRestored=()=>{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.playbackVideo&&this.depthWidth>0&&this.initialize(this.playbackVideo,this.depthWidth,this.depthHeight),this.playbackVideo&&(this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)))};disposeTextures(){const t=this.gl;t&&(this.videoTexture&&(t.deleteTexture(this.videoTexture),this.videoTexture=null),this.depthTexture&&(t.deleteTexture(this.depthTexture),this.depthTexture=null))}disposeGPUResources(){const t=this.gl;t&&(this.program&&(t.deleteProgram(this.program),this.program=null),this.vao&&(t.deleteVertexArray(this.vao),this.vao=null),this.uniforms=null)}}const B={parallaxX:.4,parallaxY:1,parallaxMax:30,overscan:.05,autoplay:!0,loop:!0,muted:!0};let Yt=class Lt{constructor(t,e=.08,i=.06){this.host=t,this.lerpFactor=e,this.motionLerpFactor=i,this.host.addEventListener("mousemove",this.handleMouseMove),this.host.addEventListener("mouseleave",this.resetPointerTarget),this.host.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),this.host.addEventListener("touchmove",this.handleTouchMove,{passive:!0}),this.host.addEventListener("touchend",this.handleTouchEnd,{passive:!0}),this.host.addEventListener("touchcancel",this.handleTouchEnd,{passive:!0})}pointerTarget={x:0,y:0};motionTarget={x:0,y:0};smoothedOutput={x:0,y:0};usingMotionInput=!1;motionListenerAttached=!1;motionRequested=!1;touchActive=!1;touchAnchorX=0;touchAnchorY=0;lerpFactor;motionLerpFactor;static TOUCH_DRAG_RANGE=100;update(){const t=this.touchActive?this.pointerTarget:this.usingMotionInput?this.motionTarget:this.pointerTarget,e=this.usingMotionInput&&!this.touchActive?this.motionLerpFactor:this.lerpFactor;return this.smoothedOutput.x=ot(this.smoothedOutput.x,t.x,e),this.smoothedOutput.y=ot(this.smoothedOutput.y,t.y,e),this.smoothedOutput}dispose(){this.host.removeEventListener("mousemove",this.handleMouseMove),this.host.removeEventListener("mouseleave",this.resetPointerTarget),this.host.removeEventListener("touchstart",this.handleTouchStart),this.host.removeEventListener("touchmove",this.handleTouchMove),this.host.removeEventListener("touchend",this.handleTouchEnd),this.host.removeEventListener("touchcancel",this.handleTouchEnd),this.motionListenerAttached&&(window.removeEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!1)}handleMouseMove=t=>{const e=this.host.getBoundingClientRect(),i=(t.clientX-e.left)/e.width*2-1,r=(t.clientY-e.top)/e.height*2-1;this.pointerTarget.x=N(i,-1,1),this.pointerTarget.y=N(r,-1,1)};resetPointerTarget=()=>{this.pointerTarget.x=0,this.pointerTarget.y=0};handleTouchStart=t=>{const e=t.touches[0];e&&(this.touchActive=!0,this.touchAnchorX=e.clientX,this.touchAnchorY=e.clientY,this.pointerTarget.x=0,this.pointerTarget.y=0,this.motionRequested||(this.motionRequested=!0,this.requestMotionPermission()))};handleTouchMove=t=>{const e=t.touches[0];if(!e)return;const i=e.clientX-this.touchAnchorX,r=e.clientY-this.touchAnchorY,o=Lt.TOUCH_DRAG_RANGE;this.pointerTarget.x=N(i/o,-1,1),this.pointerTarget.y=N(r/o,-1,1)};handleTouchEnd=()=>{this.touchActive=!1,this.pointerTarget.x=0,this.pointerTarget.y=0};async requestMotionPermission(){if(typeof DeviceOrientationEvent>"u")return;const t=DeviceOrientationEvent;if(typeof t.requestPermission=="function")try{if(await t.requestPermission()!=="granted")return}catch{return}this.motionListenerAttached||(window.addEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!0),this.usingMotionInput=!0}handleDeviceOrientation=t=>{const e=N((t.gamma??0)/45,-1,1),i=N((t.beta??0)/45,-1,1);this.motionTarget.x=ot(this.motionTarget.x,e,this.motionLerpFactor),this.motionTarget.y=ot(this.motionTarget.y,i,this.motionLerpFactor)}};class rt extends HTMLElement{static TAG_NAME="layershift-parallax";static get observedAttributes(){return["src","depth-src","depth-meta","parallax-x","parallax-y","parallax-max","layers","overscan","autoplay","loop","muted"]}shadow;container=null;renderer=null;inputHandler=null;depthWorker=null;video=null;initialized=!1;abortController=null;loopCount=0;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}getAttrFloat(t,e){const i=this.getAttribute(t);if(i===null)return e;const r=parseFloat(i);return Number.isFinite(r)?r: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",B.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",B.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",B.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",B.overscan)}get shouldAutoplay(){return this.getAttrBool("autoplay",B.autoplay)}get shouldLoop(){return this.getAttrBool("loop",B.loop)}get shouldMute(){return this.getAttrBool("muted",B.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachVideoEventListeners(t){t.addEventListener("play",()=>{this.emit("layershift-parallax:play",{currentTime:t.currentTime})}),t.addEventListener("pause",()=>{this.emit("layershift-parallax:pause",{currentTime:t.currentTime})}),t.addEventListener("ended",()=>{t.loop&&(this.loopCount+=1,this.emit("layershift-parallax:loop",{loopCount:this.loopCount}))})}connectedCallback(){this.setupShadowDOM(),this.init()}disconnectedCallback(){this.dispose()}attributeChangedCallback(t,e,i){["src","depth-src","depth-meta"].includes(t)&&(this.initialized?(this.dispose(),this.setupShadowDOM(),this.init()):this.isConnected&&this.getAttribute("src")&&this.getAttribute("depth-src")&&this.getAttribute("depth-meta")&&this.init())}setupShadowDOM(){this.shadow.innerHTML="";const t=document.createElement("style");t.textContent=`
|
|
190
|
+
`,q={contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4};function Tt(r,t,e){const i=r.createShader(t);if(!i)throw new Error("Failed to create shader.");if(r.shaderSource(i,e),r.compileShader(i),!r.getShaderParameter(i,r.COMPILE_STATUS)){const o=r.getShaderInfoLog(i)??"";throw r.deleteShader(i),new Error(`Shader compilation failed:
|
|
191
|
+
${o}`)}return i}function jt(r,t,e){const i=r.createProgram();if(!i)throw new Error("Failed to create program.");if(r.attachShader(i,t),r.attachShader(i,e),r.linkProgram(i),!r.getProgramParameter(i,r.LINK_STATUS)){const o=r.getProgramInfoLog(i)??"";throw r.deleteProgram(i),new Error(`Program linking failed:
|
|
192
|
+
${o}`)}return r.detachShader(i,t),r.detachShader(i,e),r.deleteShader(t),r.deleteShader(e),i}function Yt(r,t){return{uImage:r.getUniformLocation(t,"uImage"),uDepth:r.getUniformLocation(t,"uDepth"),uOffset:r.getUniformLocation(t,"uOffset"),uStrength:r.getUniformLocation(t,"uStrength"),uPomEnabled:r.getUniformLocation(t,"uPomEnabled"),uPomSteps:r.getUniformLocation(t,"uPomSteps"),uContrastLow:r.getUniformLocation(t,"uContrastLow"),uContrastHigh:r.getUniformLocation(t,"uContrastHigh"),uVerticalReduction:r.getUniformLocation(t,"uVerticalReduction"),uDofStart:r.getUniformLocation(t,"uDofStart"),uDofStrength:r.getUniformLocation(t,"uDofStrength"),uImageTexelSize:r.getUniformLocation(t,"uImageTexelSize"),uUvOffset:r.getUniformLocation(t,"uUvOffset"),uUvScale:r.getUniformLocation(t,"uUvScale")}}class Z{static RESIZE_DEBOUNCE_MS=100;static MAX_POM_STEPS=64;canvas;gl=null;program=null;uniforms=null;vao=null;videoTexture=null;depthTexture=null;container;depthWidth=0;depthHeight=0;videoAspect=1.7777777777777777;readDepth=null;readInput=null;playbackVideo=null;onVideoFrame=null;animationFrameHandle=0;rvfcHandle=0;rvfcSupported=!1;resizeObserver=null;resizeTimer=null;uvOffset=[0,0];uvScale=[1,1];config;constructor(t,e){this.container=t,this.config={parallaxStrength:e.parallaxStrength,pomEnabled:e.pomEnabled,pomSteps:e.pomSteps,overscanPadding:e.overscanPadding,contrastLow:e.contrastLow??q.contrastLow,contrastHigh:e.contrastHigh??q.contrastHigh,verticalReduction:e.verticalReduction??q.verticalReduction,dofStart:e.dofStart??q.dofStart,dofStrength:e.dofStrength??q.dofStrength},this.canvas=document.createElement("canvas");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,"drawingBufferColorSpace"in i&&(i.drawingBufferColorSpace="srgb"),i.clearColor(0,0,0,1),i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!0),this.container.appendChild(this.canvas),this.initGPUResources(),this.setupResizeHandling(),this.canvas.addEventListener("webglcontextlost",this.handleContextLost),this.canvas.addEventListener("webglcontextrestored",this.handleContextRestored)}initialize(t,e,i){const o=this.gl;o&&(this.disposeTextures(),this.videoAspect=t.videoWidth/t.videoHeight,this.depthWidth=e,this.depthHeight=i,this.videoTexture=o.createTexture(),o.activeTexture(o.TEXTURE0),o.bindTexture(o.TEXTURE_2D,this.videoTexture),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MIN_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MAG_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_S,o.CLAMP_TO_EDGE),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_T,o.CLAMP_TO_EDGE),this.depthTexture=o.createTexture(),o.activeTexture(o.TEXTURE1),o.bindTexture(o.TEXTURE_2D,this.depthTexture),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MIN_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MAG_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_S,o.CLAMP_TO_EDGE),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_T,o.CLAMP_TO_EDGE),o.texStorage2D(o.TEXTURE_2D,1,o.R8,e,i),this.program&&this.uniforms&&(o.useProgram(this.program),o.uniform1i(this.uniforms.uImage,0),o.uniform1i(this.uniforms.uDepth,1),o.uniform1f(this.uniforms.uStrength,this.config.parallaxStrength),o.uniform1i(this.uniforms.uPomEnabled,this.config.pomEnabled?1:0),o.uniform1i(this.uniforms.uPomSteps,this.config.pomSteps),o.uniform1f(this.uniforms.uContrastLow,this.config.contrastLow),o.uniform1f(this.uniforms.uContrastHigh,this.config.contrastHigh),o.uniform1f(this.uniforms.uVerticalReduction,this.config.verticalReduction),o.uniform1f(this.uniforms.uDofStart,this.config.dofStart),o.uniform1f(this.uniforms.uDofStrength,this.config.dofStrength),o.uniform2f(this.uniforms.uImageTexelSize,1/t.videoWidth,1/t.videoHeight)),this.recalculateViewportLayout())}start(t,e,i,o){this.stop(),this.playbackVideo=t,this.readDepth=e,this.readInput=i,this.onVideoFrame=o??null,this.rvfcSupported=Z.isRVFCSupported(),this.rvfcSupported&&(this.rvfcHandle=t.requestVideoFrameCallback(this.videoFrameLoop)),this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)}stop(){this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0),this.rvfcHandle&&this.playbackVideo&&(this.playbackVideo.cancelVideoFrameCallback(this.rvfcHandle),this.rvfcHandle=0),this.playbackVideo=null,this.readDepth=null,this.readInput=null,this.onVideoFrame=null,this.rvfcSupported=!1}dispose(){this.stop(),this.disposeTextures(),this.disposeGPUResources(),this.canvas.removeEventListener("webglcontextlost",this.handleContextLost),this.canvas.removeEventListener("webglcontextrestored",this.handleContextRestored),this.gl&&(this.gl.getExtension("WEBGL_lose_context")?.loseContext(),this.gl=null),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)}initGPUResources(){const t=this.gl;if(!t)return;const e=Gt.replace("#version 300 es",`#version 300 es
|
|
193
|
+
#define MAX_POM_STEPS ${Z.MAX_POM_STEPS}`),i=Tt(t,t.VERTEX_SHADER,Wt),o=Tt(t,t.FRAGMENT_SHADER,e);this.program=jt(t,i,o),this.uniforms=Yt(t,this.program);const n=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.vao=t.createVertexArray(),t.bindVertexArray(this.vao);const s=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,s),t.bufferData(t.ARRAY_BUFFER,n,t.STATIC_DRAW);const h=t.getAttribLocation(this.program,"aPosition");t.enableVertexAttribArray(h),t.vertexAttribPointer(h,2,t.FLOAT,!1,0,0),t.bindVertexArray(null),t.disable(t.DEPTH_TEST)}static isRVFCSupported(){return"requestVideoFrameCallback"in HTMLVideoElement.prototype}videoFrameLoop=(t,e)=>{const i=this.playbackVideo;if(!i)return;this.rvfcHandle=i.requestVideoFrameCallback(this.videoFrameLoop);const o=e.mediaTime??i.currentTime;this.updateDepthTexture(o),this.onVideoFrame&&this.onVideoFrame(o,e.presentedFrames??0)};renderLoop=()=>{this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop);const t=this.gl,e=this.playbackVideo;if(!(!t||!this.program||!this.uniforms||!this.vao)&&!(!e||e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA)){if(t.useProgram(this.program),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),this.rvfcSupported||this.updateDepthTexture(e.currentTime),this.readInput){const i=this.readInput();t.uniform2f(this.uniforms.uOffset,-i.x,i.y)}t.bindVertexArray(this.vao),t.drawArrays(t.TRIANGLE_STRIP,0,4)}};updateDepthTexture(t){const e=this.gl;if(!e||!this.readDepth||!this.depthTexture)return;const i=this.readDepth(t);e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.depthTexture),e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.depthWidth,this.depthHeight,e.RED,e.UNSIGNED_BYTE,i)}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()},Z.RESIZE_DEBOUNCE_MS)};recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:i}=this.getViewportSize(),o=Math.min(window.devicePixelRatio,2),n=Math.round(e*o),s=Math.round(i*o);(this.canvas.width!==n||this.canvas.height!==s)&&(this.canvas.width=n,this.canvas.height=s,t.viewport(0,0,n,s));const h=e/i,a=this.config.parallaxStrength+this.config.overscanPadding;let l=1,u=1;h>this.videoAspect?u=this.videoAspect/h:l=h/this.videoAspect;const f=1+a*2;l/=f,u/=f,this.uvOffset=[(1-l)/2,(1-u)/2],this.uvScale=[l,u],this.program&&this.uniforms&&(t.useProgram(this.program),t.uniform2f(this.uniforms.uUvOffset,this.uvOffset[0],this.uvOffset[1]),t.uniform2f(this.uniforms.uUvScale,this.uvScale[0],this.uvScale[1]))}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}}handleContextLost=t=>{t.preventDefault(),this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0)};handleContextRestored=()=>{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.playbackVideo&&this.depthWidth>0&&this.initialize(this.playbackVideo,this.depthWidth,this.depthHeight),this.playbackVideo&&(this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)))};disposeTextures(){const t=this.gl;t&&(this.videoTexture&&(t.deleteTexture(this.videoTexture),this.videoTexture=null),this.depthTexture&&(t.deleteTexture(this.depthTexture),this.depthTexture=null))}disposeGPUResources(){const t=this.gl;t&&(this.program&&(t.deleteProgram(this.program),this.program=null),this.vao&&(t.deleteVertexArray(this.vao),this.vao=null),this.uniforms=null)}}class Et{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;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 H={parallaxX:.4,parallaxY:1,parallaxMax:30,overscan:.05,autoplay:!0,loop:!0,muted:!0};let qt=class Ct{constructor(t,e=.08,i=.06){this.host=t,this.lerpFactor=e,this.motionLerpFactor=i,this.host.addEventListener("mousemove",this.handleMouseMove),this.host.addEventListener("mouseleave",this.resetPointerTarget),this.host.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),this.host.addEventListener("touchmove",this.handleTouchMove,{passive:!0}),this.host.addEventListener("touchend",this.handleTouchEnd,{passive:!0}),this.host.addEventListener("touchcancel",this.handleTouchEnd,{passive:!0})}pointerTarget={x:0,y:0};motionTarget={x:0,y:0};smoothedOutput={x:0,y:0};usingMotionInput=!1;motionListenerAttached=!1;motionRequested=!1;touchActive=!1;touchAnchorX=0;touchAnchorY=0;lerpFactor;motionLerpFactor;static TOUCH_DRAG_RANGE=100;update(){const t=this.touchActive?this.pointerTarget:this.usingMotionInput?this.motionTarget:this.pointerTarget,e=this.usingMotionInput&&!this.touchActive?this.motionLerpFactor:this.lerpFactor;return this.smoothedOutput.x=ot(this.smoothedOutput.x,t.x,e),this.smoothedOutput.y=ot(this.smoothedOutput.y,t.y,e),this.smoothedOutput}dispose(){this.host.removeEventListener("mousemove",this.handleMouseMove),this.host.removeEventListener("mouseleave",this.resetPointerTarget),this.host.removeEventListener("touchstart",this.handleTouchStart),this.host.removeEventListener("touchmove",this.handleTouchMove),this.host.removeEventListener("touchend",this.handleTouchEnd),this.host.removeEventListener("touchcancel",this.handleTouchEnd),this.motionListenerAttached&&(window.removeEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!1)}handleMouseMove=t=>{const e=this.host.getBoundingClientRect(),i=(t.clientX-e.left)/e.width*2-1,o=(t.clientY-e.top)/e.height*2-1;this.pointerTarget.x=N(i,-1,1),this.pointerTarget.y=N(o,-1,1)};resetPointerTarget=()=>{this.pointerTarget.x=0,this.pointerTarget.y=0};handleTouchStart=t=>{const e=t.touches[0];e&&(this.touchActive=!0,this.touchAnchorX=e.clientX,this.touchAnchorY=e.clientY,this.pointerTarget.x=0,this.pointerTarget.y=0,this.motionRequested||(this.motionRequested=!0,this.requestMotionPermission()))};handleTouchMove=t=>{const e=t.touches[0];if(!e)return;const i=e.clientX-this.touchAnchorX,o=e.clientY-this.touchAnchorY,n=Ct.TOUCH_DRAG_RANGE;this.pointerTarget.x=N(i/n,-1,1),this.pointerTarget.y=N(o/n,-1,1)};handleTouchEnd=()=>{this.touchActive=!1,this.pointerTarget.x=0,this.pointerTarget.y=0};async requestMotionPermission(){if(typeof DeviceOrientationEvent>"u")return;const t=DeviceOrientationEvent;if(typeof t.requestPermission=="function")try{if(await t.requestPermission()!=="granted")return}catch{return}this.motionListenerAttached||(window.addEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!0),this.usingMotionInput=!0}handleDeviceOrientation=t=>{const e=N((t.gamma??0)/45,-1,1),i=N((t.beta??0)/45,-1,1);this.motionTarget.x=ot(this.motionTarget.x,e,this.motionLerpFactor),this.motionTarget.y=ot(this.motionTarget.y,i,this.motionLerpFactor)}};class rt extends HTMLElement{static TAG_NAME="layershift-parallax";static get observedAttributes(){return["src","depth-src","depth-meta","parallax-x","parallax-y","parallax-max","layers","overscan","autoplay","loop","muted"]}reinitAttributes=["src","depth-src","depth-meta"];shadow;container=null;renderer=null;inputHandler=null;depthWorker=null;video=null;loopCount=0;lifecycle;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.lifecycle=new Et(this)}getAttrFloat(t,e){const i=this.getAttribute(t);if(i===null)return e;const o=parseFloat(i);return Number.isFinite(o)?o: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",H.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",H.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",H.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",H.overscan)}get shouldAutoplay(){return this.getAttrBool("autoplay",H.autoplay)}get shouldLoop(){return this.getAttrBool("loop",H.loop)}get shouldMute(){return this.getAttrBool("muted",H.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachVideoEventListeners(t){t.addEventListener("play",()=>{this.emit("layershift-parallax:play",{currentTime:t.currentTime})}),t.addEventListener("pause",()=>{this.emit("layershift-parallax:pause",{currentTime:t.currentTime})}),t.addEventListener("ended",()=>{t.loop&&(this.loopCount+=1,this.emit("layershift-parallax: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=`
|
|
194
194
|
:host {
|
|
195
195
|
display: block;
|
|
196
196
|
width: 100%;
|
|
@@ -210,34 +210,34 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
210
210
|
width: 100%;
|
|
211
211
|
height: 100%;
|
|
212
212
|
}
|
|
213
|
-
`,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async
|
|
213
|
+
`,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("src"),i=this.getAttribute("depth-src"),o=this.getAttribute("depth-meta");if(this.container)try{const[n,s]=await Promise.all([this.createVideoElement(e),vt(i,o)]);if(t.aborted){n.remove();return}this.video=n,this.loopCount=0,this.attachVideoEventListeners(n);const h=Ht(s.frames,s.meta.width,s.meta.height),a=Xt(h),l=this.hasAttribute("parallax-max")?this.parallaxMax/Math.max(n.videoWidth,1):a.parallaxStrength,u=this.hasAttribute("overscan")?this.overscan:a.overscanPadding;let f;try{const d=await it.create(s,s.meta.width,s.meta.height);this.depthWorker=d,f=m=>d.sample(m)}catch{const d=new gt(s,s.meta.width,s.meta.height);f=m=>d.sample(m)}if(t.aborted){n.remove(),this.depthWorker?.dispose(),this.depthWorker=null;return}this.renderer=new Z(this.container,{parallaxStrength:l,pomEnabled:!0,pomSteps:a.pomSteps,overscanPadding:u,contrastLow:a.contrastLow,contrastHigh:a.contrastHigh,verticalReduction:a.verticalReduction,dofStart:a.dofStart,dofStrength:a.dofStrength}),this.renderer.initialize(n,s.meta.width,s.meta.height),this.inputHandler=new qt(this);const c=this.parallaxX,g=this.parallaxY;if(this.renderer.start(n,f,()=>{if(!this.inputHandler)return{x:0,y:0};const d=this.inputHandler.update();return{x:d.x*c,y:d.y*g}},(d,m)=>{this.emit("layershift-parallax:frame",{currentTime:d,frameNumber:m})}),this.shouldAutoplay){n.currentTime=0;try{await n.play()}catch{}}if(t.aborted)return;this.lifecycle.markInitialized(),this.emit("layershift-parallax:ready",{videoWidth:n.videoWidth,videoHeight:n.videoHeight,duration:n.duration,depthProfile:h,derivedParams:a})}catch(n){const s=n instanceof Error?n.message:"Failed to initialize.";console.error("<layershift-parallax>: Failed to initialize.",n),this.emit("layershift-parallax:error",{message:s})}}async createVideoElement(t){const e=document.createElement("video");return e.crossOrigin="anonymous",e.setAttribute("crossorigin","anonymous"),e.playsInline=!0,e.setAttribute("playsinline",""),e.setAttribute("webkit-playsinline","true"),e.muted=this.shouldMute,e.defaultMuted=this.shouldMute,this.shouldMute&&e.setAttribute("muted",""),e.loop=this.shouldLoop,e.preload="auto",e.style.display="none",e.src=t,this.shadow.appendChild(e),await new Promise((i,o)=>{if(e.readyState>=HTMLMediaElement.HAVE_METADATA){i();return}const n=()=>{h(),i()},s=()=>{h(),o(new Error("Failed to load video metadata."))},h=()=>{e.removeEventListener("loadedmetadata",n),e.removeEventListener("error",s)};e.addEventListener("loadedmetadata",n),e.addEventListener("error",s),e.load()}),e}doDispose(){this.renderer?.dispose(),this.renderer=null,this.inputHandler?.dispose(),this.inputHandler=null,this.depthWorker?.dispose(),this.depthWorker=null,this.video&&(this.video.pause(),this.video.removeAttribute("src"),this.video.load(),this.video.remove(),this.video=null),this.loopCount=0,this.container=null}}function N(r,t,e){return Math.min(e,Math.max(t,r))}function ot(r,t,e){return r+(t-r)*e}const Zt=`#version 300 es
|
|
214
214
|
in vec2 aPosition;
|
|
215
215
|
uniform vec2 uMeshScale;
|
|
216
216
|
void main() {
|
|
217
217
|
gl_Position = vec4(aPosition * uMeshScale, 0.0, 1.0);
|
|
218
218
|
}
|
|
219
|
-
|
|
219
|
+
`,$t=`#version 300 es
|
|
220
220
|
precision lowp float;
|
|
221
221
|
out vec4 fragColor;
|
|
222
222
|
void main() { fragColor = vec4(0.0); }
|
|
223
|
-
|
|
223
|
+
`,Jt=`#version 300 es
|
|
224
224
|
in vec2 aPosition;
|
|
225
225
|
uniform vec2 uMeshScale;
|
|
226
226
|
void main() {
|
|
227
227
|
gl_Position = vec4(aPosition * uMeshScale, 0.0, 1.0);
|
|
228
228
|
}
|
|
229
|
-
`,
|
|
229
|
+
`,Kt=`#version 300 es
|
|
230
230
|
precision lowp float;
|
|
231
231
|
out vec4 fragColor;
|
|
232
232
|
void main() { fragColor = vec4(1.0); }
|
|
233
|
-
`,
|
|
233
|
+
`,Qt=`#version 300 es
|
|
234
234
|
in vec2 aPosition;
|
|
235
235
|
out vec2 vUv;
|
|
236
236
|
void main() {
|
|
237
237
|
vUv = aPosition * 0.5 + 0.5;
|
|
238
238
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
239
239
|
}
|
|
240
|
-
`,
|
|
240
|
+
`,te=`#version 300 es
|
|
241
241
|
precision highp float;
|
|
242
242
|
uniform sampler2D uMask;
|
|
243
243
|
uniform vec2 uTexelSize;
|
|
@@ -262,14 +262,14 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
262
262
|
fragSeed = vec2(-1.0);
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
|
-
`,
|
|
265
|
+
`,ee=`#version 300 es
|
|
266
266
|
in vec2 aPosition;
|
|
267
267
|
out vec2 vUv;
|
|
268
268
|
void main() {
|
|
269
269
|
vUv = aPosition * 0.5 + 0.5;
|
|
270
270
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
271
271
|
}
|
|
272
|
-
`,
|
|
272
|
+
`,ie=`#version 300 es
|
|
273
273
|
precision highp float;
|
|
274
274
|
uniform sampler2D uSeedTex;
|
|
275
275
|
uniform float uStepSize;
|
|
@@ -298,14 +298,14 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
298
298
|
|
|
299
299
|
fragSeed = bestSeed;
|
|
300
300
|
}
|
|
301
|
-
`,
|
|
301
|
+
`,re=`#version 300 es
|
|
302
302
|
in vec2 aPosition;
|
|
303
303
|
out vec2 vUv;
|
|
304
304
|
void main() {
|
|
305
305
|
vUv = aPosition * 0.5 + 0.5;
|
|
306
306
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
307
307
|
}
|
|
308
|
-
`,
|
|
308
|
+
`,oe=`#version 300 es
|
|
309
309
|
precision highp float;
|
|
310
310
|
uniform sampler2D uSeedTex;
|
|
311
311
|
uniform sampler2D uMask;
|
|
@@ -330,7 +330,7 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
330
330
|
float normalized = clamp(d / max(uBevelWidth, 0.001), 0.0, 1.0);
|
|
331
331
|
fragDist = vec4(normalized, 0.0, 0.0, 1.0);
|
|
332
332
|
}
|
|
333
|
-
`,
|
|
333
|
+
`,ne=`#version 300 es
|
|
334
334
|
in vec2 aPosition;
|
|
335
335
|
uniform vec2 uUvOffset;
|
|
336
336
|
uniform vec2 uUvScale;
|
|
@@ -342,7 +342,7 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
342
342
|
vScreenUv = baseUv;
|
|
343
343
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
344
344
|
}
|
|
345
|
-
`,
|
|
345
|
+
`,se=`#version 300 es
|
|
346
346
|
precision highp float;
|
|
347
347
|
|
|
348
348
|
#define MAX_POM_STEPS 32
|
|
@@ -473,14 +473,14 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
473
473
|
// Write lens-transformed depth to second attachment for boundary effects
|
|
474
474
|
fragDepth = vec4(lensD, 0.0, 0.0, 1.0);
|
|
475
475
|
}
|
|
476
|
-
`,
|
|
476
|
+
`,ae=`#version 300 es
|
|
477
477
|
in vec2 aPosition;
|
|
478
478
|
out vec2 vUv;
|
|
479
479
|
void main() {
|
|
480
480
|
vUv = aPosition * 0.5 + 0.5;
|
|
481
481
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
482
482
|
}
|
|
483
|
-
`,
|
|
483
|
+
`,he=`#version 300 es
|
|
484
484
|
precision highp float;
|
|
485
485
|
uniform sampler2D uInteriorColor;
|
|
486
486
|
uniform sampler2D uDistField;
|
|
@@ -510,7 +510,7 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
510
510
|
|
|
511
511
|
fragColor = vec4(toSRGB(linear), color.a);
|
|
512
512
|
}
|
|
513
|
-
`,
|
|
513
|
+
`,le=`#version 300 es
|
|
514
514
|
in vec2 aPosition;
|
|
515
515
|
in vec2 aNormal;
|
|
516
516
|
uniform float uRimWidth;
|
|
@@ -533,7 +533,7 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
533
533
|
|
|
534
534
|
gl_Position = vec4(pos, 0.0, 1.0);
|
|
535
535
|
}
|
|
536
|
-
`,
|
|
536
|
+
`,ce=`#version 300 es
|
|
537
537
|
precision highp float;
|
|
538
538
|
|
|
539
539
|
uniform sampler2D uInteriorColor;
|
|
@@ -635,7 +635,7 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
635
635
|
|
|
636
636
|
fragColor = vec4(color * alpha, alpha);
|
|
637
637
|
}
|
|
638
|
-
`,
|
|
638
|
+
`,ue=`#version 300 es
|
|
639
639
|
in vec2 aPosition;
|
|
640
640
|
in vec3 aNormal3;
|
|
641
641
|
in float aLerpT; // 0 = inner (at silhouette), 1 = outer edge
|
|
@@ -651,7 +651,7 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
651
651
|
vLerpT = aLerpT;
|
|
652
652
|
gl_Position = vec4(sp, 0.0, 1.0);
|
|
653
653
|
}
|
|
654
|
-
`,
|
|
654
|
+
`,fe=`#version 300 es
|
|
655
655
|
precision highp float;
|
|
656
656
|
uniform vec3 uLightDir3;
|
|
657
657
|
uniform vec3 uChamferColor;
|
|
@@ -718,9 +718,9 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
718
718
|
vec3 lit = base * (uChamferAmbient + (1.0 - uChamferAmbient) * diff) + vec3(spec);
|
|
719
719
|
fragColor = vec4(toSRGB(lit), 1.0);
|
|
720
720
|
}
|
|
721
|
-
`;function L(
|
|
722
|
-
${
|
|
723
|
-
${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.deleteShader(e),i}function fe(n){const t=[];let e=0;for(let i=0;i<n.length-2;i+=2){const r=n[i],o=n[i+1],s=n[i+2],a=n[i+3],h=s-r,l=a-o,u=Math.sqrt(h*h+l*l);if(u<1e-6)continue;const f=-l/u,c=h/u;t.push(r,o,f,c,r,o,-f,-c,s,a,f,c,s,a,f,c,r,o,-f,-c,s,a,-f,-c),e+=6}return{vertices:new Float32Array(t),count:e}}function de(n,t,e,i,r){if(i<=0)return{vertices:new Float32Array(0),count:0};const o=r*Math.PI/180,s=-Math.cos(o),a=Math.sin(o),h=[];let l=0;for(let u=0;u<t.length;u++){const f=t[u],m=((u+1<t.length?t[u+1]:n.length)-f)/2;if(m<3)continue;const g=m-1;let U=0;for(let x=0;x<g;x++){const A=f+x*2,S=n[A],F=n[A+1],P=n[A+2],_=n[A+3];U+=S*_-P*F}const y=U>=0?1:-1,E=[],p=[];for(let x=0;x<g;x++){const A=f+x*2,S=n[A+2]-n[A],F=n[A+3]-n[A+1],P=Math.sqrt(S*S+F*F);P<1e-8?(E.push(x>0?E[x-1]:0),p.push(x>0?p[x-1]:0)):(E.push(-F/P*y),p.push(S/P*y))}const v=[],T=[];for(let x=0;x<g;x++){const A=(x-1+g)%g;let S=E[A]+E[x],F=p[A]+p[x];const P=Math.sqrt(S*S+F*F);P>1e-8?(S/=P,F/=P):(S=E[x],F=p[x]),v.push(S),T.push(F)}for(let x=0;x<g;x++){const A=x,S=(x+1)%g,F=f+x*2,P=f+(x+1)%g*2,_=n[F],k=n[F+1],D=n[P],R=n[P+1],C=v[A]*a,M=T[A]*a,H=s,I=v[S]*a,G=T[S]*a,tt=s,ct=_+v[A]*i,wt=k+T[A]*i,Ne=D+v[S]*i,ze=R+T[S]*i;h.push(_,k,C,M,H,0),h.push(ct,wt,C,M,H,1),h.push(D,R,I,G,tt,0),h.push(D,R,I,G,tt,0),h.push(ct,wt,C,M,H,1),h.push(Ne,ze,I,G,tt,1),l+=6}}return{vertices:new Float32Array(h),count:l}}class ft{static RESIZE_DEBOUNCE_MS=100;canvas;gl=null;container;stencilProgram=null;maskProgram=null;jfaSeedProgram=null;jfaFloodProgram=null;jfaDistProgram=null;interiorProgram=null;compositeProgram=null;boundaryProgram=null;chamferProgram=null;stencilUniforms={};maskUniforms={};jfaSeedUniforms={};jfaFloodUniforms={};jfaDistUniforms={};interiorUniforms={};compositeUniforms={};boundaryUniforms={};chamferUniforms={};quadVao=null;stencilVao=null;stencilIndexCount=0;maskVao=null;boundaryVao=null;boundaryVertexCount=0;chamferVao=null;chamferVertexCount=0;videoTexture=null;depthTexture=null;interiorFbo=null;interiorColorTex=null;interiorDepthTex=null;fboWidth=0;fboHeight=0;maskFbo=null;maskTex=null;jfaPingFbo=null;jfaPingTex=null;jfaPongFbo=null;jfaPongTex=null;distFbo=null;distTex=null;jfaWidth=0;jfaHeight=0;distFieldDirty=!0;depthWidth=0;depthHeight=0;videoAspect=1.7777777777777777;meshAspect=1;meshScaleX=.65;meshScaleY=.65;readDepth=null;readInput=null;playbackVideo=null;onVideoFrame=null;animationFrameHandle=0;rvfcHandle=0;rvfcSupported=!1;resizeObserver=null;resizeTimer=null;uvOffset=[0,0];uvScale=[1,1];lightDirX=-.707;lightDirY=.707;lightDir3=[-.5,.7,-.3];config;constructor(t,e){this.container=t,this.config={...e};const i=this.config.bevelLightAngle*Math.PI/180;this.lightDirX=Math.cos(i),this.lightDirY=Math.sin(i);const r=this.config.lightDirection,o=Math.sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]);o>1e-6&&(this.lightDir3=[r[0]/o,r[1]/o,r[2]/o]),this.canvas=document.createElement("canvas");const s=this.canvas.getContext("webgl2",{antialias:!0,alpha:!0,premultipliedAlpha:!0,stencil:!0,desynchronized:!0,powerPreference:"high-performance"});if(!s)throw new Error("WebGL 2 is not supported.");this.gl=s,"drawingBufferColorSpace"in s&&(s.drawingBufferColorSpace="srgb"),s.clearColor(0,0,0,0),s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,!0),this.container.appendChild(this.canvas),this.initGPUResources(),this.setupResizeHandling(),this.canvas.addEventListener("webglcontextlost",this.handleContextLost),this.canvas.addEventListener("webglcontextrestored",this.handleContextRestored)}initialize(t,e,i,r){const o=this.gl;o&&(this.disposeTextures(),this.disposeFBO(),this.disposeJFA(),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.videoAspect=t.videoWidth/t.videoHeight,this.meshAspect=r.aspect,this.depthWidth=e,this.depthHeight=i,this.videoTexture=o.createTexture(),o.activeTexture(o.TEXTURE0),o.bindTexture(o.TEXTURE_2D,this.videoTexture),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MIN_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MAG_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_S,o.CLAMP_TO_EDGE),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_T,o.CLAMP_TO_EDGE),this.depthTexture=o.createTexture(),o.activeTexture(o.TEXTURE1),o.bindTexture(o.TEXTURE_2D,this.depthTexture),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MIN_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_MAG_FILTER,o.LINEAR),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_S,o.CLAMP_TO_EDGE),o.texParameteri(o.TEXTURE_2D,o.TEXTURE_WRAP_T,o.CLAMP_TO_EDGE),o.texStorage2D(o.TEXTURE_2D,1,o.R8,e,i),this.uploadStencilMesh(r),this.uploadMaskMesh(r),this.uploadBoundaryMesh(r),this.uploadChamferMesh(r),this.interiorProgram&&(o.useProgram(this.interiorProgram),o.uniform1i(this.interiorUniforms.uImage,0),o.uniform1i(this.interiorUniforms.uDepth,1),o.uniform1f(this.interiorUniforms.uStrength,this.config.parallaxStrength),o.uniform1i(this.interiorUniforms.uPomSteps,this.config.pomSteps),o.uniform1f(this.interiorUniforms.uDepthPower,this.config.depthPower),o.uniform1f(this.interiorUniforms.uDepthScale,this.config.depthScale),o.uniform1f(this.interiorUniforms.uDepthBias,this.config.depthBias),o.uniform1f(this.interiorUniforms.uContrastLow,this.config.contrastLow),o.uniform1f(this.interiorUniforms.uContrastHigh,this.config.contrastHigh),o.uniform1f(this.interiorUniforms.uVerticalReduction,this.config.verticalReduction),o.uniform1f(this.interiorUniforms.uDofStart,this.config.dofStart),o.uniform1f(this.interiorUniforms.uDofStrength,this.config.dofStrength),o.uniform2f(this.interiorUniforms.uImageTexelSize,1/t.videoWidth,1/t.videoHeight),o.uniform1f(this.interiorUniforms.uFogDensity,this.config.fogDensity),o.uniform3f(this.interiorUniforms.uFogColor,...this.config.fogColor),o.uniform1f(this.interiorUniforms.uColorShift,this.config.colorShift),o.uniform1f(this.interiorUniforms.uBrightnessBias,this.config.brightnessBias)),this.compositeProgram&&(o.useProgram(this.compositeProgram),o.uniform1i(this.compositeUniforms.uInteriorColor,2),o.uniform1i(this.compositeUniforms.uDistField,4),o.uniform1f(this.compositeUniforms.uEdgeOcclusionWidth,this.config.edgeOcclusionWidth),o.uniform1f(this.compositeUniforms.uEdgeOcclusionStrength,this.config.edgeOcclusionStrength)),this.chamferProgram&&(o.useProgram(this.chamferProgram),o.uniform3f(this.chamferUniforms.uLightDir3,...this.lightDir3),o.uniform3f(this.chamferUniforms.uChamferColor,...this.config.chamferColor),o.uniform1f(this.chamferUniforms.uChamferAmbient,this.config.chamferAmbient),o.uniform1f(this.chamferUniforms.uChamferSpecular,this.config.chamferSpecular),o.uniform1f(this.chamferUniforms.uChamferShininess,this.config.chamferShininess),o.uniform1i(this.chamferUniforms.uInteriorColor,2)),this.boundaryProgram&&(o.useProgram(this.boundaryProgram),o.uniform1i(this.boundaryUniforms.uInteriorColor,2),o.uniform1i(this.boundaryUniforms.uInteriorDepth,3),o.uniform1i(this.boundaryUniforms.uDistField,4),o.uniform1f(this.boundaryUniforms.uRimIntensity,this.config.rimLightIntensity),o.uniform3f(this.boundaryUniforms.uRimColor,...this.config.rimLightColor),o.uniform1f(this.boundaryUniforms.uRefractionStrength,this.config.refractionStrength),o.uniform1f(this.boundaryUniforms.uChromaticStrength,this.config.chromaticStrength),o.uniform1f(this.boundaryUniforms.uOcclusionIntensity,this.config.occlusionIntensity),o.uniform1f(this.boundaryUniforms.uEdgeThickness,this.config.edgeThickness),o.uniform1f(this.boundaryUniforms.uEdgeSpecular,this.config.edgeSpecular),o.uniform3f(this.boundaryUniforms.uEdgeColor,...this.config.edgeColor),o.uniform2f(this.boundaryUniforms.uLightDir,this.lightDirX,this.lightDirY),o.uniform1f(this.boundaryUniforms.uBevelIntensity,this.config.bevelIntensity)),this.recalculateViewportLayout())}uploadStencilMesh(t){const e=this.gl;if(!e||!this.stencilProgram)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 r=e.getAttribLocation(this.stencilProgram,"aPosition");e.enableVertexAttribArray(r),e.vertexAttribPointer(r,2,e.FLOAT,!1,0,0);const o=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,o),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.maskProgram)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 r=e.getAttribLocation(this.maskProgram,"aPosition");e.enableVertexAttribArray(r),e.vertexAttribPointer(r,2,e.FLOAT,!1,0,0);const o=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,o),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t.indices,e.STATIC_DRAW),e.bindVertexArray(null)}uploadBoundaryMesh(t){const e=this.gl;if(!e||!this.boundaryProgram)return;const i=fe(t.edgeVertices);if(i.count===0)return;this.boundaryVao=e.createVertexArray(),e.bindVertexArray(this.boundaryVao);const r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,i.vertices,e.STATIC_DRAW);const o=16,s=e.getAttribLocation(this.boundaryProgram,"aPosition");e.enableVertexAttribArray(s),e.vertexAttribPointer(s,2,e.FLOAT,!1,o,0);const a=e.getAttribLocation(this.boundaryProgram,"aNormal");a>=0&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,2,e.FLOAT,!1,o,8)),this.boundaryVertexCount=i.count,e.bindVertexArray(null)}uploadChamferMesh(t){const e=this.gl;if(!e||!this.chamferProgram||this.config.chamferWidth<=0)return;const i=de(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 r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,i.vertices,e.STATIC_DRAW);const o=24,s=e.getAttribLocation(this.chamferProgram,"aPosition");e.enableVertexAttribArray(s),e.vertexAttribPointer(s,2,e.FLOAT,!1,o,0);const a=e.getAttribLocation(this.chamferProgram,"aNormal3");a>=0&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,3,e.FLOAT,!1,o,8));const h=e.getAttribLocation(this.chamferProgram,"aLerpT");h>=0&&(e.enableVertexAttribArray(h),e.vertexAttribPointer(h,1,e.FLOAT,!1,o,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 r=i.checkFramebufferStatus(i.FRAMEBUFFER);r!==i.FRAMEBUFFER_COMPLETE&&console.error("Interior FBO incomplete:",r),i.bindFramebuffer(i.FRAMEBUFFER,null)}createJFAResources(t,e){const i=this.gl;if(!i)return;this.disposeJFA();const r=Math.max(1,Math.round(t/2)),o=Math.max(1,Math.round(e/2));this.jfaWidth=r,this.jfaHeight=o;const s=(a,h,l,u)=>{const f=i.createFramebuffer();return i.bindFramebuffer(i.FRAMEBUFFER,f),i.bindTexture(i.TEXTURE_2D,a),i.texStorage2D(i.TEXTURE_2D,1,h,l,u),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,a,0),i.bindFramebuffer(i.FRAMEBUFFER,null),f};this.maskTex=i.createTexture(),this.maskFbo=s(this.maskTex,i.R8,r,o),this.jfaPingTex=i.createTexture(),this.jfaPingFbo=s(this.jfaPingTex,i.RG16F,r,o),this.jfaPongTex=i.createTexture(),this.jfaPongFbo=s(this.jfaPongTex,i.RG16F,r,o),this.distTex=i.createTexture(),this.distFbo=s(this.distTex,i.RGBA8,r,o),this.distFieldDirty=!0}computeDistanceField(){const t=this.gl;if(!t||!this.maskFbo||!this.maskVao||!this.quadVao||!this.jfaPingFbo||!this.jfaPongFbo||!this.distFbo)return;const e=this.jfaWidth,i=this.jfaHeight;if(e===0||i===0)return;t.viewport(0,0,e,i),t.disable(t.STENCIL_TEST),t.disable(t.BLEND),t.bindFramebuffer(t.FRAMEBUFFER,this.maskFbo),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.maskProgram),t.uniform2f(this.maskUniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.bindVertexArray(this.maskVao),t.drawElements(t.TRIANGLES,this.stencilIndexCount,t.UNSIGNED_SHORT,0),t.bindFramebuffer(t.FRAMEBUFFER,this.jfaPingFbo),t.clearColor(-1,-1,0,0),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.jfaSeedProgram),t.activeTexture(t.TEXTURE5),t.bindTexture(t.TEXTURE_2D,this.maskTex),t.uniform1i(this.jfaSeedUniforms.uMask,5),t.uniform2f(this.jfaSeedUniforms.uTexelSize,1/e,1/i),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4);const r=Math.max(e,i),o=[];let s=Math.ceil(r/2);for(;s>=1;)o.push(s),s=Math.floor(s/2);t.useProgram(this.jfaFloodProgram);let a=this.jfaPingTex,h=this.jfaPongFbo,l=this.jfaPongTex;for(let f=0;f<o.length;f++){const c=o[f]/Math.max(e,i);t.bindFramebuffer(t.FRAMEBUFFER,h),t.activeTexture(t.TEXTURE5),t.bindTexture(t.TEXTURE_2D,a),t.uniform1i(this.jfaFloodUniforms.uSeedTex,5),t.uniform1f(this.jfaFloodUniforms.uStepSize,c),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4);const d=a,m=h;a=l,h=m===this.jfaPongFbo?this.jfaPingFbo:this.jfaPongFbo,l=d}t.bindFramebuffer(t.FRAMEBUFFER,this.distFbo),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.jfaDistProgram),t.activeTexture(t.TEXTURE5),t.bindTexture(t.TEXTURE_2D,a),t.uniform1i(this.jfaDistUniforms.uSeedTex,5),t.activeTexture(t.TEXTURE6),t.bindTexture(t.TEXTURE_2D,this.maskTex),t.uniform1i(this.jfaDistUniforms.uMask,6);const u=Math.max(this.config.bevelWidth,this.config.edgeOcclusionWidth);t.uniform1f(this.jfaDistUniforms.uBevelWidth,u),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.activeTexture(t.TEXTURE4),t.bindTexture(t.TEXTURE_2D,this.distTex),t.bindFramebuffer(t.FRAMEBUFFER,null),this.distFieldDirty=!1}start(t,e,i,r){this.stop(),this.playbackVideo=t,this.readDepth=e,this.readInput=i,this.onVideoFrame=r??null,this.rvfcSupported="requestVideoFrameCallback"in HTMLVideoElement.prototype,this.rvfcSupported&&(this.rvfcHandle=t.requestVideoFrameCallback(this.videoFrameLoop)),this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)}stop(){this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0),this.rvfcHandle&&this.playbackVideo&&(this.playbackVideo.cancelVideoFrameCallback(this.rvfcHandle),this.rvfcHandle=0),this.playbackVideo=null,this.readDepth=null,this.readInput=null,this.onVideoFrame=null,this.rvfcSupported=!1}dispose(){this.stop(),this.disposeTextures(),this.disposeFBO(),this.disposeJFA(),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.disposeGPUResources(),this.canvas.removeEventListener("webglcontextlost",this.handleContextLost),this.canvas.removeEventListener("webglcontextrestored",this.handleContextRestored),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),window.removeEventListener("resize",this.scheduleResizeRecalculate),this.resizeTimer!==null&&(window.clearTimeout(this.resizeTimer),this.resizeTimer=null)}initGPUResources(){const t=this.gl;if(!t)return;this.stencilProgram=O(t,L(t,t.VERTEX_SHADER,qt),L(t,t.FRAGMENT_SHADER,Zt)),this.stencilUniforms={uMeshScale:t.getUniformLocation(this.stencilProgram,"uMeshScale")},this.maskProgram=O(t,L(t,t.VERTEX_SHADER,$t),L(t,t.FRAGMENT_SHADER,Jt)),this.maskUniforms={uMeshScale:t.getUniformLocation(this.maskProgram,"uMeshScale")},this.jfaSeedProgram=O(t,L(t,t.VERTEX_SHADER,Kt),L(t,t.FRAGMENT_SHADER,Qt)),this.jfaSeedUniforms=this.getUniforms(this.jfaSeedProgram,["uMask","uTexelSize"]),this.jfaFloodProgram=O(t,L(t,t.VERTEX_SHADER,te),L(t,t.FRAGMENT_SHADER,ee)),this.jfaFloodUniforms=this.getUniforms(this.jfaFloodProgram,["uSeedTex","uStepSize"]),this.jfaDistProgram=O(t,L(t,t.VERTEX_SHADER,ie),L(t,t.FRAGMENT_SHADER,re)),this.jfaDistUniforms=this.getUniforms(this.jfaDistProgram,["uSeedTex","uMask","uBevelWidth"]),this.interiorProgram=O(t,L(t,t.VERTEX_SHADER,oe),L(t,t.FRAGMENT_SHADER,ne)),this.interiorUniforms=this.getUniforms(this.interiorProgram,["uImage","uDepth","uOffset","uStrength","uPomSteps","uDepthPower","uDepthScale","uDepthBias","uContrastLow","uContrastHigh","uVerticalReduction","uDofStart","uDofStrength","uImageTexelSize","uFogDensity","uFogColor","uColorShift","uBrightnessBias","uUvOffset","uUvScale"]),this.compositeProgram=O(t,L(t,t.VERTEX_SHADER,se),L(t,t.FRAGMENT_SHADER,ae)),this.compositeUniforms=this.getUniforms(this.compositeProgram,["uInteriorColor","uDistField","uEdgeOcclusionWidth","uEdgeOcclusionStrength"]),this.boundaryProgram=O(t,L(t,t.VERTEX_SHADER,he),L(t,t.FRAGMENT_SHADER,le)),this.boundaryUniforms=this.getUniforms(this.boundaryProgram,["uInteriorColor","uInteriorDepth","uDistField","uRimIntensity","uRimColor","uRimWidth","uMeshScale","uRefractionStrength","uChromaticStrength","uOcclusionIntensity","uTexelSize","uEdgeThickness","uEdgeSpecular","uEdgeColor","uLightDir","uBevelIntensity"]),this.chamferProgram=O(t,L(t,t.VERTEX_SHADER,ce),L(t,t.FRAGMENT_SHADER,ue)),this.chamferUniforms=this.getUniforms(this.chamferProgram,["uMeshScale","uLightDir3","uChamferColor","uChamferAmbient","uChamferSpecular","uChamferShininess","uInteriorColor","uTexelSize"]);const e=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.quadVao=t.createVertexArray(),t.bindVertexArray(this.quadVao);const i=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW);const r=t.getAttribLocation(this.interiorProgram,"aPosition");t.enableVertexAttribArray(r),t.vertexAttribPointer(r,2,t.FLOAT,!1,0,0),t.bindVertexArray(null),t.disable(t.DEPTH_TEST)}getUniforms(t,e){const i=this.gl,r={};for(const o of e)r[o]=i.getUniformLocation(t,o);return r}videoFrameLoop=(t,e)=>{const i=this.playbackVideo;if(!i)return;this.rvfcHandle=i.requestVideoFrameCallback(this.videoFrameLoop);const r=e.mediaTime??i.currentTime;this.updateDepthTexture(r),this.onVideoFrame&&this.onVideoFrame(r,e.presentedFrames??0)};renderLoop=()=>{this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop);const t=this.gl,e=this.playbackVideo;if(!t||!this.interiorProgram||!this.quadVao||!e||e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA||!this.interiorFbo||!this.interiorColorTex||!this.interiorDepthTex)return;this.distFieldDirty&&this.maskVao&&this.distFbo&&(this.computeDistanceField(),t.viewport(0,0,this.canvas.width,this.canvas.height)),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),this.rvfcSupported||this.updateDepthTexture(e.currentTime);let i=0,r=0;if(this.readInput){const o=this.readInput();i=-o.x,r=o.y}t.bindFramebuffer(t.FRAMEBUFFER,this.interiorFbo),t.viewport(0,0,this.fboWidth,this.fboHeight),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.interiorProgram),t.uniform2f(this.interiorUniforms.uOffset,i,r),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.depthTexture),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.stencilProgram&&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.stencilProgram),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.distTex),t.useProgram(this.compositeProgram),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.disable(t.STENCIL_TEST),this.chamferVao&&this.chamferProgram&&this.chamferVertexCount>0&&(t.useProgram(this.chamferProgram),t.uniform2f(this.chamferUniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform2f(this.chamferUniforms.uTexelSize,1/this.canvas.width,1/this.canvas.height),t.bindVertexArray(this.chamferVao),t.drawArrays(t.TRIANGLES,0,this.chamferVertexCount)),this.boundaryVao&&this.boundaryProgram&&this.boundaryVertexCount>0&&this.config.rimLightIntensity>0&&(t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.useProgram(this.boundaryProgram),t.bindVertexArray(this.boundaryVao),t.drawArrays(t.TRIANGLES,0,this.boundaryVertexCount),t.disable(t.BLEND))};updateDepthTexture(t){const e=this.gl;if(!e||!this.readDepth||!this.depthTexture)return;const i=this.readDepth(t);e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.depthTexture),e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.depthWidth,this.depthHeight,e.RED,e.UNSIGNED_BYTE,i)}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()},ft.RESIZE_DEBOUNCE_MS)};recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:i}=this.getViewportSize(),r=Math.min(window.devicePixelRatio,2),o=Math.round(e*r),s=Math.round(i*r);(this.canvas.width!==o||this.canvas.height!==s)&&(this.canvas.width=o,this.canvas.height=s,t.viewport(0,0,o,s)),(this.fboWidth!==o||this.fboHeight!==s)&&this.createFBO(o,s);const a=Math.max(1,Math.round(o/2)),h=Math.max(1,Math.round(s/2));(this.jfaWidth!==a||this.jfaHeight!==h)&&this.createJFAResources(o,s);const l=e/i,u=this.config.parallaxStrength+this.config.overscanPadding;let f=1,c=1;l>this.videoAspect?c=this.videoAspect/l:f=l/this.videoAspect;const d=1+u*2;f/=d,c/=d,this.uvOffset=[(1-f)/2,(1-c)/2],this.uvScale=[f,c],this.interiorProgram&&(t.useProgram(this.interiorProgram),t.uniform2f(this.interiorUniforms.uUvOffset,this.uvOffset[0],this.uvOffset[1]),t.uniform2f(this.interiorUniforms.uUvScale,this.uvScale[0],this.uvScale[1]));const m=.65;this.meshScaleX=m,this.meshScaleY=m,l>this.meshAspect?this.meshScaleX=m*(this.meshAspect/l):this.meshScaleY=m*(l/this.meshAspect),this.stencilProgram&&(t.useProgram(this.stencilProgram),t.uniform2f(this.stencilUniforms.uMeshScale,this.meshScaleX,this.meshScaleY)),this.boundaryProgram&&(t.useProgram(this.boundaryProgram),t.uniform2f(this.boundaryUniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform1f(this.boundaryUniforms.uRimWidth,this.config.rimLightWidth),t.uniform2f(this.boundaryUniforms.uTexelSize,1/o,1/s)),this.chamferProgram&&(t.useProgram(this.chamferProgram),t.uniform2f(this.chamferUniforms.uMeshScale,this.meshScaleX,this.meshScaleY)),this.distFieldDirty=!0}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}}handleContextLost=t=>{t.preventDefault(),this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0)};handleContextRestored=()=>{const t=this.canvas.getContext("webgl2",{alpha:!0,premultipliedAlpha:!0,stencil:!0});t&&(this.gl=t,t.clearColor(0,0,0,0),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),this.initGPUResources(),this.playbackVideo&&(this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)))};disposeTextures(){const t=this.gl;t&&(this.videoTexture&&(t.deleteTexture(this.videoTexture),this.videoTexture=null),this.depthTexture&&(t.deleteTexture(this.depthTexture),this.depthTexture=null))}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)}disposeJFA(){const t=this.gl;t&&(this.maskTex&&(t.deleteTexture(this.maskTex),this.maskTex=null),this.maskFbo&&(t.deleteFramebuffer(this.maskFbo),this.maskFbo=null),this.jfaPingTex&&(t.deleteTexture(this.jfaPingTex),this.jfaPingTex=null),this.jfaPingFbo&&(t.deleteFramebuffer(this.jfaPingFbo),this.jfaPingFbo=null),this.jfaPongTex&&(t.deleteTexture(this.jfaPongTex),this.jfaPongTex=null),this.jfaPongFbo&&(t.deleteFramebuffer(this.jfaPongFbo),this.jfaPongFbo=null),this.distTex&&(t.deleteTexture(this.distTex),this.distTex=null),this.distFbo&&(t.deleteFramebuffer(this.distFbo),this.distFbo=null),this.jfaWidth=0,this.jfaHeight=0,this.distFieldDirty=!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)}disposeGPUResources(){const t=this.gl;t&&(this.stencilProgram&&(t.deleteProgram(this.stencilProgram),this.stencilProgram=null),this.maskProgram&&(t.deleteProgram(this.maskProgram),this.maskProgram=null),this.jfaSeedProgram&&(t.deleteProgram(this.jfaSeedProgram),this.jfaSeedProgram=null),this.jfaFloodProgram&&(t.deleteProgram(this.jfaFloodProgram),this.jfaFloodProgram=null),this.jfaDistProgram&&(t.deleteProgram(this.jfaDistProgram),this.jfaDistProgram=null),this.interiorProgram&&(t.deleteProgram(this.interiorProgram),this.interiorProgram=null),this.compositeProgram&&(t.deleteProgram(this.compositeProgram),this.compositeProgram=null),this.boundaryProgram&&(t.deleteProgram(this.boundaryProgram),this.boundaryProgram=null),this.chamferProgram&&(t.deleteProgram(this.chamferProgram),this.chamferProgram=null),this.quadVao&&(t.deleteVertexArray(this.quadVao),this.quadVao=null),this.stencilUniforms={},this.maskUniforms={},this.jfaSeedUniforms={},this.jfaFloodUniforms={},this.jfaDistUniforms={},this.interiorUniforms={},this.compositeUniforms={},this.boundaryUniforms={},this.chamferUniforms={})}}async function me(n){const t=await fetch(n);if(!t.ok)throw new Error(`Failed to fetch SVG: ${t.status} ${t.statusText}`);const e=await t.text();return pe(e)}function pe(n){const i=new DOMParser().parseFromString(n,"image/svg+xml").querySelector("svg");if(!i)throw new Error("No <svg> element found in document.");const r=ge(i);if(r.length===0)throw new Error("No path data found in SVG.");let o=1/0,s=1/0,a=-1/0,h=-1/0;for(const D of r)for(let R=0;R<D.length;R+=2)o=Math.min(o,D[R]),a=Math.max(a,D[R]),s=Math.min(s,D[R+1]),h=Math.max(h,D[R+1]);const l=a-o,u=h-s,f=(o+a)/2,c=(s+h)/2,d=2/Math.max(l,u),m=l/u,g=r.map(D=>{const R=[];for(let C=0;C<D.length;C+=2)R.push((D[C]-f)*d),R.push(-((D[C+1]-c)*d));return R}),U=Se(g),y=[],E=[];for(const D of U){const{flatCoords:R,holeIndices:C}=Ae(D),M=Re(R,C),H=y.length/2;for(const I of M)E.push(I+H);for(const I of R)y.push(I)}const p=y,v=E,T=[],x=[],A=[],S=At(g);for(let D=0;D<g.length;D++){const R=g[D];x.push(T.length),A.push(S[D]);for(let C=0;C<R.length;C++)T.push(R[C]);R.length>=2&&T.push(R[0],R[1])}let F=1/0,P=1/0,_=-1/0,k=-1/0;for(let D=0;D<p.length;D+=2)F=Math.min(F,p[D]),_=Math.max(_,p[D]),P=Math.min(P,p[D+1]),k=Math.max(k,p[D+1]);return{vertices:new Float32Array(p),indices:new Uint16Array(v),edgeVertices:new Float32Array(T),contourOffsets:x,contourIsHole:A,bounds:{minX:F,maxX:_,minY:P,maxY:k},aspect:m}}function ge(n){const t=[];return n.querySelectorAll("path").forEach(h=>{const l=h.getAttribute("d");if(!l)return;const u=Te(l);t.push(...u)}),n.querySelectorAll("polygon").forEach(h=>{const l=h.getAttribute("points");if(!l)return;const u=Et(l);u.length>=6&&t.push(u)}),n.querySelectorAll("polyline").forEach(h=>{const l=h.getAttribute("points");if(!l)return;const u=Et(l);u.length>=6&&t.push(u)}),n.querySelectorAll("rect").forEach(h=>{const l=parseFloat(h.getAttribute("x")||"0"),u=parseFloat(h.getAttribute("y")||"0"),f=parseFloat(h.getAttribute("width")||"0"),c=parseFloat(h.getAttribute("height")||"0");f>0&&c>0&&t.push([l,u,l+f,u,l+f,u+c,l,u+c])}),n.querySelectorAll("circle").forEach(h=>{const l=parseFloat(h.getAttribute("cx")||"0"),u=parseFloat(h.getAttribute("cy")||"0"),f=parseFloat(h.getAttribute("r")||"0");f>0&&t.push(ve(l,u,f))}),n.querySelectorAll("ellipse").forEach(h=>{const l=parseFloat(h.getAttribute("cx")||"0"),u=parseFloat(h.getAttribute("cy")||"0"),f=parseFloat(h.getAttribute("rx")||"0"),c=parseFloat(h.getAttribute("ry")||"0");f>0&&c>0&&t.push(xe(l,u,f,c))}),t}function Et(n){const t=[],e=n.trim().split(/[\s,]+/);for(let i=0;i<e.length-1;i+=2){const r=parseFloat(e[i]),o=parseFloat(e[i+1]);Number.isFinite(r)&&Number.isFinite(o)&&t.push(r,o)}return t}function ve(n,t,e,i=64){const r=[];for(let o=0;o<i;o++){const s=2*Math.PI*o/i;r.push(n+e*Math.cos(s),t+e*Math.sin(s))}return r}function xe(n,t,e,i,r=64){const o=[];for(let s=0;s<r;s++){const a=2*Math.PI*s/r;o.push(n+e*Math.cos(a),t+i*Math.sin(a))}return o}function Te(n){const t=[];let e=[],i=0,r=0,o=0,s=0,a=0,h=0,l="";const u=Ee(n);let f=0;function c(){return f>=u.length?0:parseFloat(u[f++])}for(;f<u.length;){const d=u[f];let m;/^[a-zA-Z]$/.test(d)?(m=d,f++):m=l==="M"?"L":l==="m"?"l":l;const g=m===m.toLowerCase();switch(m.toUpperCase()){case"M":{e.length>0&&t.push(e),e=[];const y=c()+(g?i:0),E=c()+(g?r:0);i=y,r=E,o=y,s=E,e.push(i,r),a=i,h=r;break}case"L":{i=c()+(g?i:0),r=c()+(g?r:0),e.push(i,r),a=i,h=r;break}case"H":{i=c()+(g?i:0),e.push(i,r),a=i,h=r;break}case"V":{r=c()+(g?r:0),e.push(i,r),a=i,h=r;break}case"C":{const y=c()+(g?i:0),E=c()+(g?r:0),p=c()+(g?i:0),v=c()+(g?r:0),T=c()+(g?i:0),x=c()+(g?r:0);$(e,i,r,y,E,p,v,T,x),i=T,r=x,a=p,h=v;break}case"S":{const y=2*i-a,E=2*r-h,p=c()+(g?i:0),v=c()+(g?r:0),T=c()+(g?i:0),x=c()+(g?r:0);$(e,i,r,y,E,p,v,T,x),i=T,r=x,a=p,h=v;break}case"Q":{const y=c()+(g?i:0),E=c()+(g?r:0),p=c()+(g?i:0),v=c()+(g?r:0);bt(e,i,r,y,E,p,v),i=p,r=v,a=y,h=E;break}case"T":{const y=2*i-a,E=2*r-h,p=c()+(g?i:0),v=c()+(g?r:0);bt(e,i,r,y,E,p,v),i=p,r=v,a=y,h=E;break}case"A":{const y=c(),E=c(),p=c(),v=c(),T=c(),x=c()+(g?i:0),A=c()+(g?r:0);ye(e,i,r,y,E,p,!!v,!!T,x,A),i=x,r=A,a=i,h=r;break}case"Z":{i=o,r=s,e.length>0&&t.push(e),e=[],a=i,h=r;break}default:f++;break}l=m}return e.length>=6&&t.push(e),t}function Ee(n){const t=[],e=/([a-zA-Z])|([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)/g;let i;for(;(i=e.exec(n))!==null;)t.push(i[0]);return t}const be=.5;function $(n,t,e,i,r,o,s,a,h,l=0){if(l>12){n.push(a,h);return}const u=a-t,f=h-e,c=Math.sqrt(u*u+f*f);if(c<1e-6){n.push(a,h);return}const d=Math.abs((i-a)*f-(r-h)*u)/c,m=Math.abs((o-a)*f-(s-h)*u)/c;if(d+m<be){n.push(a,h);return}const g=(t+i)/2,U=(e+r)/2,y=(i+o)/2,E=(r+s)/2,p=(o+a)/2,v=(s+h)/2,T=(g+y)/2,x=(U+E)/2,A=(y+p)/2,S=(E+v)/2,F=(T+A)/2,P=(x+S)/2;$(n,t,e,g,U,T,x,F,P,l+1),$(n,F,P,A,S,p,v,a,h,l+1)}function bt(n,t,e,i,r,o,s){const a=t+.6666666666666666*(i-t),h=e+2/3*(r-e),l=o+2/3*(i-o),u=s+2/3*(r-s);$(n,t,e,a,h,l,u,o,s)}function ye(n,t,e,i,r,o,s,a,h,l){if(i===0||r===0){n.push(h,l);return}let u=Math.abs(i),f=Math.abs(r);const c=o*Math.PI/180,d=Math.cos(c),m=Math.sin(c),g=(t-h)/2,U=(e-l)/2,y=d*g+m*U,E=-m*g+d*U;let p=y*y/(u*u)+E*E/(f*f);if(p>1){const M=Math.sqrt(p);u*=M,f*=M,p=1}const v=u*u,T=f*f,x=y*y,A=E*E;let S=Math.max(0,(v*T-v*A-T*x)/(v*A+T*x));S=Math.sqrt(S),s===a&&(S=-S);const F=S*(u*E)/f,P=S*-(f*y)/u,_=d*F-m*P+(t+h)/2,k=m*F+d*P+(e+l)/2,D=yt(1,0,(y-F)/u,(E-P)/f);let R=yt((y-F)/u,(E-P)/f,(-y-F)/u,(-E-P)/f);!a&&R>0&&(R-=2*Math.PI),a&&R<0&&(R+=2*Math.PI);const C=Math.max(4,Math.ceil(Math.abs(R)/(Math.PI/16)));for(let M=1;M<=C;M++){const H=D+M/C*R,I=Math.cos(H),G=Math.sin(H),tt=d*u*I-m*f*G+_,ct=m*u*I+d*f*G+k;n.push(tt,ct)}}function yt(n,t,e,i){const r=n*i-t*e<0?-1:1,o=n*e+t*i,s=Math.sqrt(n*n+t*t),a=Math.sqrt(e*e+i*i),h=o/(s*a);return r*Math.acos(Math.max(-1,Math.min(1,h)))}function Ae(n){const t=[],e=[];for(let i=0;i<n.length;i++){i>0&&e.push(t.length/2);for(const r of n[i])t.push(r)}return{flatCoords:t,holeIndices:e}}function At(n){const t=n.length,e=n.map(r=>Math.abs(St(r))),i=new Array(t).fill(!1);for(let r=0;r<t;r++){let o=0;const s=n[r][0],a=n[r][1];for(let h=0;h<t;h++)r!==h&&e[h]>e[r]&&Rt(s,a,n[h])&&o++;i[r]=o%2===1}return i}function Se(n){if(n.length<=1)return[n];const t=At(n),e=n.map((s,a)=>{const h=St(s);return{index:a,contour:s,area:h,isOuter:!t[a]}}),i=e.filter(s=>s.isOuter),r=e.filter(s=>!s.isOuter);if(i.length===0)return n.map(s=>[s]);const o=i.map(s=>({outer:s.contour,holes:[]}));for(const s of r){const a=s.contour[0],h=s.contour[1];let l=-1,u=1/0;for(let f=0;f<i.length;f++)if(Rt(a,h,i[f].contour)){const c=Math.abs(i[f].area);c<u&&(u=c,l=f)}l>=0?o[l].holes.push(s.contour):o.push({outer:s.contour,holes:[]})}return o.map(s=>[s.outer,...s.holes])}function St(n){let t=0;const e=n.length;for(let i=0;i<e;i+=2){const r=n[i],o=n[i+1],s=n[(i+2)%e],a=n[(i+3)%e];t+=r*a-s*o}return t/2}function Rt(n,t,e){let i=!1;const r=e.length;for(let o=0,s=r-2;o<r;s=o,o+=2){const a=e[o],h=e[o+1],l=e[s],u=e[s+1];h>t!=u>t&&n<(l-a)*(t-h)/(u-h)+a&&(i=!i)}return i}function Re(n,t,e=2){const i=t&&t.length>0,r=i?t[0]*e:n.length;let o=Dt(n,0,r,e,!0);const s=[];if(!o||o.next===o.prev)return s;i&&(o=we(n,t,o,e));let a=1/0,h=1/0,l=-1/0,u=-1/0,f=0;if(n.length>80*e){for(let c=0;c<r;c+=e){const d=n[c],m=n[c+1];d<a&&(a=d),m<h&&(h=m),d>l&&(l=d),m>u&&(u=m)}f=Math.max(l-a,u-h),f=f!==0?32767/f:0}return J(o,s,e,a,h,f,0),s}function Dt(n,t,e,i,r){let o=null;if(r===Be(n,t,e,i)>0)for(let s=t;s<e;s+=i)o=Pt(s,n[s],n[s+1],o);else for(let s=e-i;s>=t;s-=i)o=Pt(s,n[s],n[s+1],o);return o&&nt(o,o.next)&&(Q(o),o=o.next),o?(o.next.prev=o,o.prev.next=o,o.next):null}function X(n,t){t||(t=n);let e=n,i;do if(i=!1,!e.steiner&&(nt(e,e.next)||w(e.prev,e,e.next)===0)){if(Q(e),e=t=e.prev,e===e.next)break;i=!0}else e=e.next;while(i||e!==t);return t}function J(n,t,e,i,r,o,s){if(!n)return;!s&&o&&_e(n,i,r,o);let a=n,h,l;for(;n.prev!==n.next;){if(h=n.prev,l=n.next,o?Fe(n,i,r,o):De(n)){t.push(h.i/e,n.i/e,l.i/e),Q(n),n=l.next,a=l.next;continue}if(n=l,n===a){s?s===1?(n=Ue(X(n),t,e),J(n,t,e,i,r,o,2)):s===2&&Pe(n,t,e,i,r,o):J(X(n),t,e,i,r,o,1);break}}}function De(n){const t=n.prev,e=n,i=n.next;if(w(t,e,i)>=0)return!1;const r=t.x,o=e.x,s=i.x,a=t.y,h=e.y,l=i.y,u=r<o?r<s?r:s:o<s?o:s,f=a<h?a<l?a:l:h<l?h:l,c=r>o?r>s?r:s:o>s?o:s,d=a>h?a>l?a:l:h>l?h:l;let m=i.next;for(;m!==t;){if(m.x>=u&&m.x<=c&&m.y>=f&&m.y<=d&&z(r,a,o,h,s,l,m.x,m.y)&&w(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Fe(n,t,e,i){const r=n.prev,o=n,s=n.next;if(w(r,o,s)>=0)return!1;const a=r.x,h=o.x,l=s.x,u=r.y,f=o.y,c=s.y,d=a<h?a<l?a:l:h<l?h:l,m=u<f?u<c?u:c:f<c?f:c,g=a>h?a>l?a:l:h>l?h:l,U=u>f?u>c?u:c:f>c?f:c,y=dt(d,m,t,e,i),E=dt(g,U,t,e,i);let p=n.prevZ,v=n.nextZ;for(;p&&p.z>=y&&v&&v.z<=E;){if(p.x>=d&&p.x<=g&&p.y>=m&&p.y<=U&&p!==r&&p!==s&&z(a,u,h,f,l,c,p.x,p.y)&&w(p.prev,p,p.next)>=0||(p=p.prevZ,v.x>=d&&v.x<=g&&v.y>=m&&v.y<=U&&v!==r&&v!==s&&z(a,u,h,f,l,c,v.x,v.y)&&w(v.prev,v,v.next)>=0))return!1;v=v.nextZ}for(;p&&p.z>=y;){if(p.x>=d&&p.x<=g&&p.y>=m&&p.y<=U&&p!==r&&p!==s&&z(a,u,h,f,l,c,p.x,p.y)&&w(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;v&&v.z<=E;){if(v.x>=d&&v.x<=g&&v.y>=m&&v.y<=U&&v!==r&&v!==s&&z(a,u,h,f,l,c,v.x,v.y)&&w(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function Ue(n,t,e){let i=n;do{const r=i.prev,o=i.next.next;!nt(r,o)&&Ft(r,i,i.next,o)&&K(r,o)&&K(o,r)&&(t.push(r.i/e,i.i/e,o.i/e),Q(i),Q(i.next),i=n=o),i=i.next}while(i!==n);return X(i)}function Pe(n,t,e,i,r,o){let s=n;do{let a=s.next.next;for(;a!==s.prev;){if(s.i!==a.i&&Oe(s,a)){let h=Ut(s,a);s=X(s,s.next),h=X(h,h.next),J(s,t,e,i,r,o,0),J(h,t,e,i,r,o,0);return}a=a.next}s=s.next}while(s!==n)}function we(n,t,e,i){const r=[];for(let o=0;o<t.length;o++){const s=t[o]*i,a=o<t.length-1?t[o+1]*i:n.length,h=Dt(n,s,a,i,!1);h&&(h===h.next&&(h.steiner=!0),r.push(Ve(h)))}r.sort((o,s)=>o.x-s.x);for(const o of r)e=Le(o,e);return e}function Le(n,t){const e=Ce(n,t);if(!e)return t;const i=Ut(e,n);return X(i,i.next),X(e,e.next)}function Ce(n,t){let e=t;const i=n.x,r=n.y;let o=-1/0,s=null;do{if(r<=e.y&&r>=e.next.y&&e.next.y!==e.y){const f=e.x+(r-e.y)/(e.next.y-e.y)*(e.next.x-e.x);if(f<=i&&f>o&&(o=f,s=e.x<e.next.x?e:e.next,f===i))return s}e=e.next}while(e!==t);if(!s)return null;const a=s,h=s.x,l=s.y;let u=1/0;e=s;do{if(i>=e.x&&e.x>=h&&i!==e.x&&z(r<l?i:o,r,h,l,r<l?o:i,r,e.x,e.y)){const f=Math.abs(r-e.y)/(i-e.x);K(e,n)&&(f<u||f===u&&(e.x>s.x||Me(s,e)))&&(s=e,u=f)}e=e.next}while(e!==a);return s}function Me(n,t){return w(n.prev,n,t.prev)<0&&w(t.next,n,n.next)<0}function _e(n,t,e,i){let r=n;do r.z===0&&(r.z=dt(r.x,r.y,t,e,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next;while(r!==n);r.prevZ.nextZ=null,r.prevZ=null,Ie(r)}function Ie(n){let t=1,e;do{let i=n;n=null;let r=null;for(e=0;i;){e++;let o=i,s=0;for(let h=0;h<t&&(s++,o=o.nextZ,!!o);h++);let a=t;for(;s>0||a>0&&o;){let h;s!==0&&(a===0||!o||i.z<=o.z)?(h=i,i=i.nextZ,s--):(h=o,o=o.nextZ,a--),r?r.nextZ=h:n=h,h.prevZ=r,r=h}i=o}r.nextZ=null,t*=2}while(e>1);return n}function dt(n,t,e,i,r){let o=(n-e)*r|0,s=(t-i)*r|0;return o=(o|o<<8)&16711935,o=(o|o<<4)&252645135,o=(o|o<<2)&858993459,o=(o|o<<1)&1431655765,s=(s|s<<8)&16711935,s=(s|s<<4)&252645135,s=(s|s<<2)&858993459,s=(s|s<<1)&1431655765,o|s<<1}function Ve(n){let t=n,e=n;do(t.x<e.x||t.x===e.x&&t.y<e.y)&&(e=t),t=t.next;while(t!==n);return e}function z(n,t,e,i,r,o,s,a){return(r-s)*(t-a)-(n-s)*(o-a)>=0&&(n-s)*(i-a)-(e-s)*(t-a)>=0&&(e-s)*(o-a)-(r-s)*(i-a)>=0}function Oe(n,t){return n.next.i!==t.i&&n.prev.i!==t.i&&!ke(n,t)&&(K(n,t)&&K(t,n)&&He(n,t)&&(w(n.prev,n,t.prev)!==0||w(n,t.prev,t)!==0)||nt(n,t)&&w(n.prev,n,n.next)>0&&w(t.prev,t,t.next)>0)}function w(n,t,e){return(t.y-n.y)*(e.x-t.x)-(t.x-n.x)*(e.y-t.y)}function nt(n,t){return n.x===t.x&&n.y===t.y}function Ft(n,t,e,i){const r=at(w(n,t,e)),o=at(w(n,t,i)),s=at(w(e,i,n)),a=at(w(e,i,t));return!!(r!==o&&s!==a||r===0&&st(n,e,t)||o===0&&st(n,i,t)||s===0&&st(e,n,i)||a===0&&st(e,t,i))}function st(n,t,e){return t.x<=Math.max(n.x,e.x)&&t.x>=Math.min(n.x,e.x)&&t.y<=Math.max(n.y,e.y)&&t.y>=Math.min(n.y,e.y)}function at(n){return n>0?1:n<0?-1:0}function ke(n,t){let e=n;do{if(e.i!==n.i&&e.next.i!==n.i&&e.i!==t.i&&e.next.i!==t.i&&Ft(e,e.next,n,t))return!0;e=e.next}while(e!==n);return!1}function K(n,t){return w(n.prev,n,n.next)<0?w(n,t,n.next)>=0&&w(n,n.prev,t)>=0:w(n,t,n.prev)<0||w(n,n.next,t)<0}function He(n,t){let e=n,i=!1;const r=(n.x+t.x)/2,o=(n.y+t.y)/2;do e.y>o!=e.next.y>o&&e.next.y!==e.y&&r<(e.next.x-e.x)*(o-e.y)/(e.next.y-e.y)+e.x&&(i=!i),e=e.next;while(e!==n);return i}function Ut(n,t){const e=mt(n.i,n.x,n.y),i=mt(t.i,t.x,t.y),r=n.next,o=t.prev;return n.next=t,t.prev=n,e.next=r,r.prev=e,i.next=e,e.prev=i,o.next=i,i.prev=o,i}function Pt(n,t,e,i){const r=mt(n,t,e);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function Q(n){n.next.prev=n.prev,n.prev.next=n.next,n.prevZ&&(n.prevZ.nextZ=n.nextZ),n.nextZ&&(n.nextZ.prevZ=n.prevZ)}function mt(n,t,e){return{i:n,x:t,y:e,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function Be(n,t,e,i){let r=0;for(let o=t,s=e-i;o<e;o+=i)r+=(n[s]-n[o])*(n[o+1]+n[s+1]),s=o;return r}const b={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};class pt{constructor(t,e=.08,i=.06){this.host=t,this.lerpFactor=e,this.motionLerpFactor=i,this.host.addEventListener("mousemove",this.handleMouseMove),this.host.addEventListener("mouseleave",this.resetPointerTarget),this.host.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),this.host.addEventListener("touchmove",this.handleTouchMove,{passive:!0}),this.host.addEventListener("touchend",this.handleTouchEnd,{passive:!0}),this.host.addEventListener("touchcancel",this.handleTouchEnd,{passive:!0})}pointerTarget={x:0,y:0};motionTarget={x:0,y:0};smoothedOutput={x:0,y:0};usingMotionInput=!1;motionListenerAttached=!1;motionRequested=!1;touchActive=!1;touchAnchorX=0;touchAnchorY=0;lerpFactor;motionLerpFactor;static TOUCH_DRAG_RANGE=100;update(){const t=this.touchActive?this.pointerTarget:this.usingMotionInput?this.motionTarget:this.pointerTarget,e=this.usingMotionInput&&!this.touchActive?this.motionLerpFactor:this.lerpFactor;return this.smoothedOutput.x=lt(this.smoothedOutput.x,t.x,e),this.smoothedOutput.y=lt(this.smoothedOutput.y,t.y,e),this.smoothedOutput}dispose(){this.host.removeEventListener("mousemove",this.handleMouseMove),this.host.removeEventListener("mouseleave",this.resetPointerTarget),this.host.removeEventListener("touchstart",this.handleTouchStart),this.host.removeEventListener("touchmove",this.handleTouchMove),this.host.removeEventListener("touchend",this.handleTouchEnd),this.host.removeEventListener("touchcancel",this.handleTouchEnd),this.motionListenerAttached&&(window.removeEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!1)}handleMouseMove=t=>{const e=this.host.getBoundingClientRect(),i=(t.clientX-e.left)/e.width*2-1,r=(t.clientY-e.top)/e.height*2-1;this.pointerTarget.x=W(i,-1,1),this.pointerTarget.y=W(r,-1,1)};resetPointerTarget=()=>{this.pointerTarget.x=0,this.pointerTarget.y=0};handleTouchStart=t=>{const e=t.touches[0];e&&(this.touchActive=!0,this.touchAnchorX=e.clientX,this.touchAnchorY=e.clientY,this.pointerTarget.x=0,this.pointerTarget.y=0,this.motionRequested||(this.motionRequested=!0,this.requestMotionPermission()))};handleTouchMove=t=>{const e=t.touches[0];if(!e)return;const i=e.clientX-this.touchAnchorX,r=e.clientY-this.touchAnchorY,o=pt.TOUCH_DRAG_RANGE;this.pointerTarget.x=W(i/o,-1,1),this.pointerTarget.y=W(r/o,-1,1)};handleTouchEnd=()=>{this.touchActive=!1,this.pointerTarget.x=0,this.pointerTarget.y=0};async requestMotionPermission(){if(typeof DeviceOrientationEvent>"u")return;const t=DeviceOrientationEvent;if(typeof t.requestPermission=="function")try{if(await t.requestPermission()!=="granted")return}catch{return}this.motionListenerAttached||(window.addEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!0),this.usingMotionInput=!0}handleDeviceOrientation=t=>{const e=W((t.gamma??0)/45,-1,1),i=W((t.beta??0)/45,-1,1);this.motionTarget.x=lt(this.motionTarget.x,e,this.motionLerpFactor),this.motionTarget.y=lt(this.motionTarget.y,i,this.motionLerpFactor)}}class ht extends HTMLElement{static TAG_NAME="layershift-portal";static get observedAttributes(){return["src","depth-src","depth-meta","logo-src","parallax-x","parallax-y","parallax-max","overscan","pom-steps","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"]}shadow;container=null;renderer=null;inputHandler=null;depthWorker=null;video=null;mesh=null;initialized=!1;abortController=null;loopCount=0;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}getAttrFloat(t,e){const i=this.getAttribute(t);if(i===null)return e;const r=parseFloat(i);return Number.isFinite(r)?r: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 Xe(i)}getAttrVec3(t,e){const r=(this.getAttribute(t)??e).split(",").map(s=>parseFloat(s.trim()));if(r.length>=3&&r.every(Number.isFinite))return[r[0],r[1],r[2]];const o=e.split(",").map(s=>parseFloat(s.trim()));return[o[0],o[1],o[2]]}get parallaxX(){return this.getAttrFloat("parallax-x",b.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",b.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",b.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",b.overscan)}get pomSteps(){return this.getAttrFloat("pom-steps",b.pomSteps)}get rimIntensity(){return this.getAttrFloat("rim-intensity",b.rimIntensity)}get rimWidth(){return this.getAttrFloat("rim-width",b.rimWidth)}get rimColor(){return this.getAttrColor("rim-color",b.rimColor)}get refractionStrength(){return this.getAttrFloat("refraction-strength",b.refractionStrength)}get chromaticStrength(){return this.getAttrFloat("chromatic-strength",b.chromaticStrength)}get occlusionIntensity(){return this.getAttrFloat("occlusion-intensity",b.occlusionIntensity)}get depthPower(){return this.getAttrFloat("depth-power",b.depthPower)}get depthScale(){return this.getAttrFloat("depth-scale",b.depthScale)}get depthBias(){return this.getAttrFloat("depth-bias",b.depthBias)}get fogDensity(){return this.getAttrFloat("fog-density",b.fogDensity)}get fogColor(){return this.getAttrColor("fog-color",b.fogColor)}get colorShift(){return this.getAttrFloat("color-shift",b.colorShift)}get brightnessBias(){return this.getAttrFloat("brightness-bias",b.brightnessBias)}get contrastLow(){return this.getAttrFloat("contrast-low",b.contrastLow)}get contrastHigh(){return this.getAttrFloat("contrast-high",b.contrastHigh)}get verticalReduction(){return this.getAttrFloat("vertical-reduction",b.verticalReduction)}get dofStart(){return this.getAttrFloat("dof-start",b.dofStart)}get dofStrength(){return this.getAttrFloat("dof-strength",b.dofStrength)}get bevelIntensity(){return this.getAttrFloat("bevel-intensity",b.bevelIntensity)}get bevelWidth(){return this.getAttrFloat("bevel-width",b.bevelWidth)}get bevelDarkening(){return this.getAttrFloat("bevel-darkening",b.bevelDarkening)}get bevelDesaturation(){return this.getAttrFloat("bevel-desaturation",b.bevelDesaturation)}get bevelLightAngle(){return this.getAttrFloat("bevel-light-angle",b.bevelLightAngle)}get edgeThickness(){return this.getAttrFloat("edge-thickness",b.edgeThickness)}get edgeSpecular(){return this.getAttrFloat("edge-specular",b.edgeSpecular)}get edgeColor(){return this.getAttrColor("edge-color",b.edgeColor)}get chamferWidth(){return this.getAttrFloat("chamfer-width",b.chamferWidth)}get chamferAngle(){return this.getAttrFloat("chamfer-angle",b.chamferAngle)}get chamferColor(){return this.getAttrColor("chamfer-color",b.chamferColor)}get chamferAmbient(){return this.getAttrFloat("chamfer-ambient",b.chamferAmbient)}get chamferSpecular(){return this.getAttrFloat("chamfer-specular",b.chamferSpecular)}get chamferShininess(){return this.getAttrFloat("chamfer-shininess",b.chamferShininess)}get edgeOcclusionWidth(){return this.getAttrFloat("edge-occlusion-width",b.edgeOcclusionWidth)}get edgeOcclusionStrength(){return this.getAttrFloat("edge-occlusion-strength",b.edgeOcclusionStrength)}get lightDirection3(){return this.getAttrVec3("light-direction",b.lightDirection)}get shouldAutoplay(){return this.getAttrBool("autoplay",b.autoplay)}get shouldLoop(){return this.getAttrBool("loop",b.loop)}get shouldMute(){return this.getAttrBool("muted",b.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachVideoEventListeners(t){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",()=>{t.loop&&(this.loopCount+=1,this.emit("layershift-portal:loop",{loopCount:this.loopCount}))})}connectedCallback(){this.setupShadowDOM(),this.init()}disconnectedCallback(){this.dispose()}attributeChangedCallback(t,e,i){["src","depth-src","depth-meta","logo-src"].includes(t)&&(this.initialized?(this.dispose(),this.setupShadowDOM(),this.init()):this.isConnected&&this.getAttribute("src")&&this.getAttribute("depth-src")&&this.getAttribute("depth-meta")&&this.getAttribute("logo-src")&&this.init())}setupShadowDOM(){this.shadow.innerHTML="";const t=document.createElement("style");t.textContent=`
|
|
721
|
+
`;function L(r,t,e){const i=r.createShader(t);if(!i)throw new Error("Failed to create shader.");if(r.shaderSource(i,e),r.compileShader(i),!r.getShaderParameter(i,r.COMPILE_STATUS)){const o=r.getShaderInfoLog(i)??"";throw r.deleteShader(i),new Error(`Shader compilation failed:
|
|
722
|
+
${o}`)}return i}function O(r,t,e){const i=r.createProgram();if(!i)throw new Error("Failed to create program.");if(r.attachShader(i,t),r.attachShader(i,e),r.linkProgram(i),!r.getProgramParameter(i,r.LINK_STATUS)){const o=r.getProgramInfoLog(i)??"";throw r.deleteProgram(i),new Error(`Program linking failed:
|
|
723
|
+
${o}`)}return r.detachShader(i,t),r.detachShader(i,e),r.deleteShader(t),r.deleteShader(e),i}function de(r){const t=[];let e=0;for(let i=0;i<r.length-2;i+=2){const o=r[i],n=r[i+1],s=r[i+2],h=r[i+3],a=s-o,l=h-n,u=Math.sqrt(a*a+l*l);if(u<1e-6)continue;const f=-l/u,c=a/u;t.push(o,n,f,c,o,n,-f,-c,s,h,f,c,s,h,f,c,o,n,-f,-c,s,h,-f,-c),e+=6}return{vertices:new Float32Array(t),count:e}}function me(r,t,e,i,o){if(i<=0)return{vertices:new Float32Array(0),count:0};const n=o*Math.PI/180,s=-Math.cos(n),h=Math.sin(n),a=[];let l=0;for(let u=0;u<t.length;u++){const f=t[u],d=((u+1<t.length?t[u+1]:r.length)-f)/2;if(d<3)continue;const m=d-1;let U=0;for(let x=0;x<m;x++){const A=f+x*2,S=r[A],D=r[A+1],P=r[A+2],_=r[A+3];U+=S*_-P*D}const y=U>=0?1:-1,E=[],p=[];for(let x=0;x<m;x++){const A=f+x*2,S=r[A+2]-r[A],D=r[A+3]-r[A+1],P=Math.sqrt(S*S+D*D);P<1e-8?(E.push(x>0?E[x-1]:0),p.push(x>0?p[x-1]:0)):(E.push(-D/P*y),p.push(S/P*y))}const v=[],T=[];for(let x=0;x<m;x++){const A=(x-1+m)%m;let S=E[A]+E[x],D=p[A]+p[x];const P=Math.sqrt(S*S+D*D);P>1e-8?(S/=P,D/=P):(S=E[x],D=p[x]),v.push(S),T.push(D)}for(let x=0;x<m;x++){const A=x,S=(x+1)%m,D=f+x*2,P=f+(x+1)%m*2,_=r[D],k=r[D+1],F=r[P],R=r[P+1],C=v[A]*h,M=T[A]*h,B=s,I=v[S]*h,G=T[S]*h,tt=s,ct=_+v[A]*i,Lt=k+T[A]*i,ze=F+v[S]*i,We=R+T[S]*i;a.push(_,k,C,M,B,0),a.push(ct,Lt,C,M,B,1),a.push(F,R,I,G,tt,0),a.push(F,R,I,G,tt,0),a.push(ct,Lt,C,M,B,1),a.push(ze,We,I,G,tt,1),l+=6}}return{vertices:new Float32Array(a),count:l}}class ft{static RESIZE_DEBOUNCE_MS=100;canvas;gl=null;container;stencilProgram=null;maskProgram=null;jfaSeedProgram=null;jfaFloodProgram=null;jfaDistProgram=null;interiorProgram=null;compositeProgram=null;boundaryProgram=null;chamferProgram=null;stencilUniforms={};maskUniforms={};jfaSeedUniforms={};jfaFloodUniforms={};jfaDistUniforms={};interiorUniforms={};compositeUniforms={};boundaryUniforms={};chamferUniforms={};quadVao=null;stencilVao=null;stencilIndexCount=0;maskVao=null;boundaryVao=null;boundaryVertexCount=0;chamferVao=null;chamferVertexCount=0;videoTexture=null;depthTexture=null;interiorFbo=null;interiorColorTex=null;interiorDepthTex=null;fboWidth=0;fboHeight=0;maskFbo=null;maskTex=null;jfaPingFbo=null;jfaPingTex=null;jfaPongFbo=null;jfaPongTex=null;distFbo=null;distTex=null;jfaWidth=0;jfaHeight=0;distFieldDirty=!0;hasColorBufferFloat=!1;depthWidth=0;depthHeight=0;videoAspect=1.7777777777777777;meshAspect=1;meshScaleX=.65;meshScaleY=.65;readDepth=null;readInput=null;playbackVideo=null;onVideoFrame=null;animationFrameHandle=0;rvfcHandle=0;rvfcSupported=!1;resizeObserver=null;resizeTimer=null;uvOffset=[0,0];uvScale=[1,1];lightDirX=-.707;lightDirY=.707;lightDir3=[-.5,.7,-.3];config;constructor(t,e){this.container=t,this.config={...e};const i=this.config.bevelLightAngle*Math.PI/180;this.lightDirX=Math.cos(i),this.lightDirY=Math.sin(i);const o=this.config.lightDirection,n=Math.sqrt(o[0]*o[0]+o[1]*o[1]+o[2]*o[2]);n>1e-6&&(this.lightDir3=[o[0]/n,o[1]/n,o[2]/n]),this.canvas=document.createElement("canvas");const s=this.canvas.getContext("webgl2",{antialias:!0,alpha:!0,premultipliedAlpha:!0,stencil:!0,desynchronized:!0,powerPreference:"high-performance"});if(!s)throw new Error("WebGL 2 is not supported.");this.gl=s,"drawingBufferColorSpace"in s&&(s.drawingBufferColorSpace="srgb"),this.hasColorBufferFloat=!!s.getExtension("EXT_color_buffer_float"),s.clearColor(0,0,0,0),s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,!0),this.container.appendChild(this.canvas),this.initGPUResources(),this.setupResizeHandling(),this.canvas.addEventListener("webglcontextlost",this.handleContextLost),this.canvas.addEventListener("webglcontextrestored",this.handleContextRestored)}initialize(t,e,i,o){const n=this.gl;n&&(this.disposeTextures(),this.disposeFBO(),this.disposeJFA(),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.videoAspect=t.videoWidth/t.videoHeight,this.meshAspect=o.aspect,this.depthWidth=e,this.depthHeight=i,this.videoTexture=n.createTexture(),n.activeTexture(n.TEXTURE0),n.bindTexture(n.TEXTURE_2D,this.videoTexture),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.depthTexture=n.createTexture(),n.activeTexture(n.TEXTURE1),n.bindTexture(n.TEXTURE_2D,this.depthTexture),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.uploadStencilMesh(o),this.uploadMaskMesh(o),this.uploadBoundaryMesh(o),this.uploadChamferMesh(o),this.interiorProgram&&(n.useProgram(this.interiorProgram),n.uniform1i(this.interiorUniforms.uImage,0),n.uniform1i(this.interiorUniforms.uDepth,1),n.uniform1f(this.interiorUniforms.uStrength,this.config.parallaxStrength),n.uniform1i(this.interiorUniforms.uPomSteps,this.config.pomSteps),n.uniform1f(this.interiorUniforms.uDepthPower,this.config.depthPower),n.uniform1f(this.interiorUniforms.uDepthScale,this.config.depthScale),n.uniform1f(this.interiorUniforms.uDepthBias,this.config.depthBias),n.uniform1f(this.interiorUniforms.uContrastLow,this.config.contrastLow),n.uniform1f(this.interiorUniforms.uContrastHigh,this.config.contrastHigh),n.uniform1f(this.interiorUniforms.uVerticalReduction,this.config.verticalReduction),n.uniform1f(this.interiorUniforms.uDofStart,this.config.dofStart),n.uniform1f(this.interiorUniforms.uDofStrength,this.config.dofStrength),n.uniform2f(this.interiorUniforms.uImageTexelSize,1/t.videoWidth,1/t.videoHeight),n.uniform1f(this.interiorUniforms.uFogDensity,this.config.fogDensity),n.uniform3f(this.interiorUniforms.uFogColor,...this.config.fogColor),n.uniform1f(this.interiorUniforms.uColorShift,this.config.colorShift),n.uniform1f(this.interiorUniforms.uBrightnessBias,this.config.brightnessBias)),this.compositeProgram&&(n.useProgram(this.compositeProgram),n.uniform1i(this.compositeUniforms.uInteriorColor,2),n.uniform1i(this.compositeUniforms.uDistField,4),n.uniform1f(this.compositeUniforms.uEdgeOcclusionWidth,this.config.edgeOcclusionWidth),n.uniform1f(this.compositeUniforms.uEdgeOcclusionStrength,this.config.edgeOcclusionStrength)),this.chamferProgram&&(n.useProgram(this.chamferProgram),n.uniform3f(this.chamferUniforms.uLightDir3,...this.lightDir3),n.uniform3f(this.chamferUniforms.uChamferColor,...this.config.chamferColor),n.uniform1f(this.chamferUniforms.uChamferAmbient,this.config.chamferAmbient),n.uniform1f(this.chamferUniforms.uChamferSpecular,this.config.chamferSpecular),n.uniform1f(this.chamferUniforms.uChamferShininess,this.config.chamferShininess),n.uniform1i(this.chamferUniforms.uInteriorColor,2)),this.boundaryProgram&&(n.useProgram(this.boundaryProgram),n.uniform1i(this.boundaryUniforms.uInteriorColor,2),n.uniform1i(this.boundaryUniforms.uInteriorDepth,3),n.uniform1i(this.boundaryUniforms.uDistField,4),n.uniform1f(this.boundaryUniforms.uRimIntensity,this.config.rimLightIntensity),n.uniform3f(this.boundaryUniforms.uRimColor,...this.config.rimLightColor),n.uniform1f(this.boundaryUniforms.uRefractionStrength,this.config.refractionStrength),n.uniform1f(this.boundaryUniforms.uChromaticStrength,this.config.chromaticStrength),n.uniform1f(this.boundaryUniforms.uOcclusionIntensity,this.config.occlusionIntensity),n.uniform1f(this.boundaryUniforms.uEdgeThickness,this.config.edgeThickness),n.uniform1f(this.boundaryUniforms.uEdgeSpecular,this.config.edgeSpecular),n.uniform3f(this.boundaryUniforms.uEdgeColor,...this.config.edgeColor),n.uniform2f(this.boundaryUniforms.uLightDir,this.lightDirX,this.lightDirY),n.uniform1f(this.boundaryUniforms.uBevelIntensity,this.config.bevelIntensity)),this.recalculateViewportLayout())}uploadStencilMesh(t){const e=this.gl;if(!e||!this.stencilProgram)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 o=e.getAttribLocation(this.stencilProgram,"aPosition");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0);const n=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,n),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.maskProgram)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 o=e.getAttribLocation(this.maskProgram,"aPosition");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0);const n=e.createBuffer();e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,n),e.bufferData(e.ELEMENT_ARRAY_BUFFER,t.indices,e.STATIC_DRAW),e.bindVertexArray(null)}uploadBoundaryMesh(t){const e=this.gl;if(!e||!this.boundaryProgram)return;const i=de(t.edgeVertices);if(i.count===0)return;this.boundaryVao=e.createVertexArray(),e.bindVertexArray(this.boundaryVao);const o=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,o),e.bufferData(e.ARRAY_BUFFER,i.vertices,e.STATIC_DRAW);const n=16,s=e.getAttribLocation(this.boundaryProgram,"aPosition");e.enableVertexAttribArray(s),e.vertexAttribPointer(s,2,e.FLOAT,!1,n,0);const h=e.getAttribLocation(this.boundaryProgram,"aNormal");h>=0&&(e.enableVertexAttribArray(h),e.vertexAttribPointer(h,2,e.FLOAT,!1,n,8)),this.boundaryVertexCount=i.count,e.bindVertexArray(null)}uploadChamferMesh(t){const e=this.gl;if(!e||!this.chamferProgram||this.config.chamferWidth<=0)return;const i=me(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 o=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,o),e.bufferData(e.ARRAY_BUFFER,i.vertices,e.STATIC_DRAW);const n=24,s=e.getAttribLocation(this.chamferProgram,"aPosition");e.enableVertexAttribArray(s),e.vertexAttribPointer(s,2,e.FLOAT,!1,n,0);const h=e.getAttribLocation(this.chamferProgram,"aNormal3");h>=0&&(e.enableVertexAttribArray(h),e.vertexAttribPointer(h,3,e.FLOAT,!1,n,8));const a=e.getAttribLocation(this.chamferProgram,"aLerpT");a>=0&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,1,e.FLOAT,!1,n,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 o=i.checkFramebufferStatus(i.FRAMEBUFFER);o!==i.FRAMEBUFFER_COMPLETE&&console.error("Interior FBO incomplete:",o),i.bindFramebuffer(i.FRAMEBUFFER,null)}createJFAResources(t,e){const i=this.gl;if(!i)return;this.disposeJFA();const o=Math.max(1,Math.round(t/2)),n=Math.max(1,Math.round(e/2));this.jfaWidth=o,this.jfaHeight=n;const s=(a,l,u,f)=>{const c=i.createFramebuffer();return i.bindFramebuffer(i.FRAMEBUFFER,c),i.bindTexture(i.TEXTURE_2D,a),i.texStorage2D(i.TEXTURE_2D,1,l,u,f),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,a,0),i.bindFramebuffer(i.FRAMEBUFFER,null),c};this.maskTex=i.createTexture(),this.maskFbo=s(this.maskTex,i.R8,o,n);const h=this.hasColorBufferFloat?i.RG16F:i.RGBA8;this.jfaPingTex=i.createTexture(),this.jfaPingFbo=s(this.jfaPingTex,h,o,n),this.jfaPongTex=i.createTexture(),this.jfaPongFbo=s(this.jfaPongTex,h,o,n),this.distTex=i.createTexture(),this.distFbo=s(this.distTex,i.RGBA8,o,n),this.distFieldDirty=!0}computeDistanceField(){const t=this.gl;if(!t||!this.maskFbo||!this.maskVao||!this.quadVao||!this.jfaPingFbo||!this.jfaPongFbo||!this.distFbo)return;const e=this.jfaWidth,i=this.jfaHeight;if(e===0||i===0)return;t.viewport(0,0,e,i),t.disable(t.STENCIL_TEST),t.disable(t.BLEND),t.bindFramebuffer(t.FRAMEBUFFER,this.maskFbo),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.maskProgram),t.uniform2f(this.maskUniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.bindVertexArray(this.maskVao),t.drawElements(t.TRIANGLES,this.stencilIndexCount,t.UNSIGNED_SHORT,0),t.bindFramebuffer(t.FRAMEBUFFER,this.jfaPingFbo),t.clearColor(-1,-1,0,0),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.jfaSeedProgram),t.activeTexture(t.TEXTURE5),t.bindTexture(t.TEXTURE_2D,this.maskTex),t.uniform1i(this.jfaSeedUniforms.uMask,5),t.uniform2f(this.jfaSeedUniforms.uTexelSize,1/e,1/i),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4);const o=Math.max(e,i),n=[];let s=Math.ceil(o/2);for(;s>=1;)n.push(s),s=Math.floor(s/2);t.useProgram(this.jfaFloodProgram);let h=this.jfaPingTex,a=this.jfaPongFbo,l=this.jfaPongTex;for(let f=0;f<n.length;f++){const c=n[f]/Math.max(e,i);t.bindFramebuffer(t.FRAMEBUFFER,a),t.activeTexture(t.TEXTURE5),t.bindTexture(t.TEXTURE_2D,h),t.uniform1i(this.jfaFloodUniforms.uSeedTex,5),t.uniform1f(this.jfaFloodUniforms.uStepSize,c),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4);const g=h,d=a;h=l,a=d===this.jfaPongFbo?this.jfaPingFbo:this.jfaPongFbo,l=g}t.bindFramebuffer(t.FRAMEBUFFER,this.distFbo),t.clearColor(0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this.jfaDistProgram),t.activeTexture(t.TEXTURE5),t.bindTexture(t.TEXTURE_2D,h),t.uniform1i(this.jfaDistUniforms.uSeedTex,5),t.activeTexture(t.TEXTURE6),t.bindTexture(t.TEXTURE_2D,this.maskTex),t.uniform1i(this.jfaDistUniforms.uMask,6);const u=Math.max(this.config.bevelWidth,this.config.edgeOcclusionWidth);t.uniform1f(this.jfaDistUniforms.uBevelWidth,u),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.activeTexture(t.TEXTURE4),t.bindTexture(t.TEXTURE_2D,this.distTex),t.bindFramebuffer(t.FRAMEBUFFER,null),this.distFieldDirty=!1}start(t,e,i,o){this.stop(),this.playbackVideo=t,this.readDepth=e,this.readInput=i,this.onVideoFrame=o??null,this.rvfcSupported="requestVideoFrameCallback"in HTMLVideoElement.prototype,this.rvfcSupported&&(this.rvfcHandle=t.requestVideoFrameCallback(this.videoFrameLoop)),this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)}stop(){this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0),this.rvfcHandle&&this.playbackVideo&&(this.playbackVideo.cancelVideoFrameCallback(this.rvfcHandle),this.rvfcHandle=0),this.playbackVideo=null,this.readDepth=null,this.readInput=null,this.onVideoFrame=null,this.rvfcSupported=!1}dispose(){this.stop(),this.disposeTextures(),this.disposeFBO(),this.disposeJFA(),this.disposeStencilGeometry(),this.disposeBoundaryGeometry(),this.disposeChamferGeometry(),this.disposeGPUResources(),this.canvas.removeEventListener("webglcontextlost",this.handleContextLost),this.canvas.removeEventListener("webglcontextrestored",this.handleContextRestored),this.gl&&(this.gl.getExtension("WEBGL_lose_context")?.loseContext(),this.gl=null),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)}initGPUResources(){const t=this.gl;if(!t)return;this.stencilProgram=O(t,L(t,t.VERTEX_SHADER,Zt),L(t,t.FRAGMENT_SHADER,$t)),this.stencilUniforms={uMeshScale:t.getUniformLocation(this.stencilProgram,"uMeshScale")},this.maskProgram=O(t,L(t,t.VERTEX_SHADER,Jt),L(t,t.FRAGMENT_SHADER,Kt)),this.maskUniforms={uMeshScale:t.getUniformLocation(this.maskProgram,"uMeshScale")},this.jfaSeedProgram=O(t,L(t,t.VERTEX_SHADER,Qt),L(t,t.FRAGMENT_SHADER,te)),this.jfaSeedUniforms=this.getUniforms(this.jfaSeedProgram,["uMask","uTexelSize"]),this.jfaFloodProgram=O(t,L(t,t.VERTEX_SHADER,ee),L(t,t.FRAGMENT_SHADER,ie)),this.jfaFloodUniforms=this.getUniforms(this.jfaFloodProgram,["uSeedTex","uStepSize"]),this.jfaDistProgram=O(t,L(t,t.VERTEX_SHADER,re),L(t,t.FRAGMENT_SHADER,oe)),this.jfaDistUniforms=this.getUniforms(this.jfaDistProgram,["uSeedTex","uMask","uBevelWidth"]),this.interiorProgram=O(t,L(t,t.VERTEX_SHADER,ne),L(t,t.FRAGMENT_SHADER,se)),this.interiorUniforms=this.getUniforms(this.interiorProgram,["uImage","uDepth","uOffset","uStrength","uPomSteps","uDepthPower","uDepthScale","uDepthBias","uContrastLow","uContrastHigh","uVerticalReduction","uDofStart","uDofStrength","uImageTexelSize","uFogDensity","uFogColor","uColorShift","uBrightnessBias","uUvOffset","uUvScale"]),this.compositeProgram=O(t,L(t,t.VERTEX_SHADER,ae),L(t,t.FRAGMENT_SHADER,he)),this.compositeUniforms=this.getUniforms(this.compositeProgram,["uInteriorColor","uDistField","uEdgeOcclusionWidth","uEdgeOcclusionStrength"]),this.boundaryProgram=O(t,L(t,t.VERTEX_SHADER,le),L(t,t.FRAGMENT_SHADER,ce)),this.boundaryUniforms=this.getUniforms(this.boundaryProgram,["uInteriorColor","uInteriorDepth","uDistField","uRimIntensity","uRimColor","uRimWidth","uMeshScale","uRefractionStrength","uChromaticStrength","uOcclusionIntensity","uTexelSize","uEdgeThickness","uEdgeSpecular","uEdgeColor","uLightDir","uBevelIntensity"]),this.chamferProgram=O(t,L(t,t.VERTEX_SHADER,ue),L(t,t.FRAGMENT_SHADER,fe)),this.chamferUniforms=this.getUniforms(this.chamferProgram,["uMeshScale","uLightDir3","uChamferColor","uChamferAmbient","uChamferSpecular","uChamferShininess","uInteriorColor","uTexelSize"]);const e=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.quadVao=t.createVertexArray(),t.bindVertexArray(this.quadVao);const i=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW);const o=t.getAttribLocation(this.interiorProgram,"aPosition");t.enableVertexAttribArray(o),t.vertexAttribPointer(o,2,t.FLOAT,!1,0,0),t.bindVertexArray(null),t.disable(t.DEPTH_TEST)}getUniforms(t,e){const i=this.gl,o={};for(const n of e)o[n]=i.getUniformLocation(t,n);return o}videoFrameLoop=(t,e)=>{const i=this.playbackVideo;if(!i)return;this.rvfcHandle=i.requestVideoFrameCallback(this.videoFrameLoop);const o=e.mediaTime??i.currentTime;this.updateDepthTexture(o),this.onVideoFrame&&this.onVideoFrame(o,e.presentedFrames??0)};renderLoop=()=>{this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop);const t=this.gl,e=this.playbackVideo;if(!t||!this.interiorProgram||!this.quadVao||!e||e.readyState<HTMLMediaElement.HAVE_CURRENT_DATA||!this.interiorFbo||!this.interiorColorTex||!this.interiorDepthTex)return;this.distFieldDirty&&this.maskVao&&this.distFbo&&(this.computeDistanceField(),t.viewport(0,0,this.canvas.width,this.canvas.height)),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),this.rvfcSupported||this.updateDepthTexture(e.currentTime);let i=0,o=0;if(this.readInput){const n=this.readInput();i=-n.x,o=n.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.interiorProgram),t.uniform2f(this.interiorUniforms.uOffset,i,o),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.depthTexture),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.stencilProgram&&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.stencilProgram),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.distTex),t.useProgram(this.compositeProgram),t.bindVertexArray(this.quadVao),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.disable(t.STENCIL_TEST),this.chamferVao&&this.chamferProgram&&this.chamferVertexCount>0&&(t.useProgram(this.chamferProgram),t.uniform2f(this.chamferUniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform2f(this.chamferUniforms.uTexelSize,1/this.canvas.width,1/this.canvas.height),t.bindVertexArray(this.chamferVao),t.drawArrays(t.TRIANGLES,0,this.chamferVertexCount)),this.boundaryVao&&this.boundaryProgram&&this.boundaryVertexCount>0&&this.config.rimLightIntensity>0&&(t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.useProgram(this.boundaryProgram),t.bindVertexArray(this.boundaryVao),t.drawArrays(t.TRIANGLES,0,this.boundaryVertexCount),t.disable(t.BLEND))};updateDepthTexture(t){const e=this.gl;if(!e||!this.readDepth||!this.depthTexture)return;const i=this.readDepth(t);e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.depthTexture),e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.depthWidth,this.depthHeight,e.RED,e.UNSIGNED_BYTE,i)}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()},ft.RESIZE_DEBOUNCE_MS)};recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:i}=this.getViewportSize(),o=Math.min(window.devicePixelRatio,2),n=Math.round(e*o),s=Math.round(i*o);(this.canvas.width!==n||this.canvas.height!==s)&&(this.canvas.width=n,this.canvas.height=s,t.viewport(0,0,n,s)),(this.fboWidth!==n||this.fboHeight!==s)&&this.createFBO(n,s);const h=Math.max(1,Math.round(n/2)),a=Math.max(1,Math.round(s/2));(this.jfaWidth!==h||this.jfaHeight!==a)&&this.createJFAResources(n,s);const l=e/i,u=this.config.parallaxStrength+this.config.overscanPadding;let f=1,c=1;l>this.videoAspect?c=this.videoAspect/l:f=l/this.videoAspect;const g=1+u*2;f/=g,c/=g,this.uvOffset=[(1-f)/2,(1-c)/2],this.uvScale=[f,c],this.interiorProgram&&(t.useProgram(this.interiorProgram),t.uniform2f(this.interiorUniforms.uUvOffset,this.uvOffset[0],this.uvOffset[1]),t.uniform2f(this.interiorUniforms.uUvScale,this.uvScale[0],this.uvScale[1]));const d=.65;this.meshScaleX=d,this.meshScaleY=d,l>this.meshAspect?this.meshScaleX=d*(this.meshAspect/l):this.meshScaleY=d*(l/this.meshAspect),this.stencilProgram&&(t.useProgram(this.stencilProgram),t.uniform2f(this.stencilUniforms.uMeshScale,this.meshScaleX,this.meshScaleY)),this.boundaryProgram&&(t.useProgram(this.boundaryProgram),t.uniform2f(this.boundaryUniforms.uMeshScale,this.meshScaleX,this.meshScaleY),t.uniform1f(this.boundaryUniforms.uRimWidth,this.config.rimLightWidth),t.uniform2f(this.boundaryUniforms.uTexelSize,1/n,1/s)),this.chamferProgram&&(t.useProgram(this.chamferProgram),t.uniform2f(this.chamferUniforms.uMeshScale,this.meshScaleX,this.meshScaleY)),this.distFieldDirty=!0}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}}handleContextLost=t=>{t.preventDefault(),this.animationFrameHandle&&(window.cancelAnimationFrame(this.animationFrameHandle),this.animationFrameHandle=0)};handleContextRestored=()=>{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.playbackVideo&&(this.animationFrameHandle=window.requestAnimationFrame(this.renderLoop)))};disposeTextures(){const t=this.gl;t&&(this.videoTexture&&(t.deleteTexture(this.videoTexture),this.videoTexture=null),this.depthTexture&&(t.deleteTexture(this.depthTexture),this.depthTexture=null))}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)}disposeJFA(){const t=this.gl;t&&(this.maskTex&&(t.deleteTexture(this.maskTex),this.maskTex=null),this.maskFbo&&(t.deleteFramebuffer(this.maskFbo),this.maskFbo=null),this.jfaPingTex&&(t.deleteTexture(this.jfaPingTex),this.jfaPingTex=null),this.jfaPingFbo&&(t.deleteFramebuffer(this.jfaPingFbo),this.jfaPingFbo=null),this.jfaPongTex&&(t.deleteTexture(this.jfaPongTex),this.jfaPongTex=null),this.jfaPongFbo&&(t.deleteFramebuffer(this.jfaPongFbo),this.jfaPongFbo=null),this.distTex&&(t.deleteTexture(this.distTex),this.distTex=null),this.distFbo&&(t.deleteFramebuffer(this.distFbo),this.distFbo=null),this.jfaWidth=0,this.jfaHeight=0,this.distFieldDirty=!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)}disposeGPUResources(){const t=this.gl;t&&(this.stencilProgram&&(t.deleteProgram(this.stencilProgram),this.stencilProgram=null),this.maskProgram&&(t.deleteProgram(this.maskProgram),this.maskProgram=null),this.jfaSeedProgram&&(t.deleteProgram(this.jfaSeedProgram),this.jfaSeedProgram=null),this.jfaFloodProgram&&(t.deleteProgram(this.jfaFloodProgram),this.jfaFloodProgram=null),this.jfaDistProgram&&(t.deleteProgram(this.jfaDistProgram),this.jfaDistProgram=null),this.interiorProgram&&(t.deleteProgram(this.interiorProgram),this.interiorProgram=null),this.compositeProgram&&(t.deleteProgram(this.compositeProgram),this.compositeProgram=null),this.boundaryProgram&&(t.deleteProgram(this.boundaryProgram),this.boundaryProgram=null),this.chamferProgram&&(t.deleteProgram(this.chamferProgram),this.chamferProgram=null),this.quadVao&&(t.deleteVertexArray(this.quadVao),this.quadVao=null),this.stencilUniforms={},this.maskUniforms={},this.jfaSeedUniforms={},this.jfaFloodUniforms={},this.jfaDistUniforms={},this.interiorUniforms={},this.compositeUniforms={},this.boundaryUniforms={},this.chamferUniforms={})}}async function pe(r){const t=await fetch(r);if(!t.ok)throw new Error(`Failed to fetch SVG: ${t.status} ${t.statusText}`);const e=await t.text();return ge(e)}function ge(r){const i=new DOMParser().parseFromString(r,"image/svg+xml").querySelector("svg");if(!i)throw new Error("No <svg> element found in document.");const o=ve(i);if(o.length===0)throw new Error("No path data found in SVG.");let n=1/0,s=1/0,h=-1/0,a=-1/0;for(const F of o)for(let R=0;R<F.length;R+=2)n=Math.min(n,F[R]),h=Math.max(h,F[R]),s=Math.min(s,F[R+1]),a=Math.max(a,F[R+1]);const l=h-n,u=a-s,f=(n+h)/2,c=(s+a)/2,g=2/Math.max(l,u),d=l/u,m=o.map(F=>{const R=[];for(let C=0;C<F.length;C+=2)R.push((F[C]-f)*g),R.push(-((F[C+1]-c)*g));return R}),U=Re(m),y=[],E=[];for(const F of U){const{flatCoords:R,holeIndices:C}=Se(F),M=Fe(R,C),B=y.length/2;for(const I of M)E.push(I+B);for(const I of R)y.push(I)}const p=y,v=E,T=[],x=[],A=[],S=St(m);for(let F=0;F<m.length;F++){const R=m[F];x.push(T.length),A.push(S[F]);for(let C=0;C<R.length;C++)T.push(R[C]);R.length>=2&&T.push(R[0],R[1])}let D=1/0,P=1/0,_=-1/0,k=-1/0;for(let F=0;F<p.length;F+=2)D=Math.min(D,p[F]),_=Math.max(_,p[F]),P=Math.min(P,p[F+1]),k=Math.max(k,p[F+1]);return{vertices:new Float32Array(p),indices:new Uint16Array(v),edgeVertices:new Float32Array(T),contourOffsets:x,contourIsHole:A,bounds:{minX:D,maxX:_,minY:P,maxY:k},aspect:d}}function ve(r){const t=[];return r.querySelectorAll("path").forEach(a=>{const l=a.getAttribute("d");if(!l)return;const u=Ee(l);t.push(...u)}),r.querySelectorAll("polygon").forEach(a=>{const l=a.getAttribute("points");if(!l)return;const u=bt(l);u.length>=6&&t.push(u)}),r.querySelectorAll("polyline").forEach(a=>{const l=a.getAttribute("points");if(!l)return;const u=bt(l);u.length>=6&&t.push(u)}),r.querySelectorAll("rect").forEach(a=>{const l=parseFloat(a.getAttribute("x")||"0"),u=parseFloat(a.getAttribute("y")||"0"),f=parseFloat(a.getAttribute("width")||"0"),c=parseFloat(a.getAttribute("height")||"0");f>0&&c>0&&t.push([l,u,l+f,u,l+f,u+c,l,u+c])}),r.querySelectorAll("circle").forEach(a=>{const l=parseFloat(a.getAttribute("cx")||"0"),u=parseFloat(a.getAttribute("cy")||"0"),f=parseFloat(a.getAttribute("r")||"0");f>0&&t.push(xe(l,u,f))}),r.querySelectorAll("ellipse").forEach(a=>{const l=parseFloat(a.getAttribute("cx")||"0"),u=parseFloat(a.getAttribute("cy")||"0"),f=parseFloat(a.getAttribute("rx")||"0"),c=parseFloat(a.getAttribute("ry")||"0");f>0&&c>0&&t.push(Te(l,u,f,c))}),t}function bt(r){const t=[],e=r.trim().split(/[\s,]+/);for(let i=0;i<e.length-1;i+=2){const o=parseFloat(e[i]),n=parseFloat(e[i+1]);Number.isFinite(o)&&Number.isFinite(n)&&t.push(o,n)}return t}function xe(r,t,e,i=64){const o=[];for(let n=0;n<i;n++){const s=2*Math.PI*n/i;o.push(r+e*Math.cos(s),t+e*Math.sin(s))}return o}function Te(r,t,e,i,o=64){const n=[];for(let s=0;s<o;s++){const h=2*Math.PI*s/o;n.push(r+e*Math.cos(h),t+i*Math.sin(h))}return n}function Ee(r){const t=[];let e=[],i=0,o=0,n=0,s=0,h=0,a=0,l="";const u=be(r);let f=0;function c(){return f>=u.length?0:parseFloat(u[f++])}for(;f<u.length;){const g=u[f];let d;/^[a-zA-Z]$/.test(g)?(d=g,f++):d=l==="M"?"L":l==="m"?"l":l;const m=d===d.toLowerCase();switch(d.toUpperCase()){case"M":{e.length>0&&t.push(e),e=[];const y=c()+(m?i:0),E=c()+(m?o:0);i=y,o=E,n=y,s=E,e.push(i,o),h=i,a=o;break}case"L":{i=c()+(m?i:0),o=c()+(m?o:0),e.push(i,o),h=i,a=o;break}case"H":{i=c()+(m?i:0),e.push(i,o),h=i,a=o;break}case"V":{o=c()+(m?o:0),e.push(i,o),h=i,a=o;break}case"C":{const y=c()+(m?i:0),E=c()+(m?o:0),p=c()+(m?i:0),v=c()+(m?o:0),T=c()+(m?i:0),x=c()+(m?o:0);$(e,i,o,y,E,p,v,T,x),i=T,o=x,h=p,a=v;break}case"S":{const y=2*i-h,E=2*o-a,p=c()+(m?i:0),v=c()+(m?o:0),T=c()+(m?i:0),x=c()+(m?o:0);$(e,i,o,y,E,p,v,T,x),i=T,o=x,h=p,a=v;break}case"Q":{const y=c()+(m?i:0),E=c()+(m?o:0),p=c()+(m?i:0),v=c()+(m?o:0);yt(e,i,o,y,E,p,v),i=p,o=v,h=y,a=E;break}case"T":{const y=2*i-h,E=2*o-a,p=c()+(m?i:0),v=c()+(m?o:0);yt(e,i,o,y,E,p,v),i=p,o=v,h=y,a=E;break}case"A":{const y=c(),E=c(),p=c(),v=c(),T=c(),x=c()+(m?i:0),A=c()+(m?o:0);Ae(e,i,o,y,E,p,!!v,!!T,x,A),i=x,o=A,h=i,a=o;break}case"Z":{i=n,o=s,e.length>0&&t.push(e),e=[],h=i,a=o;break}default:f++;break}l=d}return e.length>=6&&t.push(e),t}function be(r){const t=[],e=/([a-zA-Z])|([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)/g;let i;for(;(i=e.exec(r))!==null;)t.push(i[0]);return t}const ye=.5;function $(r,t,e,i,o,n,s,h,a,l=0){if(l>12){r.push(h,a);return}const u=h-t,f=a-e,c=Math.sqrt(u*u+f*f);if(c<1e-6){r.push(h,a);return}const g=Math.abs((i-h)*f-(o-a)*u)/c,d=Math.abs((n-h)*f-(s-a)*u)/c;if(g+d<ye){r.push(h,a);return}const m=(t+i)/2,U=(e+o)/2,y=(i+n)/2,E=(o+s)/2,p=(n+h)/2,v=(s+a)/2,T=(m+y)/2,x=(U+E)/2,A=(y+p)/2,S=(E+v)/2,D=(T+A)/2,P=(x+S)/2;$(r,t,e,m,U,T,x,D,P,l+1),$(r,D,P,A,S,p,v,h,a,l+1)}function yt(r,t,e,i,o,n,s){const h=t+.6666666666666666*(i-t),a=e+2/3*(o-e),l=n+2/3*(i-n),u=s+2/3*(o-s);$(r,t,e,h,a,l,u,n,s)}function Ae(r,t,e,i,o,n,s,h,a,l){if(i===0||o===0){r.push(a,l);return}let u=Math.abs(i),f=Math.abs(o);const c=n*Math.PI/180,g=Math.cos(c),d=Math.sin(c),m=(t-a)/2,U=(e-l)/2,y=g*m+d*U,E=-d*m+g*U;let p=y*y/(u*u)+E*E/(f*f);if(p>1){const M=Math.sqrt(p);u*=M,f*=M,p=1}const v=u*u,T=f*f,x=y*y,A=E*E;let S=Math.max(0,(v*T-v*A-T*x)/(v*A+T*x));S=Math.sqrt(S),s===h&&(S=-S);const D=S*(u*E)/f,P=S*-(f*y)/u,_=g*D-d*P+(t+a)/2,k=d*D+g*P+(e+l)/2,F=At(1,0,(y-D)/u,(E-P)/f);let R=At((y-D)/u,(E-P)/f,(-y-D)/u,(-E-P)/f);!h&&R>0&&(R-=2*Math.PI),h&&R<0&&(R+=2*Math.PI);const C=Math.max(4,Math.ceil(Math.abs(R)/(Math.PI/16)));for(let M=1;M<=C;M++){const B=F+M/C*R,I=Math.cos(B),G=Math.sin(B),tt=g*u*I-d*f*G+_,ct=d*u*I+g*f*G+k;r.push(tt,ct)}}function At(r,t,e,i){const o=r*i-t*e<0?-1:1,n=r*e+t*i,s=Math.sqrt(r*r+t*t),h=Math.sqrt(e*e+i*i),a=n/(s*h);return o*Math.acos(Math.max(-1,Math.min(1,a)))}function Se(r){const t=[],e=[];for(let i=0;i<r.length;i++){i>0&&e.push(t.length/2);for(const o of r[i])t.push(o)}return{flatCoords:t,holeIndices:e}}function St(r){const t=r.length,e=r.map(o=>Math.abs(Rt(o))),i=new Array(t).fill(!1);for(let o=0;o<t;o++){let n=0;const s=r[o][0],h=r[o][1];for(let a=0;a<t;a++)o!==a&&e[a]>e[o]&&Ft(s,h,r[a])&&n++;i[o]=n%2===1}return i}function Re(r){if(r.length<=1)return[r];const t=St(r),e=r.map((s,h)=>{const a=Rt(s);return{index:h,contour:s,area:a,isOuter:!t[h]}}),i=e.filter(s=>s.isOuter),o=e.filter(s=>!s.isOuter);if(i.length===0)return r.map(s=>[s]);const n=i.map(s=>({outer:s.contour,holes:[]}));for(const s of o){const h=s.contour[0],a=s.contour[1];let l=-1,u=1/0;for(let f=0;f<i.length;f++)if(Ft(h,a,i[f].contour)){const c=Math.abs(i[f].area);c<u&&(u=c,l=f)}l>=0?n[l].holes.push(s.contour):n.push({outer:s.contour,holes:[]})}return n.map(s=>[s.outer,...s.holes])}function Rt(r){let t=0;const e=r.length;for(let i=0;i<e;i+=2){const o=r[i],n=r[i+1],s=r[(i+2)%e],h=r[(i+3)%e];t+=o*h-s*n}return t/2}function Ft(r,t,e){let i=!1;const o=e.length;for(let n=0,s=o-2;n<o;s=n,n+=2){const h=e[n],a=e[n+1],l=e[s],u=e[s+1];a>t!=u>t&&r<(l-h)*(t-a)/(u-a)+h&&(i=!i)}return i}function Fe(r,t,e=2){const i=t&&t.length>0,o=i?t[0]*e:r.length;let n=Dt(r,0,o,e,!0);const s=[];if(!n||n.next===n.prev)return s;i&&(n=Le(r,t,n,e));let h=1/0,a=1/0,l=-1/0,u=-1/0,f=0;if(r.length>80*e){for(let c=0;c<o;c+=e){const g=r[c],d=r[c+1];g<h&&(h=g),d<a&&(a=d),g>l&&(l=g),d>u&&(u=d)}f=Math.max(l-h,u-a),f=f!==0?32767/f:0}return J(n,s,e,h,a,f,0),s}function Dt(r,t,e,i,o){let n=null;if(o===Xe(r,t,e,i)>0)for(let s=t;s<e;s+=i)n=wt(s,r[s],r[s+1],n);else for(let s=e-i;s>=t;s-=i)n=wt(s,r[s],r[s+1],n);return n&&nt(n,n.next)&&(Q(n),n=n.next),n?(n.next.prev=n,n.prev.next=n,n.next):null}function X(r,t){t||(t=r);let e=r,i;do if(i=!1,!e.steiner&&(nt(e,e.next)||w(e.prev,e,e.next)===0)){if(Q(e),e=t=e.prev,e===e.next)break;i=!0}else e=e.next;while(i||e!==t);return t}function J(r,t,e,i,o,n,s){if(!r)return;!s&&n&&Ie(r,i,o,n);let h=r,a,l;for(;r.prev!==r.next;){if(a=r.prev,l=r.next,n?Ue(r,i,o,n):De(r)){t.push(a.i/e,r.i/e,l.i/e),Q(r),r=l.next,h=l.next;continue}if(r=l,r===h){s?s===1?(r=Pe(X(r),t,e),J(r,t,e,i,o,n,2)):s===2&&we(r,t,e,i,o,n):J(X(r),t,e,i,o,n,1);break}}}function De(r){const t=r.prev,e=r,i=r.next;if(w(t,e,i)>=0)return!1;const o=t.x,n=e.x,s=i.x,h=t.y,a=e.y,l=i.y,u=o<n?o<s?o:s:n<s?n:s,f=h<a?h<l?h:l:a<l?a:l,c=o>n?o>s?o:s:n>s?n:s,g=h>a?h>l?h:l:a>l?a:l;let d=i.next;for(;d!==t;){if(d.x>=u&&d.x<=c&&d.y>=f&&d.y<=g&&z(o,h,n,a,s,l,d.x,d.y)&&w(d.prev,d,d.next)>=0)return!1;d=d.next}return!0}function Ue(r,t,e,i){const o=r.prev,n=r,s=r.next;if(w(o,n,s)>=0)return!1;const h=o.x,a=n.x,l=s.x,u=o.y,f=n.y,c=s.y,g=h<a?h<l?h:l:a<l?a:l,d=u<f?u<c?u:c:f<c?f:c,m=h>a?h>l?h:l:a>l?a:l,U=u>f?u>c?u:c:f>c?f:c,y=dt(g,d,t,e,i),E=dt(m,U,t,e,i);let p=r.prevZ,v=r.nextZ;for(;p&&p.z>=y&&v&&v.z<=E;){if(p.x>=g&&p.x<=m&&p.y>=d&&p.y<=U&&p!==o&&p!==s&&z(h,u,a,f,l,c,p.x,p.y)&&w(p.prev,p,p.next)>=0||(p=p.prevZ,v.x>=g&&v.x<=m&&v.y>=d&&v.y<=U&&v!==o&&v!==s&&z(h,u,a,f,l,c,v.x,v.y)&&w(v.prev,v,v.next)>=0))return!1;v=v.nextZ}for(;p&&p.z>=y;){if(p.x>=g&&p.x<=m&&p.y>=d&&p.y<=U&&p!==o&&p!==s&&z(h,u,a,f,l,c,p.x,p.y)&&w(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;v&&v.z<=E;){if(v.x>=g&&v.x<=m&&v.y>=d&&v.y<=U&&v!==o&&v!==s&&z(h,u,a,f,l,c,v.x,v.y)&&w(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function Pe(r,t,e){let i=r;do{const o=i.prev,n=i.next.next;!nt(o,n)&&Ut(o,i,i.next,n)&&K(o,n)&&K(n,o)&&(t.push(o.i/e,i.i/e,n.i/e),Q(i),Q(i.next),i=r=n),i=i.next}while(i!==r);return X(i)}function we(r,t,e,i,o,n){let s=r;do{let h=s.next.next;for(;h!==s.prev;){if(s.i!==h.i&&ke(s,h)){let a=Pt(s,h);s=X(s,s.next),a=X(a,a.next),J(s,t,e,i,o,n,0),J(a,t,e,i,o,n,0);return}h=h.next}s=s.next}while(s!==r)}function Le(r,t,e,i){const o=[];for(let n=0;n<t.length;n++){const s=t[n]*i,h=n<t.length-1?t[n+1]*i:r.length,a=Dt(r,s,h,i,!1);a&&(a===a.next&&(a.steiner=!0),o.push(Oe(a)))}o.sort((n,s)=>n.x-s.x);for(const n of o)e=Ce(n,e);return e}function Ce(r,t){const e=Me(r,t);if(!e)return t;const i=Pt(e,r);return X(i,i.next),X(e,e.next)}function Me(r,t){let e=t;const i=r.x,o=r.y;let n=-1/0,s=null;do{if(o<=e.y&&o>=e.next.y&&e.next.y!==e.y){const f=e.x+(o-e.y)/(e.next.y-e.y)*(e.next.x-e.x);if(f<=i&&f>n&&(n=f,s=e.x<e.next.x?e:e.next,f===i))return s}e=e.next}while(e!==t);if(!s)return null;const h=s,a=s.x,l=s.y;let u=1/0;e=s;do{if(i>=e.x&&e.x>=a&&i!==e.x&&z(o<l?i:n,o,a,l,o<l?n:i,o,e.x,e.y)){const f=Math.abs(o-e.y)/(i-e.x);K(e,r)&&(f<u||f===u&&(e.x>s.x||_e(s,e)))&&(s=e,u=f)}e=e.next}while(e!==h);return s}function _e(r,t){return w(r.prev,r,t.prev)<0&&w(t.next,r,r.next)<0}function Ie(r,t,e,i){let o=r;do o.z===0&&(o.z=dt(o.x,o.y,t,e,i)),o.prevZ=o.prev,o.nextZ=o.next,o=o.next;while(o!==r);o.prevZ.nextZ=null,o.prevZ=null,Ve(o)}function Ve(r){let t=1,e;do{let i=r;r=null;let o=null;for(e=0;i;){e++;let n=i,s=0;for(let a=0;a<t&&(s++,n=n.nextZ,!!n);a++);let h=t;for(;s>0||h>0&&n;){let a;s!==0&&(h===0||!n||i.z<=n.z)?(a=i,i=i.nextZ,s--):(a=n,n=n.nextZ,h--),o?o.nextZ=a:r=a,a.prevZ=o,o=a}i=n}o.nextZ=null,t*=2}while(e>1);return r}function dt(r,t,e,i,o){let n=(r-e)*o|0,s=(t-i)*o|0;return n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,s=(s|s<<8)&16711935,s=(s|s<<4)&252645135,s=(s|s<<2)&858993459,s=(s|s<<1)&1431655765,n|s<<1}function Oe(r){let t=r,e=r;do(t.x<e.x||t.x===e.x&&t.y<e.y)&&(e=t),t=t.next;while(t!==r);return e}function z(r,t,e,i,o,n,s,h){return(o-s)*(t-h)-(r-s)*(n-h)>=0&&(r-s)*(i-h)-(e-s)*(t-h)>=0&&(e-s)*(n-h)-(o-s)*(i-h)>=0}function ke(r,t){return r.next.i!==t.i&&r.prev.i!==t.i&&!Be(r,t)&&(K(r,t)&&K(t,r)&&He(r,t)&&(w(r.prev,r,t.prev)!==0||w(r,t.prev,t)!==0)||nt(r,t)&&w(r.prev,r,r.next)>0&&w(t.prev,t,t.next)>0)}function w(r,t,e){return(t.y-r.y)*(e.x-t.x)-(t.x-r.x)*(e.y-t.y)}function nt(r,t){return r.x===t.x&&r.y===t.y}function Ut(r,t,e,i){const o=at(w(r,t,e)),n=at(w(r,t,i)),s=at(w(e,i,r)),h=at(w(e,i,t));return!!(o!==n&&s!==h||o===0&&st(r,e,t)||n===0&&st(r,i,t)||s===0&&st(e,r,i)||h===0&&st(e,t,i))}function st(r,t,e){return t.x<=Math.max(r.x,e.x)&&t.x>=Math.min(r.x,e.x)&&t.y<=Math.max(r.y,e.y)&&t.y>=Math.min(r.y,e.y)}function at(r){return r>0?1:r<0?-1:0}function Be(r,t){let e=r;do{if(e.i!==r.i&&e.next.i!==r.i&&e.i!==t.i&&e.next.i!==t.i&&Ut(e,e.next,r,t))return!0;e=e.next}while(e!==r);return!1}function K(r,t){return w(r.prev,r,r.next)<0?w(r,t,r.next)>=0&&w(r,r.prev,t)>=0:w(r,t,r.prev)<0||w(r,r.next,t)<0}function He(r,t){let e=r,i=!1;const o=(r.x+t.x)/2,n=(r.y+t.y)/2;do e.y>n!=e.next.y>n&&e.next.y!==e.y&&o<(e.next.x-e.x)*(n-e.y)/(e.next.y-e.y)+e.x&&(i=!i),e=e.next;while(e!==r);return i}function Pt(r,t){const e=mt(r.i,r.x,r.y),i=mt(t.i,t.x,t.y),o=r.next,n=t.prev;return r.next=t,t.prev=r,e.next=o,o.prev=e,i.next=e,e.prev=i,n.next=i,i.prev=n,i}function wt(r,t,e,i){const o=mt(r,t,e);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Q(r){r.next.prev=r.prev,r.prev.next=r.next,r.prevZ&&(r.prevZ.nextZ=r.nextZ),r.nextZ&&(r.nextZ.prevZ=r.prevZ)}function mt(r,t,e){return{i:r,x:t,y:e,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function Xe(r,t,e,i){let o=0;for(let n=t,s=e-i;n<e;n+=i)o+=(r[s]-r[n])*(r[n+1]+r[s+1]),s=n;return o}const b={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};class pt{constructor(t,e=.08,i=.06){this.host=t,this.lerpFactor=e,this.motionLerpFactor=i,this.host.addEventListener("mousemove",this.handleMouseMove),this.host.addEventListener("mouseleave",this.resetPointerTarget),this.host.addEventListener("touchstart",this.handleTouchStart,{passive:!0}),this.host.addEventListener("touchmove",this.handleTouchMove,{passive:!0}),this.host.addEventListener("touchend",this.handleTouchEnd,{passive:!0}),this.host.addEventListener("touchcancel",this.handleTouchEnd,{passive:!0})}pointerTarget={x:0,y:0};motionTarget={x:0,y:0};smoothedOutput={x:0,y:0};usingMotionInput=!1;motionListenerAttached=!1;motionRequested=!1;touchActive=!1;touchAnchorX=0;touchAnchorY=0;lerpFactor;motionLerpFactor;static TOUCH_DRAG_RANGE=100;update(){const t=this.touchActive?this.pointerTarget:this.usingMotionInput?this.motionTarget:this.pointerTarget,e=this.usingMotionInput&&!this.touchActive?this.motionLerpFactor:this.lerpFactor;return this.smoothedOutput.x=lt(this.smoothedOutput.x,t.x,e),this.smoothedOutput.y=lt(this.smoothedOutput.y,t.y,e),this.smoothedOutput}dispose(){this.host.removeEventListener("mousemove",this.handleMouseMove),this.host.removeEventListener("mouseleave",this.resetPointerTarget),this.host.removeEventListener("touchstart",this.handleTouchStart),this.host.removeEventListener("touchmove",this.handleTouchMove),this.host.removeEventListener("touchend",this.handleTouchEnd),this.host.removeEventListener("touchcancel",this.handleTouchEnd),this.motionListenerAttached&&(window.removeEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!1)}handleMouseMove=t=>{const e=this.host.getBoundingClientRect(),i=(t.clientX-e.left)/e.width*2-1,o=(t.clientY-e.top)/e.height*2-1;this.pointerTarget.x=W(i,-1,1),this.pointerTarget.y=W(o,-1,1)};resetPointerTarget=()=>{this.pointerTarget.x=0,this.pointerTarget.y=0};handleTouchStart=t=>{const e=t.touches[0];e&&(this.touchActive=!0,this.touchAnchorX=e.clientX,this.touchAnchorY=e.clientY,this.pointerTarget.x=0,this.pointerTarget.y=0,this.motionRequested||(this.motionRequested=!0,this.requestMotionPermission()))};handleTouchMove=t=>{const e=t.touches[0];if(!e)return;const i=e.clientX-this.touchAnchorX,o=e.clientY-this.touchAnchorY,n=pt.TOUCH_DRAG_RANGE;this.pointerTarget.x=W(i/n,-1,1),this.pointerTarget.y=W(o/n,-1,1)};handleTouchEnd=()=>{this.touchActive=!1,this.pointerTarget.x=0,this.pointerTarget.y=0};async requestMotionPermission(){if(typeof DeviceOrientationEvent>"u")return;const t=DeviceOrientationEvent;if(typeof t.requestPermission=="function")try{if(await t.requestPermission()!=="granted")return}catch{return}this.motionListenerAttached||(window.addEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!0),this.usingMotionInput=!0}handleDeviceOrientation=t=>{const e=W((t.gamma??0)/45,-1,1),i=W((t.beta??0)/45,-1,1);this.motionTarget.x=lt(this.motionTarget.x,e,this.motionLerpFactor),this.motionTarget.y=lt(this.motionTarget.y,i,this.motionLerpFactor)}}class ht extends HTMLElement{static TAG_NAME="layershift-portal";static get observedAttributes(){return["src","depth-src","depth-meta","logo-src","parallax-x","parallax-y","parallax-max","overscan","pom-steps","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","logo-src"];shadow;container=null;renderer=null;inputHandler=null;depthWorker=null;video=null;mesh=null;loopCount=0;lifecycle;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.lifecycle=new Et(this)}getAttrFloat(t,e){const i=this.getAttribute(t);if(i===null)return e;const o=parseFloat(i);return Number.isFinite(o)?o: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 Ne(i)}getAttrVec3(t,e){const o=(this.getAttribute(t)??e).split(",").map(s=>parseFloat(s.trim()));if(o.length>=3&&o.every(Number.isFinite))return[o[0],o[1],o[2]];const n=e.split(",").map(s=>parseFloat(s.trim()));return[n[0],n[1],n[2]]}get parallaxX(){return this.getAttrFloat("parallax-x",b.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",b.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",b.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",b.overscan)}get pomSteps(){return this.getAttrFloat("pom-steps",b.pomSteps)}get rimIntensity(){return this.getAttrFloat("rim-intensity",b.rimIntensity)}get rimWidth(){return this.getAttrFloat("rim-width",b.rimWidth)}get rimColor(){return this.getAttrColor("rim-color",b.rimColor)}get refractionStrength(){return this.getAttrFloat("refraction-strength",b.refractionStrength)}get chromaticStrength(){return this.getAttrFloat("chromatic-strength",b.chromaticStrength)}get occlusionIntensity(){return this.getAttrFloat("occlusion-intensity",b.occlusionIntensity)}get depthPower(){return this.getAttrFloat("depth-power",b.depthPower)}get depthScale(){return this.getAttrFloat("depth-scale",b.depthScale)}get depthBias(){return this.getAttrFloat("depth-bias",b.depthBias)}get fogDensity(){return this.getAttrFloat("fog-density",b.fogDensity)}get fogColor(){return this.getAttrColor("fog-color",b.fogColor)}get colorShift(){return this.getAttrFloat("color-shift",b.colorShift)}get brightnessBias(){return this.getAttrFloat("brightness-bias",b.brightnessBias)}get contrastLow(){return this.getAttrFloat("contrast-low",b.contrastLow)}get contrastHigh(){return this.getAttrFloat("contrast-high",b.contrastHigh)}get verticalReduction(){return this.getAttrFloat("vertical-reduction",b.verticalReduction)}get dofStart(){return this.getAttrFloat("dof-start",b.dofStart)}get dofStrength(){return this.getAttrFloat("dof-strength",b.dofStrength)}get bevelIntensity(){return this.getAttrFloat("bevel-intensity",b.bevelIntensity)}get bevelWidth(){return this.getAttrFloat("bevel-width",b.bevelWidth)}get bevelDarkening(){return this.getAttrFloat("bevel-darkening",b.bevelDarkening)}get bevelDesaturation(){return this.getAttrFloat("bevel-desaturation",b.bevelDesaturation)}get bevelLightAngle(){return this.getAttrFloat("bevel-light-angle",b.bevelLightAngle)}get edgeThickness(){return this.getAttrFloat("edge-thickness",b.edgeThickness)}get edgeSpecular(){return this.getAttrFloat("edge-specular",b.edgeSpecular)}get edgeColor(){return this.getAttrColor("edge-color",b.edgeColor)}get chamferWidth(){return this.getAttrFloat("chamfer-width",b.chamferWidth)}get chamferAngle(){return this.getAttrFloat("chamfer-angle",b.chamferAngle)}get chamferColor(){return this.getAttrColor("chamfer-color",b.chamferColor)}get chamferAmbient(){return this.getAttrFloat("chamfer-ambient",b.chamferAmbient)}get chamferSpecular(){return this.getAttrFloat("chamfer-specular",b.chamferSpecular)}get chamferShininess(){return this.getAttrFloat("chamfer-shininess",b.chamferShininess)}get edgeOcclusionWidth(){return this.getAttrFloat("edge-occlusion-width",b.edgeOcclusionWidth)}get edgeOcclusionStrength(){return this.getAttrFloat("edge-occlusion-strength",b.edgeOcclusionStrength)}get lightDirection3(){return this.getAttrVec3("light-direction",b.lightDirection)}get shouldAutoplay(){return this.getAttrBool("autoplay",b.autoplay)}get shouldLoop(){return this.getAttrBool("loop",b.loop)}get shouldMute(){return this.getAttrBool("muted",b.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}attachVideoEventListeners(t){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",()=>{t.loop&&(this.loopCount+=1,this.emit("layershift-portal: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=`
|
|
724
724
|
:host {
|
|
725
725
|
display: block;
|
|
726
726
|
width: 100%;
|
|
@@ -740,4 +740,4 @@ ${r}`)}return n.detachShader(i,t),n.detachShader(i,e),n.deleteShader(t),n.delete
|
|
|
740
740
|
width: 100%;
|
|
741
741
|
height: 100%;
|
|
742
742
|
}
|
|
743
|
-
`,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async
|
|
743
|
+
`,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("src"),i=this.getAttribute("depth-src"),o=this.getAttribute("depth-meta"),n=this.getAttribute("logo-src");if(this.container)try{const[s,h,a]=await Promise.all([this.createVideoElement(e),vt(i,o),pe(n)]);if(t.aborted){s.remove();return}this.video=s,this.mesh=a,this.loopCount=0,this.attachVideoEventListeners(s);const l=this.parallaxMax/Math.max(s.videoWidth,1);let u;try{const d=await it.create(h,h.meta.width,h.meta.height);this.depthWorker=d,u=m=>d.sample(m)}catch{const d=new gt(h,h.meta.width,h.meta.height);u=m=>d.sample(m)}if(t.aborted){s.remove(),this.depthWorker?.dispose(),this.depthWorker=null;return}const f={parallaxStrength:l,overscanPadding:this.overscan,pomSteps:this.pomSteps,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};this.renderer=new ft(this.container,f),this.renderer.initialize(s,h.meta.width,h.meta.height,a),this.inputHandler=new pt(this);const c=this.parallaxX,g=this.parallaxY;if(this.renderer.start(s,u,()=>{if(!this.inputHandler)return{x:0,y:0};const d=this.inputHandler.update();return{x:d.x*c,y:d.y*g}},(d,m)=>{this.emit("layershift-portal:frame",{currentTime:d,frameNumber:m})}),this.shouldAutoplay){s.currentTime=0;try{await s.play()}catch{}}if(t.aborted)return;this.lifecycle.markInitialized(),this.emit("layershift-portal:ready",{videoWidth:s.videoWidth,videoHeight:s.videoHeight,duration:s.duration})}catch(s){const h=s instanceof Error?s.message:"Failed to initialize.";console.error("<layershift-portal>: Failed to initialize.",s),this.emit("layershift-portal:error",{message:h})}}async createVideoElement(t){const e=document.createElement("video");return e.crossOrigin="anonymous",e.setAttribute("crossorigin","anonymous"),e.playsInline=!0,e.setAttribute("playsinline",""),e.setAttribute("webkit-playsinline","true"),e.muted=this.shouldMute,e.defaultMuted=this.shouldMute,this.shouldMute&&e.setAttribute("muted",""),e.loop=this.shouldLoop,e.preload="auto",e.style.display="none",e.src=t,this.shadow.appendChild(e),await new Promise((i,o)=>{if(e.readyState>=HTMLMediaElement.HAVE_METADATA){i();return}const n=()=>{h(),i()},s=()=>{h(),o(new Error("Failed to load video metadata."))},h=()=>{e.removeEventListener("loadedmetadata",n),e.removeEventListener("error",s)};e.addEventListener("loadedmetadata",n),e.addEventListener("error",s),e.load()}),e}doDispose(){this.renderer?.dispose(),this.renderer=null,this.inputHandler?.dispose(),this.inputHandler=null,this.depthWorker?.dispose(),this.depthWorker=null,this.video&&(this.video.pause(),this.video.removeAttribute("src"),this.video.load(),this.video.remove(),this.video=null),this.mesh=null,this.loopCount=0,this.container=null}}function W(r,t,e){return Math.min(e,Math.max(t,r))}function lt(r,t,e){return r+(t-r)*e}function Ne(r){const t=r.replace("#","");if(t.length===3){const e=parseInt(t[0]+t[0],16)/255,i=parseInt(t[1]+t[1],16)/255,o=parseInt(t[2]+t[2],16)/255;return[e,i,o]}if(t.length===6){const e=parseInt(t.substring(0,2),16)/255,i=parseInt(t.substring(2,4),16)/255,o=parseInt(t.substring(4,6),16)/255;return[e,i,o]}return[0,0,0]}return customElements.get(rt.TAG_NAME)||customElements.define(rt.TAG_NAME,rt),customElements.get(ht.TAG_NAME)||customElements.define(ht.TAG_NAME,ht),et.LayershiftElement=rt,et.LayershiftPortalElement=ht,Object.defineProperty(et,Symbol.toStringTag,{value:"Module"}),et})({});
|