layershift 0.1.1 → 0.1.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.
@@ -1,4 +1,4 @@
1
- var Layershift=(function(C){"use strict";var V=typeof document<"u"?document.currentScript:null;class _{worker;currentBuffer;pendingTimeSec=null;workerBusy=!1;disposed=!1;constructor(t,e){this.worker=t,this.currentBuffer=new Uint8Array(e)}static async create(t,e,r){const i=new Worker(new URL("/assets/depth-worker-CMcEa805.js",V&&V.tagName.toUpperCase()==="SCRIPT"&&V.src||new URL("layershift.js",document.baseURI).href),{type:"module"}),a=e*r,l=new _(i,a),n=t.frames.map(c=>{const h=new Uint8Array(c.length);return h.set(c),h.buffer});return await new Promise((c,h)=>{const d=setTimeout(()=>h(new Error("Worker init timeout")),1e4);i.onmessage=p=>{p.data.type==="ready"&&(clearTimeout(d),c())},i.onerror=p=>{clearTimeout(d),h(p)},i.postMessage({type:"init",frames:n,meta:{frameCount:t.meta.frameCount,fps:t.meta.fps,width:t.meta.width,height:t.meta.height},targetWidth:e,targetHeight:r},n)}),i.onmessage=c=>{if(c.data.type==="result"&&(l.currentBuffer=c.data.data,l.workerBusy=!1,l.pendingTimeSec!==null)){const h=l.pendingTimeSec;l.pendingTimeSec=null,l.requestSample(h)}},l}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 z{constructor(t,e,r){this.depthData=t,this.targetWidth=e,this.targetHeight=r;const i=t.meta.width*t.meta.height,a=e*r;this.interpolatedDepth=new Float32Array(i),this.bilateralOutput=new Float32Array(i),this.resizedDepth=new Float32Array(a),this.uint8Output=new Uint8Array(a)}interpolatedDepth;resizedDepth;bilateralOutput;uint8Output;lastFrameIndex=-1;lastNextFrameIndex=-1;lastLerpFactor=-1;sample(t){const e=S(t*this.depthData.meta.fps,0,this.depthData.meta.frameCount-1),r=Math.floor(e),i=Math.min(r+1,this.depthData.meta.frameCount-1),a=e-r,l=r!==this.lastFrameIndex||i!==this.lastNextFrameIndex,n=Math.abs(a-this.lastLerpFactor)>.001;if(!l&&!n)return this.uint8Output;this.lastFrameIndex=r,this.lastNextFrameIndex=i,this.lastLerpFactor=a;const c=1-a,h=this.depthData.frames[r],d=this.depthData.frames[i];for(let u=0;u<this.interpolatedDepth.length;u+=1)this.interpolatedDepth[u]=(h[u]*c+d[u]*a)/255;q(this.interpolatedDepth,this.depthData.meta.width,this.depthData.meta.height,this.bilateralOutput);const p=this.targetWidth!==this.depthData.meta.width||this.targetHeight!==this.depthData.meta.height;p&&W(this.bilateralOutput,this.depthData.meta.width,this.depthData.meta.height,this.targetWidth,this.targetHeight,this.resizedDepth);const s=p?this.resizedDepth:this.bilateralOutput;for(let u=0;u<this.uint8Output.length;u+=1)this.uint8Output[u]=s[u]*255+.5|0;return this.uint8Output}}async function k(o,t,e){const[r,i]=await Promise.all([X(t),B(o)]);return N(i,r)}async function X(o){const t=await fetch(o);if(!t.ok)throw new Error(`Failed to fetch depth metadata (${t.status} ${t.statusText}).`);const e=await t.json();return G(e),{frameCount:e.frameCount,fps:e.fps,width:e.width,height:e.height,sourceFps:e.sourceFps}}async function B(o,t){const e=await fetch(o);if(!e.ok)throw new Error(`Failed to fetch depth data (${e.status} ${e.statusText}).`);e.headers.get("content-length");const r=e.body;if(!r)return new Uint8Array(await e.arrayBuffer());const i=[];let a=0;const l=r.getReader();for(;;){const{done:h,value:d}=await l.read();if(h)break;d&&(i.push(d),a+=d.byteLength)}const n=new Uint8Array(a);let c=0;for(const h of i)n.set(h,c),c+=h.byteLength;return n}function N(o,t){if(o.byteLength<4)throw new Error("Depth data binary is missing the frame-count header.");const r=new DataView(o.buffer,o.byteOffset,o.byteLength).getUint32(0,!0),i=t.width*t.height,a=4+r*i;if(o.byteLength!==a)throw new Error(`Depth data byte length mismatch. Expected ${a} bytes, received ${o.byteLength}.`);if(r!==t.frameCount)throw new Error(`Depth frame count mismatch between metadata (${t.frameCount}) and binary header (${r}).`);const l=o.subarray(4),n=new Array(r);for(let c=0;c<r;c+=1){const h=c*i;n[c]=l.subarray(h,h+i)}return{meta:t,frames:n}}function G(o){if(!o||typeof o.frameCount!="number"||typeof o.fps!="number"||typeof o.width!="number"||typeof o.height!="number"||typeof o.sourceFps!="number")throw new Error("Depth metadata is malformed.");if(!Number.isFinite(o.frameCount)||!Number.isFinite(o.fps)||!Number.isFinite(o.width)||!Number.isFinite(o.height)||!Number.isFinite(o.sourceFps)||o.frameCount<=0||o.fps<=0||o.width<=0||o.height<=0||o.sourceFps<=0)throw new Error("Depth metadata contains invalid numeric values.")}function W(o,t,e,r,i,a){const l=t/r,n=e/i;for(let c=0;c<i;c+=1){const h=(c+.5)*n-.5,d=S(Math.floor(h),0,e-1),p=S(d+1,0,e-1),s=h-d;for(let u=0;u<r;u+=1){const m=(u+.5)*l-.5,v=S(Math.floor(m),0,t-1),x=S(v+1,0,t-1),b=m-v,E=o[d*t+v],y=o[d*t+x],P=o[p*t+v],f=o[p*t+x],w=E+(y-E)*b,M=P+(f-P)*b;a[c*r+u]=w+(M-w)*s}}}function q(o,t,e,r){for(let l=0;l<e;l+=1)for(let n=0;n<t;n+=1){const c=l*t+n,h=o[c];let d=1,p=h;for(let s=-2;s<=2;s+=1){const u=l+s;if(!(u<0||u>=e))for(let m=-2;m<=2;m+=1){if(m===0&&s===0)continue;const v=n+m;if(v<0||v>=t)continue;const x=o[u*t+v],b=m*m+s*s,E=x-h,y=Math.exp(-b/2.25-E*E/.01);d+=y,p+=x*y}}r[c]=p/d}}function S(o,t,e){return Math.min(e,Math.max(t,o))}const Y={parallaxStrength:.05,contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4,pomSteps:16,overscanPadding:.08};function $(o,t,e){const r=new Float32Array(256);if(o.length===0||t<=0||e<=0)return I(r);const i=K(o.length),a=t*e;let l=0;const n=new Uint32Array(256);for(const f of i){const w=o[f],M=Math.min(w.length,a);for(let O=0;O<M;O+=1)n[w[O]]+=1;l+=M}if(l===0)return I(r);const c=1/l;for(let f=0;f<256;f+=1)r[f]=n[f]*c;const h=new Float32Array(256);h[0]=r[0];for(let f=1;f<256;f+=1)h[f]=h[f-1]+r[f];const d=D(h,.05),p=D(h,.25),s=D(h,.5),u=D(h,.75),m=D(h,.95);let v=0;for(let f=0;f<256;f+=1)v+=f/255*r[f];let x=0;for(let f=0;f<256;f+=1){const w=f/255-v;x+=r[f]*w*w}const b=Math.sqrt(x),E=m-d,y=u-p,P=Z(r);return{mean:v,stdDev:b,p5:d,p25:p,median:s,p75:u,p95:m,effectiveRange:E,iqr:y,bimodality:P,histogram:r}}function j(o){if(o.effectiveRange<.05||o.stdDev<.02)return{...Y};const t=o.effectiveRange-.5,e=o.bimodality-.4,r=g(.05-t*.03+e*.01,.035,.065),i=g(o.p5-.03,0,.25),a=g(o.p95+.03,.75,1),l=g((r-.03)/.05,0,1),n=g(.6-l*.25,.35,.6),c=g(.6-t*.2,.5,.7),h=g(.4+t*.2,.25,.5),d=16,p=g(r+.03,.06,.1);return{parallaxStrength:r,contrastLow:i,contrastHigh:a,verticalReduction:n,dofStart:c,dofStrength:h,pomSteps:d,overscanPadding:p}}function K(o){if(o<=0)return[];if(o===1)return[0];const t=o-1,e=[0,Math.floor(o/4),Math.floor(o/2),Math.floor(3*o/4),t],r=new Set,i=[];for(const a of e)r.has(a)||(r.add(a),i.push(a));return i}function D(o,t){for(let e=0;e<256;e+=1)if(o[e]>=t)return e/255;return 1}function Z(o){const t=new Float32Array(256);for(let s=0;s<256;s+=1){let u=0,m=0;for(let v=s-2;v<=s+2;v+=1)v>=0&&v<256&&(u+=o[v],m+=1);t[s]=u/m}let e=0;for(let s=0;s<256;s+=1)e+=t[s];e/=256;const r=e*2,i=25,a=[];for(let s=1;s<255;s+=1)t[s]>t[s-1]&&t[s]>t[s+1]&&t[s]>=r&&a.push({bin:s,height:t[s]});if(t[0]>t[1]&&t[0]>=r&&a.push({bin:0,height:t[0]}),t[255]>t[254]&&t[255]>=r&&a.push({bin:255,height:t[255]}),a.sort((s,u)=>u.height-s.height),a.length<2)return 0;const l=a[0];let n=null;for(let s=1;s<a.length;s+=1)if(Math.abs(a[s].bin-l.bin)>=i){n=a[s];break}if(!n)return 0;const c=Math.min(l.bin,n.bin),h=Math.max(l.bin,n.bin);let d=1/0;for(let s=c;s<=h;s+=1)t[s]<d&&(d=t[s]);const p=Math.min(l.height,n.height);return p<=0?0:g(1-d/p,0,1)}function I(o){return{mean:0,stdDev:0,p5:0,p25:0,median:0,p75:0,p95:0,effectiveRange:0,iqr:0,bimodality:0,histogram:o}}function g(o,t,e){return Math.min(e,Math.max(t,o))}const J=`#version 300 es
1
+ var Layershift=(function(C){"use strict";var _=typeof document<"u"?document.currentScript:null;class V{worker;currentBuffer;pendingTimeSec=null;workerBusy=!1;disposed=!1;constructor(t,e){this.worker=t,this.currentBuffer=new Uint8Array(e)}static async create(t,e,r){const i=new Worker(new URL("/assets/depth-worker-CMcEa805.js",_&&_.tagName.toUpperCase()==="SCRIPT"&&_.src||new URL("layershift.js",document.baseURI).href),{type:"module"}),a=e*r,c=new V(i,a),n=t.frames.map(l=>{const h=new Uint8Array(l.length);return h.set(l),h.buffer});return await new Promise((l,h)=>{const d=setTimeout(()=>h(new Error("Worker init timeout")),1e4);i.onmessage=p=>{p.data.type==="ready"&&(clearTimeout(d),l())},i.onerror=p=>{clearTimeout(d),h(p)},i.postMessage({type:"init",frames:n,meta:{frameCount:t.meta.frameCount,fps:t.meta.fps,width:t.meta.width,height:t.meta.height},targetWidth:e,targetHeight:r},n)}),i.onmessage=l=>{if(l.data.type==="result"&&(c.currentBuffer=l.data.data,c.workerBusy=!1,c.pendingTimeSec!==null)){const h=c.pendingTimeSec;c.pendingTimeSec=null,c.requestSample(h)}},c}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 k{constructor(t,e,r){this.depthData=t,this.targetWidth=e,this.targetHeight=r;const i=t.meta.width*t.meta.height,a=e*r;this.interpolatedDepth=new Float32Array(i),this.bilateralOutput=new Float32Array(i),this.resizedDepth=new Float32Array(a),this.uint8Output=new Uint8Array(a)}interpolatedDepth;resizedDepth;bilateralOutput;uint8Output;lastFrameIndex=-1;lastNextFrameIndex=-1;lastLerpFactor=-1;sample(t){const e=D(t*this.depthData.meta.fps,0,this.depthData.meta.frameCount-1),r=Math.floor(e),i=Math.min(r+1,this.depthData.meta.frameCount-1),a=e-r,c=r!==this.lastFrameIndex||i!==this.lastNextFrameIndex,n=Math.abs(a-this.lastLerpFactor)>.001;if(!c&&!n)return this.uint8Output;this.lastFrameIndex=r,this.lastNextFrameIndex=i,this.lastLerpFactor=a;const l=1-a,h=this.depthData.frames[r],d=this.depthData.frames[i];for(let u=0;u<this.interpolatedDepth.length;u+=1)this.interpolatedDepth[u]=(h[u]*l+d[u]*a)/255;Y(this.interpolatedDepth,this.depthData.meta.width,this.depthData.meta.height,this.bilateralOutput);const p=this.targetWidth!==this.depthData.meta.width||this.targetHeight!==this.depthData.meta.height;p&&q(this.bilateralOutput,this.depthData.meta.width,this.depthData.meta.height,this.targetWidth,this.targetHeight,this.resizedDepth);const s=p?this.resizedDepth:this.bilateralOutput;for(let u=0;u<this.uint8Output.length;u+=1)this.uint8Output[u]=s[u]*255+.5|0;return this.uint8Output}}async function X(o,t,e){const[r,i]=await Promise.all([B(t),N(o)]);return G(i,r)}async function B(o){const t=await fetch(o);if(!t.ok)throw new Error(`Failed to fetch depth metadata (${t.status} ${t.statusText}).`);const e=await t.json();return W(e),{frameCount:e.frameCount,fps:e.fps,width:e.width,height:e.height,sourceFps:e.sourceFps}}async function N(o,t){const e=await fetch(o);if(!e.ok)throw new Error(`Failed to fetch depth data (${e.status} ${e.statusText}).`);e.headers.get("content-length");const r=e.body;if(!r)return new Uint8Array(await e.arrayBuffer());const i=[];let a=0;const c=r.getReader();for(;;){const{done:h,value:d}=await c.read();if(h)break;d&&(i.push(d),a+=d.byteLength)}const n=new Uint8Array(a);let l=0;for(const h of i)n.set(h,l),l+=h.byteLength;return n}function G(o,t){if(o.byteLength<4)throw new Error("Depth data binary is missing the frame-count header.");const r=new DataView(o.buffer,o.byteOffset,o.byteLength).getUint32(0,!0),i=t.width*t.height,a=4+r*i;if(o.byteLength!==a)throw new Error(`Depth data byte length mismatch. Expected ${a} bytes, received ${o.byteLength}.`);if(r!==t.frameCount)throw new Error(`Depth frame count mismatch between metadata (${t.frameCount}) and binary header (${r}).`);const c=o.subarray(4),n=new Array(r);for(let l=0;l<r;l+=1){const h=l*i;n[l]=c.subarray(h,h+i)}return{meta:t,frames:n}}function W(o){if(!o||typeof o.frameCount!="number"||typeof o.fps!="number"||typeof o.width!="number"||typeof o.height!="number"||typeof o.sourceFps!="number")throw new Error("Depth metadata is malformed.");if(!Number.isFinite(o.frameCount)||!Number.isFinite(o.fps)||!Number.isFinite(o.width)||!Number.isFinite(o.height)||!Number.isFinite(o.sourceFps)||o.frameCount<=0||o.fps<=0||o.width<=0||o.height<=0||o.sourceFps<=0)throw new Error("Depth metadata contains invalid numeric values.")}function q(o,t,e,r,i,a){const c=t/r,n=e/i;for(let l=0;l<i;l+=1){const h=(l+.5)*n-.5,d=D(Math.floor(h),0,e-1),p=D(d+1,0,e-1),s=h-d;for(let u=0;u<r;u+=1){const m=(u+.5)*c-.5,v=D(Math.floor(m),0,t-1),T=D(v+1,0,t-1),b=m-v,E=o[d*t+v],S=o[d*t+T],F=o[p*t+v],f=o[p*t+T],x=E+(S-E)*b,M=F+(f-F)*b;a[l*r+u]=x+(M-x)*s}}}function Y(o,t,e,r){for(let c=0;c<e;c+=1)for(let n=0;n<t;n+=1){const l=c*t+n,h=o[l];let d=1,p=h;for(let s=-2;s<=2;s+=1){const u=c+s;if(!(u<0||u>=e))for(let m=-2;m<=2;m+=1){if(m===0&&s===0)continue;const v=n+m;if(v<0||v>=t)continue;const T=o[u*t+v],b=m*m+s*s,E=T-h,S=Math.exp(-b/2.25-E*E/.01);d+=S,p+=T*S}}r[l]=p/d}}function D(o,t,e){return Math.min(e,Math.max(t,o))}const $={parallaxStrength:.05,contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4,pomSteps:16,overscanPadding:.08};function j(o,t,e){const r=new Float32Array(256);if(o.length===0||t<=0||e<=0)return H(r);const i=Z(o.length),a=t*e;let c=0;const n=new Uint32Array(256);for(const f of i){const x=o[f],M=Math.min(x.length,a);for(let I=0;I<M;I+=1)n[x[I]]+=1;c+=M}if(c===0)return H(r);const l=1/c;for(let f=0;f<256;f+=1)r[f]=n[f]*l;const h=new Float32Array(256);h[0]=r[0];for(let f=1;f<256;f+=1)h[f]=h[f-1]+r[f];const d=A(h,.05),p=A(h,.25),s=A(h,.5),u=A(h,.75),m=A(h,.95);let v=0;for(let f=0;f<256;f+=1)v+=f/255*r[f];let T=0;for(let f=0;f<256;f+=1){const x=f/255-v;T+=r[f]*x*x}const b=Math.sqrt(T),E=m-d,S=u-p,F=J(r);return{mean:v,stdDev:b,p5:d,p25:p,median:s,p75:u,p95:m,effectiveRange:E,iqr:S,bimodality:F,histogram:r}}function K(o){if(o.effectiveRange<.05||o.stdDev<.02)return{...$};const t=o.effectiveRange-.5,e=o.bimodality-.4,r=g(.05-t*.03+e*.01,.035,.065),i=g(o.p5-.03,0,.25),a=g(o.p95+.03,.75,1),c=g((r-.03)/.05,0,1),n=g(.6-c*.25,.35,.6),l=g(.6-t*.2,.5,.7),h=g(.4+t*.2,.25,.5),d=16,p=g(r+.03,.06,.1);return{parallaxStrength:r,contrastLow:i,contrastHigh:a,verticalReduction:n,dofStart:l,dofStrength:h,pomSteps:d,overscanPadding:p}}function Z(o){if(o<=0)return[];if(o===1)return[0];const t=o-1,e=[0,Math.floor(o/4),Math.floor(o/2),Math.floor(3*o/4),t],r=new Set,i=[];for(const a of e)r.has(a)||(r.add(a),i.push(a));return i}function A(o,t){for(let e=0;e<256;e+=1)if(o[e]>=t)return e/255;return 1}function J(o){const t=new Float32Array(256);for(let s=0;s<256;s+=1){let u=0,m=0;for(let v=s-2;v<=s+2;v+=1)v>=0&&v<256&&(u+=o[v],m+=1);t[s]=u/m}let e=0;for(let s=0;s<256;s+=1)e+=t[s];e/=256;const r=e*2,i=25,a=[];for(let s=1;s<255;s+=1)t[s]>t[s-1]&&t[s]>t[s+1]&&t[s]>=r&&a.push({bin:s,height:t[s]});if(t[0]>t[1]&&t[0]>=r&&a.push({bin:0,height:t[0]}),t[255]>t[254]&&t[255]>=r&&a.push({bin:255,height:t[255]}),a.sort((s,u)=>u.height-s.height),a.length<2)return 0;const c=a[0];let n=null;for(let s=1;s<a.length;s+=1)if(Math.abs(a[s].bin-c.bin)>=i){n=a[s];break}if(!n)return 0;const l=Math.min(c.bin,n.bin),h=Math.max(c.bin,n.bin);let d=1/0;for(let s=l;s<=h;s+=1)t[s]<d&&(d=t[s]);const p=Math.min(c.height,n.height);return p<=0?0:g(1-d/p,0,1)}function H(o){return{mean:0,stdDev:0,p5:0,p25:0,median:0,p75:0,p95:0,effectiveRange:0,iqr:0,bimodality:0,histogram:o}}function g(o,t,e){return Math.min(e,Math.max(t,o))}const Q=`#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(C){"use strict";var V=typeof document<"u"?document.curr
19
19
  vScreenUv = baseUv;
20
20
  gl_Position = vec4(aPosition, 0.0, 1.0);
21
21
  }
22
- `,Q=`#version 300 es
22
+ `,tt=`#version 300 es
23
23
  precision highp float;
24
24
 
25
25
  // ---- Uniforms ----
@@ -187,10 +187,10 @@ var Layershift=(function(C){"use strict";var V=typeof document<"u"?document.curr
187
187
 
188
188
  fragColor = color;
189
189
  }
190
- `,L={contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4};function H(o,t,e){const r=o.createShader(t);if(!r)throw new Error("Failed to create shader.");if(o.shaderSource(r,e),o.compileShader(r),!o.getShaderParameter(r,o.COMPILE_STATUS)){const i=o.getShaderInfoLog(r)??"";throw o.deleteShader(r),new Error(`Shader compilation failed:
191
- ${i}`)}return r}function tt(o,t,e){const r=o.createProgram();if(!r)throw new Error("Failed to create program.");if(o.attachShader(r,t),o.attachShader(r,e),o.linkProgram(r),!o.getProgramParameter(r,o.LINK_STATUS)){const i=o.getProgramInfoLog(r)??"";throw o.deleteProgram(r),new Error(`Program linking failed:
192
- ${i}`)}return o.detachShader(r,t),o.detachShader(r,e),o.deleteShader(t),o.deleteShader(e),r}function et(o,t){return{uImage:o.getUniformLocation(t,"uImage"),uDepth:o.getUniformLocation(t,"uDepth"),uOffset:o.getUniformLocation(t,"uOffset"),uStrength:o.getUniformLocation(t,"uStrength"),uPomEnabled:o.getUniformLocation(t,"uPomEnabled"),uPomSteps:o.getUniformLocation(t,"uPomSteps"),uContrastLow:o.getUniformLocation(t,"uContrastLow"),uContrastHigh:o.getUniformLocation(t,"uContrastHigh"),uVerticalReduction:o.getUniformLocation(t,"uVerticalReduction"),uDofStart:o.getUniformLocation(t,"uDofStart"),uDofStrength:o.getUniformLocation(t,"uDofStrength"),uImageTexelSize:o.getUniformLocation(t,"uImageTexelSize"),uUvOffset:o.getUniformLocation(t,"uUvOffset"),uUvScale:o.getUniformLocation(t,"uUvScale")}}class A{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??L.contrastLow,contrastHigh:e.contrastHigh??L.contrastHigh,verticalReduction:e.verticalReduction??L.verticalReduction,dofStart:e.dofStart??L.dofStart,dofStrength:e.dofStrength??L.dofStrength},this.canvas=document.createElement("canvas");const r=this.canvas.getContext("webgl2",{antialias:!1,alpha:!1,desynchronized:!0,powerPreference:"high-performance"});if(!r)throw new Error("WebGL 2 is not supported.");this.gl=r,"drawingBufferColorSpace"in r&&(r.drawingBufferColorSpace="srgb"),r.clearColor(0,0,0,1),r.pixelStorei(r.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,r){const i=this.gl;i&&(this.disposeTextures(),this.videoAspect=t.videoWidth/t.videoHeight,this.depthWidth=e,this.depthHeight=r,this.videoTexture=i.createTexture(),i.activeTexture(i.TEXTURE0),i.bindTexture(i.TEXTURE_2D,this.videoTexture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),this.depthTexture=i.createTexture(),i.activeTexture(i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,this.depthTexture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.texStorage2D(i.TEXTURE_2D,1,i.R8,e,r),this.program&&this.uniforms&&(i.useProgram(this.program),i.uniform1i(this.uniforms.uImage,0),i.uniform1i(this.uniforms.uDepth,1),i.uniform1f(this.uniforms.uStrength,this.config.parallaxStrength),i.uniform1i(this.uniforms.uPomEnabled,this.config.pomEnabled?1:0),i.uniform1i(this.uniforms.uPomSteps,this.config.pomSteps),i.uniform1f(this.uniforms.uContrastLow,this.config.contrastLow),i.uniform1f(this.uniforms.uContrastHigh,this.config.contrastHigh),i.uniform1f(this.uniforms.uVerticalReduction,this.config.verticalReduction),i.uniform1f(this.uniforms.uDofStart,this.config.dofStart),i.uniform1f(this.uniforms.uDofStrength,this.config.dofStrength),i.uniform2f(this.uniforms.uImageTexelSize,1/t.videoWidth,1/t.videoHeight)),this.recalculateViewportLayout())}start(t,e,r,i){this.stop(),this.playbackVideo=t,this.readDepth=e,this.readInput=r,this.onVideoFrame=i??null,this.rvfcSupported=A.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.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=Q.replace("#version 300 es",`#version 300 es
193
- #define MAX_POM_STEPS ${A.MAX_POM_STEPS}`),r=H(t,t.VERTEX_SHADER,J),i=H(t,t.FRAGMENT_SHADER,e);this.program=tt(t,r,i),this.uniforms=et(t,this.program);const a=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.vao=t.createVertexArray(),t.bindVertexArray(this.vao);const l=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,l),t.bufferData(t.ARRAY_BUFFER,a,t.STATIC_DRAW);const n=t.getAttribLocation(this.program,"aPosition");t.enableVertexAttribArray(n),t.vertexAttribPointer(n,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 r=this.playbackVideo;if(!r)return;this.rvfcHandle=r.requestVideoFrameCallback(this.videoFrameLoop);const i=e.mediaTime??r.currentTime;this.updateDepthTexture(i),this.onVideoFrame&&this.onVideoFrame(i,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 r=this.readInput();t.uniform2f(this.uniforms.uOffset,-r.x,r.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 r=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,r)}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()},A.RESIZE_DEBOUNCE_MS)};recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:r}=this.getViewportSize(),i=Math.min(window.devicePixelRatio,2),a=Math.round(e*i),l=Math.round(r*i);(this.canvas.width!==a||this.canvas.height!==l)&&(this.canvas.width=a,this.canvas.height=l,t.viewport(0,0,a,l));const n=e/r,c=this.config.parallaxStrength+this.config.overscanPadding;let h=1,d=1;n>this.videoAspect?d=this.videoAspect/n:h=n/this.videoAspect;const p=1+c*2;h/=p,d/=p,this.uvOffset=[(1-h)/2,(1-d)/2],this.uvScale=[h,d],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 T={parallaxX:.4,parallaxY:1,parallaxMax:30,overscan:.05,autoplay:!0,loop:!0,muted:!0};class it{constructor(t,e=.08,r=.06){this.host=t,this.lerpFactor=e,this.motionLerpFactor=r,this.host.addEventListener("mousemove",this.handleMouseMove),this.host.addEventListener("mouseleave",this.resetPointerTarget),this.host.addEventListener("touchstart",this.handleFirstTouch,{once:!0})}pointerTarget={x:0,y:0};motionTarget={x:0,y:0};smoothedOutput={x:0,y:0};usingMotionInput=!1;motionListenerAttached=!1;motionRequested=!1;lerpFactor;motionLerpFactor;update(){const t=this.usingMotionInput?this.motionTarget:this.pointerTarget,e=this.usingMotionInput?this.motionLerpFactor:this.lerpFactor;return this.smoothedOutput.x=F(this.smoothedOutput.x,t.x,e),this.smoothedOutput.y=F(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.handleFirstTouch),this.motionListenerAttached&&(window.removeEventListener("deviceorientation",this.handleDeviceOrientation),this.motionListenerAttached=!1)}handleMouseMove=t=>{const e=this.host.getBoundingClientRect(),r=(t.clientX-e.left)/e.width*2-1,i=(t.clientY-e.top)/e.height*2-1;this.pointerTarget.x=U(r,-1,1),this.pointerTarget.y=U(i,-1,1)};resetPointerTarget=()=>{this.pointerTarget.x=0,this.pointerTarget.y=0};handleFirstTouch=async()=>{if(this.motionRequested||(this.motionRequested=!0,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=U((t.gamma??0)/45,-1,1),r=U((t.beta??0)/45,-1,1);this.motionTarget.x=F(this.motionTarget.x,e,this.motionLerpFactor),this.motionTarget.y=F(this.motionTarget.y,r,this.motionLerpFactor)}}class R 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 r=this.getAttribute(t);if(r===null)return e;const i=parseFloat(r);return Number.isFinite(i)?i:e}getAttrBool(t,e){if(!this.hasAttribute(t))return e;const r=this.getAttribute(t);return!(r==="false"||r==="0")}get parallaxX(){return this.getAttrFloat("parallax-x",T.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",T.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",T.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",T.overscan)}get shouldAutoplay(){return this.getAttrBool("autoplay",T.autoplay)}get shouldLoop(){return this.getAttrBool("loop",T.loop)}get shouldMute(){return this.getAttrBool("muted",T.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,r){["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
+ `,L={contrastLow:.05,contrastHigh:.95,verticalReduction:.5,dofStart:.6,dofStrength:.4};function z(o,t,e){const r=o.createShader(t);if(!r)throw new Error("Failed to create shader.");if(o.shaderSource(r,e),o.compileShader(r),!o.getShaderParameter(r,o.COMPILE_STATUS)){const i=o.getShaderInfoLog(r)??"";throw o.deleteShader(r),new Error(`Shader compilation failed:
191
+ ${i}`)}return r}function et(o,t,e){const r=o.createProgram();if(!r)throw new Error("Failed to create program.");if(o.attachShader(r,t),o.attachShader(r,e),o.linkProgram(r),!o.getProgramParameter(r,o.LINK_STATUS)){const i=o.getProgramInfoLog(r)??"";throw o.deleteProgram(r),new Error(`Program linking failed:
192
+ ${i}`)}return o.detachShader(r,t),o.detachShader(r,e),o.deleteShader(t),o.deleteShader(e),r}function it(o,t){return{uImage:o.getUniformLocation(t,"uImage"),uDepth:o.getUniformLocation(t,"uDepth"),uOffset:o.getUniformLocation(t,"uOffset"),uStrength:o.getUniformLocation(t,"uStrength"),uPomEnabled:o.getUniformLocation(t,"uPomEnabled"),uPomSteps:o.getUniformLocation(t,"uPomSteps"),uContrastLow:o.getUniformLocation(t,"uContrastLow"),uContrastHigh:o.getUniformLocation(t,"uContrastHigh"),uVerticalReduction:o.getUniformLocation(t,"uVerticalReduction"),uDofStart:o.getUniformLocation(t,"uDofStart"),uDofStrength:o.getUniformLocation(t,"uDofStrength"),uImageTexelSize:o.getUniformLocation(t,"uImageTexelSize"),uUvOffset:o.getUniformLocation(t,"uUvOffset"),uUvScale:o.getUniformLocation(t,"uUvScale")}}class R{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??L.contrastLow,contrastHigh:e.contrastHigh??L.contrastHigh,verticalReduction:e.verticalReduction??L.verticalReduction,dofStart:e.dofStart??L.dofStart,dofStrength:e.dofStrength??L.dofStrength},this.canvas=document.createElement("canvas");const r=this.canvas.getContext("webgl2",{antialias:!1,alpha:!1,desynchronized:!0,powerPreference:"high-performance"});if(!r)throw new Error("WebGL 2 is not supported.");this.gl=r,"drawingBufferColorSpace"in r&&(r.drawingBufferColorSpace="srgb"),r.clearColor(0,0,0,1),r.pixelStorei(r.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,r){const i=this.gl;i&&(this.disposeTextures(),this.videoAspect=t.videoWidth/t.videoHeight,this.depthWidth=e,this.depthHeight=r,this.videoTexture=i.createTexture(),i.activeTexture(i.TEXTURE0),i.bindTexture(i.TEXTURE_2D,this.videoTexture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),this.depthTexture=i.createTexture(),i.activeTexture(i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,this.depthTexture),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.LINEAR),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_S,i.CLAMP_TO_EDGE),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_WRAP_T,i.CLAMP_TO_EDGE),i.texStorage2D(i.TEXTURE_2D,1,i.R8,e,r),this.program&&this.uniforms&&(i.useProgram(this.program),i.uniform1i(this.uniforms.uImage,0),i.uniform1i(this.uniforms.uDepth,1),i.uniform1f(this.uniforms.uStrength,this.config.parallaxStrength),i.uniform1i(this.uniforms.uPomEnabled,this.config.pomEnabled?1:0),i.uniform1i(this.uniforms.uPomSteps,this.config.pomSteps),i.uniform1f(this.uniforms.uContrastLow,this.config.contrastLow),i.uniform1f(this.uniforms.uContrastHigh,this.config.contrastHigh),i.uniform1f(this.uniforms.uVerticalReduction,this.config.verticalReduction),i.uniform1f(this.uniforms.uDofStart,this.config.dofStart),i.uniform1f(this.uniforms.uDofStrength,this.config.dofStrength),i.uniform2f(this.uniforms.uImageTexelSize,1/t.videoWidth,1/t.videoHeight)),this.recalculateViewportLayout())}start(t,e,r,i){this.stop(),this.playbackVideo=t,this.readDepth=e,this.readInput=r,this.onVideoFrame=i??null,this.rvfcSupported=R.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.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=tt.replace("#version 300 es",`#version 300 es
193
+ #define MAX_POM_STEPS ${R.MAX_POM_STEPS}`),r=z(t,t.VERTEX_SHADER,Q),i=z(t,t.FRAGMENT_SHADER,e);this.program=et(t,r,i),this.uniforms=it(t,this.program);const a=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.vao=t.createVertexArray(),t.bindVertexArray(this.vao);const c=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,c),t.bufferData(t.ARRAY_BUFFER,a,t.STATIC_DRAW);const n=t.getAttribLocation(this.program,"aPosition");t.enableVertexAttribArray(n),t.vertexAttribPointer(n,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 r=this.playbackVideo;if(!r)return;this.rvfcHandle=r.requestVideoFrameCallback(this.videoFrameLoop);const i=e.mediaTime??r.currentTime;this.updateDepthTexture(i),this.onVideoFrame&&this.onVideoFrame(i,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 r=this.readInput();t.uniform2f(this.uniforms.uOffset,-r.x,r.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 r=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,r)}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()},R.RESIZE_DEBOUNCE_MS)};recalculateViewportLayout(){const t=this.gl;if(!t)return;const{width:e,height:r}=this.getViewportSize(),i=Math.min(window.devicePixelRatio,2),a=Math.round(e*i),c=Math.round(r*i);(this.canvas.width!==a||this.canvas.height!==c)&&(this.canvas.width=a,this.canvas.height=c,t.viewport(0,0,a,c));const n=e/r,l=this.config.parallaxStrength+this.config.overscanPadding;let h=1,d=1;n>this.videoAspect?d=this.videoAspect/n:h=n/this.videoAspect;const p=1+l*2;h/=p,d/=p,this.uvOffset=[(1-h)/2,(1-d)/2],this.uvScale=[h,d],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 w={parallaxX:.4,parallaxY:1,parallaxMax:30,overscan:.05,autoplay:!0,loop:!0,muted:!0};class O{constructor(t,e=.08,r=.06){this.host=t,this.lerpFactor=e,this.motionLerpFactor=r,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=P(this.smoothedOutput.x,t.x,e),this.smoothedOutput.y=P(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(),r=(t.clientX-e.left)/e.width*2-1,i=(t.clientY-e.top)/e.height*2-1;this.pointerTarget.x=y(r,-1,1),this.pointerTarget.y=y(i,-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 r=e.clientX-this.touchAnchorX,i=e.clientY-this.touchAnchorY,a=O.TOUCH_DRAG_RANGE;this.pointerTarget.x=y(r/a,-1,1),this.pointerTarget.y=y(i/a,-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=y((t.gamma??0)/45,-1,1),r=y((t.beta??0)/45,-1,1);this.motionTarget.x=P(this.motionTarget.x,e,this.motionLerpFactor),this.motionTarget.y=P(this.motionTarget.y,r,this.motionLerpFactor)}}class U 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 r=this.getAttribute(t);if(r===null)return e;const i=parseFloat(r);return Number.isFinite(i)?i:e}getAttrBool(t,e){if(!this.hasAttribute(t))return e;const r=this.getAttribute(t);return!(r==="false"||r==="0")}get parallaxX(){return this.getAttrFloat("parallax-x",w.parallaxX)}get parallaxY(){return this.getAttrFloat("parallax-y",w.parallaxY)}get parallaxMax(){return this.getAttrFloat("parallax-max",w.parallaxMax)}get overscan(){return this.getAttrFloat("overscan",w.overscan)}get shouldAutoplay(){return this.getAttrBool("autoplay",w.autoplay)}get shouldLoop(){return this.getAttrBool("loop",w.loop)}get shouldMute(){return this.getAttrBool("muted",w.muted)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}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,r){["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=`
194
194
  :host {
195
195
  display: block;
196
196
  width: 100%;
@@ -210,4 +210,4 @@ ${i}`)}return o.detachShader(r,t),o.detachShader(r,e),o.deleteShader(t),o.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 init(){const t=this.getAttribute("src"),e=this.getAttribute("depth-src"),r=this.getAttribute("depth-meta");if(!t||!e||!r){const i="src, depth-src, and depth-meta attributes are required.";console.warn(`<layershift-parallax>: ${i}`),this.emit("layershift-parallax:error",{message:i});return}if(this.container){this.abortController=new AbortController;try{const[i,a]=await Promise.all([this.createVideoElement(t),k(e,r)]);if(this.abortController.signal.aborted){i.remove();return}this.video=i,this.loopCount=0,this.attachVideoEventListeners(i);const l=$(a.frames,a.meta.width,a.meta.height),n=j(l),c=this.hasAttribute("parallax-max")?this.parallaxMax/Math.max(i.videoWidth,1):n.parallaxStrength,h=this.hasAttribute("overscan")?this.overscan:n.overscanPadding;let d;try{const u=await _.create(a,a.meta.width,a.meta.height);this.depthWorker=u,d=m=>u.sample(m)}catch{const u=new z(a,a.meta.width,a.meta.height);d=m=>u.sample(m)}if(this.abortController.signal.aborted){i.remove(),this.depthWorker?.dispose(),this.depthWorker=null;return}this.renderer=new A(this.container,{parallaxStrength:c,pomEnabled:!0,pomSteps:n.pomSteps,overscanPadding:h,contrastLow:n.contrastLow,contrastHigh:n.contrastHigh,verticalReduction:n.verticalReduction,dofStart:n.dofStart,dofStrength:n.dofStrength}),this.renderer.initialize(i,a.meta.width,a.meta.height),this.inputHandler=new it(this);const p=this.parallaxX,s=this.parallaxY;if(this.renderer.start(i,d,()=>{const u=this.inputHandler.update();return{x:u.x*p,y:u.y*s}},(u,m)=>{this.emit("layershift-parallax:frame",{currentTime:u,frameNumber:m})}),this.shouldAutoplay){i.currentTime=0;try{await i.play()}catch{}}this.initialized=!0,this.emit("layershift-parallax:ready",{videoWidth:i.videoWidth,videoHeight:i.videoHeight,duration:i.duration,depthProfile:l,derivedParams:n})}catch(i){const a=i instanceof Error?i.message:"Failed to initialize.";console.error("<layershift-parallax>: Failed to initialize.",i),this.emit("layershift-parallax:error",{message:a})}}}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((r,i)=>{if(e.readyState>=HTMLMediaElement.HAVE_METADATA){r();return}const a=()=>{n(),r()},l=()=>{n(),i(new Error("Failed to load video metadata."))},n=()=>{e.removeEventListener("loadedmetadata",a),e.removeEventListener("error",l)};e.addEventListener("loadedmetadata",a),e.addEventListener("error",l),e.load()}),e}dispose(){this.abortController?.abort(),this.abortController=null,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.initialized=!1,this.loopCount=0,this.container=null}}function U(o,t,e){return Math.min(e,Math.max(t,o))}function F(o,t,e){return o+(t-o)*e}return customElements.get(R.TAG_NAME)||customElements.define(R.TAG_NAME,R),C.LayershiftElement=R,Object.defineProperty(C,Symbol.toStringTag,{value:"Module"}),C})({});
213
+ `,this.shadow.appendChild(t),this.container=document.createElement("div"),this.container.className="container",this.shadow.appendChild(this.container)}async init(){const t=this.getAttribute("src"),e=this.getAttribute("depth-src"),r=this.getAttribute("depth-meta");if(!t||!e||!r){const i="src, depth-src, and depth-meta attributes are required.";console.warn(`<layershift-parallax>: ${i}`),this.emit("layershift-parallax:error",{message:i});return}if(this.container){this.abortController=new AbortController;try{const[i,a]=await Promise.all([this.createVideoElement(t),X(e,r)]);if(this.abortController.signal.aborted){i.remove();return}this.video=i,this.loopCount=0,this.attachVideoEventListeners(i);const c=j(a.frames,a.meta.width,a.meta.height),n=K(c),l=this.hasAttribute("parallax-max")?this.parallaxMax/Math.max(i.videoWidth,1):n.parallaxStrength,h=this.hasAttribute("overscan")?this.overscan:n.overscanPadding;let d;try{const u=await V.create(a,a.meta.width,a.meta.height);this.depthWorker=u,d=m=>u.sample(m)}catch{const u=new k(a,a.meta.width,a.meta.height);d=m=>u.sample(m)}if(this.abortController.signal.aborted){i.remove(),this.depthWorker?.dispose(),this.depthWorker=null;return}this.renderer=new R(this.container,{parallaxStrength:l,pomEnabled:!0,pomSteps:n.pomSteps,overscanPadding:h,contrastLow:n.contrastLow,contrastHigh:n.contrastHigh,verticalReduction:n.verticalReduction,dofStart:n.dofStart,dofStrength:n.dofStrength}),this.renderer.initialize(i,a.meta.width,a.meta.height),this.inputHandler=new O(this);const p=this.parallaxX,s=this.parallaxY;if(this.renderer.start(i,d,()=>{const u=this.inputHandler.update();return{x:u.x*p,y:u.y*s}},(u,m)=>{this.emit("layershift-parallax:frame",{currentTime:u,frameNumber:m})}),this.shouldAutoplay){i.currentTime=0;try{await i.play()}catch{}}this.initialized=!0,this.emit("layershift-parallax:ready",{videoWidth:i.videoWidth,videoHeight:i.videoHeight,duration:i.duration,depthProfile:c,derivedParams:n})}catch(i){const a=i instanceof Error?i.message:"Failed to initialize.";console.error("<layershift-parallax>: Failed to initialize.",i),this.emit("layershift-parallax:error",{message:a})}}}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((r,i)=>{if(e.readyState>=HTMLMediaElement.HAVE_METADATA){r();return}const a=()=>{n(),r()},c=()=>{n(),i(new Error("Failed to load video metadata."))},n=()=>{e.removeEventListener("loadedmetadata",a),e.removeEventListener("error",c)};e.addEventListener("loadedmetadata",a),e.addEventListener("error",c),e.load()}),e}dispose(){this.abortController?.abort(),this.abortController=null,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.initialized=!1,this.loopCount=0,this.container=null}}function y(o,t,e){return Math.min(e,Math.max(t,o))}function P(o,t,e){return o+(t-o)*e}return customElements.get(U.TAG_NAME)||customElements.define(U.TAG_NAME,U),C.LayershiftElement=U,Object.defineProperty(C,Symbol.toStringTag,{value:"Module"}),C})({});
@@ -1,4 +1,4 @@
1
- class V {
1
+ class _ {
2
2
  worker;
3
3
  currentBuffer;
4
4
  pendingTimeSec = null;
@@ -22,14 +22,14 @@ class V {
22
22
  import.meta.url
23
23
  ),
24
24
  { type: "module" }
25
- ), a = e * r, l = new V(i, a), n = t.frames.map((c) => {
26
- const h = new Uint8Array(c.length);
27
- return h.set(c), h.buffer;
25
+ ), a = e * r, c = new _(i, a), n = t.frames.map((l) => {
26
+ const h = new Uint8Array(l.length);
27
+ return h.set(l), h.buffer;
28
28
  });
29
- return await new Promise((c, h) => {
29
+ return await new Promise((l, h) => {
30
30
  const d = setTimeout(() => h(new Error("Worker init timeout")), 1e4);
31
31
  i.onmessage = (p) => {
32
- p.data.type === "ready" && (clearTimeout(d), c());
32
+ p.data.type === "ready" && (clearTimeout(d), l());
33
33
  }, i.onerror = (p) => {
34
34
  clearTimeout(d), h(p);
35
35
  }, i.postMessage(
@@ -48,12 +48,12 @@ class V {
48
48
  n
49
49
  // Transfer list
50
50
  );
51
- }), i.onmessage = (c) => {
52
- if (c.data.type === "result" && (l.currentBuffer = c.data.data, l.workerBusy = !1, l.pendingTimeSec !== null)) {
53
- const h = l.pendingTimeSec;
54
- l.pendingTimeSec = null, l.requestSample(h);
51
+ }), i.onmessage = (l) => {
52
+ if (l.data.type === "result" && (c.currentBuffer = l.data.data, c.workerBusy = !1, c.pendingTimeSec !== null)) {
53
+ const h = c.pendingTimeSec;
54
+ c.pendingTimeSec = null, c.requestSample(h);
55
55
  }
56
- }, l;
56
+ }, c;
57
57
  }
58
58
  /**
59
59
  * Get the current depth frame — always synchronous, zero main-thread work.
@@ -82,7 +82,7 @@ class V {
82
82
  this.disposed = !0, this.worker.terminate();
83
83
  }
84
84
  }
85
- class I {
85
+ class H {
86
86
  constructor(t, e, r) {
87
87
  this.depthData = t, this.targetWidth = e, this.targetHeight = r;
88
88
  const i = t.meta.width * t.meta.height, a = e * r;
@@ -100,21 +100,21 @@ class I {
100
100
  lastNextFrameIndex = -1;
101
101
  lastLerpFactor = -1;
102
102
  sample(t) {
103
- const e = L(t * this.depthData.meta.fps, 0, this.depthData.meta.frameCount - 1), r = Math.floor(e), i = Math.min(r + 1, this.depthData.meta.frameCount - 1), a = e - r, l = r !== this.lastFrameIndex || i !== this.lastNextFrameIndex, n = Math.abs(a - this.lastLerpFactor) > 1e-3;
104
- if (!l && !n)
103
+ const e = L(t * this.depthData.meta.fps, 0, this.depthData.meta.frameCount - 1), r = Math.floor(e), i = Math.min(r + 1, this.depthData.meta.frameCount - 1), a = e - r, c = r !== this.lastFrameIndex || i !== this.lastNextFrameIndex, n = Math.abs(a - this.lastLerpFactor) > 1e-3;
104
+ if (!c && !n)
105
105
  return this.uint8Output;
106
106
  this.lastFrameIndex = r, this.lastNextFrameIndex = i, this.lastLerpFactor = a;
107
- const c = 1 - a, h = this.depthData.frames[r], d = this.depthData.frames[i];
107
+ const l = 1 - a, h = this.depthData.frames[r], d = this.depthData.frames[i];
108
108
  for (let u = 0; u < this.interpolatedDepth.length; u += 1)
109
- this.interpolatedDepth[u] = (h[u] * c + d[u] * a) / 255;
110
- G(
109
+ this.interpolatedDepth[u] = (h[u] * l + d[u] * a) / 255;
110
+ W(
111
111
  this.interpolatedDepth,
112
112
  this.depthData.meta.width,
113
113
  this.depthData.meta.height,
114
114
  this.bilateralOutput
115
115
  );
116
116
  const p = this.targetWidth !== this.depthData.meta.width || this.targetHeight !== this.depthData.meta.height;
117
- p && N(
117
+ p && G(
118
118
  this.bilateralOutput,
119
119
  this.depthData.meta.width,
120
120
  this.depthData.meta.height,
@@ -128,19 +128,19 @@ class I {
128
128
  return this.uint8Output;
129
129
  }
130
130
  }
131
- async function H(o, t, e) {
131
+ async function z(o, t, e) {
132
132
  const [r, i] = await Promise.all([
133
- z(t),
134
- k(o)
133
+ k(t),
134
+ X(o)
135
135
  ]);
136
- return X(i, r);
136
+ return B(i, r);
137
137
  }
138
- async function z(o) {
138
+ async function k(o) {
139
139
  const t = await fetch(o);
140
140
  if (!t.ok)
141
141
  throw new Error(`Failed to fetch depth metadata (${t.status} ${t.statusText}).`);
142
142
  const e = await t.json();
143
- return B(e), {
143
+ return N(e), {
144
144
  frameCount: e.frameCount,
145
145
  fps: e.fps,
146
146
  width: e.width,
@@ -148,7 +148,7 @@ async function z(o) {
148
148
  sourceFps: e.sourceFps
149
149
  };
150
150
  }
151
- async function k(o, t) {
151
+ async function X(o, t) {
152
152
  const e = await fetch(o);
153
153
  if (!e.ok)
154
154
  throw new Error(`Failed to fetch depth data (${e.status} ${e.statusText}).`);
@@ -158,20 +158,20 @@ async function k(o, t) {
158
158
  return new Uint8Array(await e.arrayBuffer());
159
159
  const i = [];
160
160
  let a = 0;
161
- const l = r.getReader();
161
+ const c = r.getReader();
162
162
  for (; ; ) {
163
- const { done: h, value: d } = await l.read();
163
+ const { done: h, value: d } = await c.read();
164
164
  if (h)
165
165
  break;
166
166
  d && (i.push(d), a += d.byteLength);
167
167
  }
168
168
  const n = new Uint8Array(a);
169
- let c = 0;
169
+ let l = 0;
170
170
  for (const h of i)
171
- n.set(h, c), c += h.byteLength;
171
+ n.set(h, l), l += h.byteLength;
172
172
  return n;
173
173
  }
174
- function X(o, t) {
174
+ function B(o, t) {
175
175
  if (o.byteLength < 4)
176
176
  throw new Error("Depth data binary is missing the frame-count header.");
177
177
  const r = new DataView(o.buffer, o.byteOffset, o.byteLength).getUint32(0, !0), i = t.width * t.height, a = 4 + r * i;
@@ -183,52 +183,52 @@ function X(o, t) {
183
183
  throw new Error(
184
184
  `Depth frame count mismatch between metadata (${t.frameCount}) and binary header (${r}).`
185
185
  );
186
- const l = o.subarray(4), n = new Array(r);
187
- for (let c = 0; c < r; c += 1) {
188
- const h = c * i;
189
- n[c] = l.subarray(h, h + i);
186
+ const c = o.subarray(4), n = new Array(r);
187
+ for (let l = 0; l < r; l += 1) {
188
+ const h = l * i;
189
+ n[l] = c.subarray(h, h + i);
190
190
  }
191
191
  return { meta: t, frames: n };
192
192
  }
193
- function B(o) {
193
+ function N(o) {
194
194
  if (!o || typeof o.frameCount != "number" || typeof o.fps != "number" || typeof o.width != "number" || typeof o.height != "number" || typeof o.sourceFps != "number")
195
195
  throw new Error("Depth metadata is malformed.");
196
196
  if (!Number.isFinite(o.frameCount) || !Number.isFinite(o.fps) || !Number.isFinite(o.width) || !Number.isFinite(o.height) || !Number.isFinite(o.sourceFps) || o.frameCount <= 0 || o.fps <= 0 || o.width <= 0 || o.height <= 0 || o.sourceFps <= 0)
197
197
  throw new Error("Depth metadata contains invalid numeric values.");
198
198
  }
199
- function N(o, t, e, r, i, a) {
200
- const l = t / r, n = e / i;
201
- for (let c = 0; c < i; c += 1) {
202
- const h = (c + 0.5) * n - 0.5, d = L(Math.floor(h), 0, e - 1), p = L(d + 1, 0, e - 1), s = h - d;
199
+ function G(o, t, e, r, i, a) {
200
+ const c = t / r, n = e / i;
201
+ for (let l = 0; l < i; l += 1) {
202
+ const h = (l + 0.5) * n - 0.5, d = L(Math.floor(h), 0, e - 1), p = L(d + 1, 0, e - 1), s = h - d;
203
203
  for (let u = 0; u < r; u += 1) {
204
- const m = (u + 0.5) * l - 0.5, v = L(Math.floor(m), 0, t - 1), x = L(v + 1, 0, t - 1), b = m - v, T = o[d * t + v], y = o[d * t + x], R = o[p * t + v], f = o[p * t + x], w = T + (y - T) * b, U = R + (f - R) * b;
205
- a[c * r + u] = w + (U - w) * s;
204
+ const m = (u + 0.5) * c - 0.5, v = L(Math.floor(m), 0, t - 1), T = L(v + 1, 0, t - 1), y = m - v, w = o[d * t + v], b = o[d * t + T], U = o[p * t + v], f = o[p * t + T], x = w + (b - w) * y, P = U + (f - U) * y;
205
+ a[l * r + u] = x + (P - x) * s;
206
206
  }
207
207
  }
208
208
  }
209
- function G(o, t, e, r) {
210
- for (let l = 0; l < e; l += 1)
209
+ function W(o, t, e, r) {
210
+ for (let c = 0; c < e; c += 1)
211
211
  for (let n = 0; n < t; n += 1) {
212
- const c = l * t + n, h = o[c];
212
+ const l = c * t + n, h = o[l];
213
213
  let d = 1, p = h;
214
214
  for (let s = -2; s <= 2; s += 1) {
215
- const u = l + s;
215
+ const u = c + s;
216
216
  if (!(u < 0 || u >= e))
217
217
  for (let m = -2; m <= 2; m += 1) {
218
218
  if (m === 0 && s === 0) continue;
219
219
  const v = n + m;
220
220
  if (v < 0 || v >= t) continue;
221
- const x = o[u * t + v], b = m * m + s * s, T = x - h, y = Math.exp(-b / 2.25 - T * T / 0.01);
222
- d += y, p += x * y;
221
+ const T = o[u * t + v], y = m * m + s * s, w = T - h, b = Math.exp(-y / 2.25 - w * w / 0.01);
222
+ d += b, p += T * b;
223
223
  }
224
224
  }
225
- r[c] = p / d;
225
+ r[l] = p / d;
226
226
  }
227
227
  }
228
228
  function L(o, t, e) {
229
229
  return Math.min(e, Math.max(t, o));
230
230
  }
231
- const W = {
231
+ const q = {
232
232
  parallaxStrength: 0.05,
233
233
  contrastLow: 0.05,
234
234
  contrastHigh: 0.95,
@@ -238,72 +238,72 @@ const W = {
238
238
  pomSteps: 16,
239
239
  overscanPadding: 0.08
240
240
  };
241
- function q(o, t, e) {
241
+ function Y(o, t, e) {
242
242
  const r = new Float32Array(256);
243
243
  if (o.length === 0 || t <= 0 || e <= 0)
244
- return _(r);
245
- const i = $(o.length), a = t * e;
246
- let l = 0;
244
+ return O(r);
245
+ const i = j(o.length), a = t * e;
246
+ let c = 0;
247
247
  const n = new Uint32Array(256);
248
248
  for (const f of i) {
249
- const w = o[f], U = Math.min(w.length, a);
250
- for (let M = 0; M < U; M += 1)
251
- n[w[M]] += 1;
252
- l += U;
249
+ const x = o[f], P = Math.min(x.length, a);
250
+ for (let M = 0; M < P; M += 1)
251
+ n[x[M]] += 1;
252
+ c += P;
253
253
  }
254
- if (l === 0)
255
- return _(r);
256
- const c = 1 / l;
254
+ if (c === 0)
255
+ return O(r);
256
+ const l = 1 / c;
257
257
  for (let f = 0; f < 256; f += 1)
258
- r[f] = n[f] * c;
258
+ r[f] = n[f] * l;
259
259
  const h = new Float32Array(256);
260
260
  h[0] = r[0];
261
261
  for (let f = 1; f < 256; f += 1)
262
262
  h[f] = h[f - 1] + r[f];
263
- const d = S(h, 0.05), p = S(h, 0.25), s = S(h, 0.5), u = S(h, 0.75), m = S(h, 0.95);
263
+ const d = D(h, 0.05), p = D(h, 0.25), s = D(h, 0.5), u = D(h, 0.75), m = D(h, 0.95);
264
264
  let v = 0;
265
265
  for (let f = 0; f < 256; f += 1)
266
266
  v += f / 255 * r[f];
267
- let x = 0;
267
+ let T = 0;
268
268
  for (let f = 0; f < 256; f += 1) {
269
- const w = f / 255 - v;
270
- x += r[f] * w * w;
269
+ const x = f / 255 - v;
270
+ T += r[f] * x * x;
271
271
  }
272
- const b = Math.sqrt(x), T = m - d, y = u - p, R = j(r);
272
+ const y = Math.sqrt(T), w = m - d, b = u - p, U = K(r);
273
273
  return {
274
274
  mean: v,
275
- stdDev: b,
275
+ stdDev: y,
276
276
  p5: d,
277
277
  p25: p,
278
278
  median: s,
279
279
  p75: u,
280
280
  p95: m,
281
- effectiveRange: T,
282
- iqr: y,
283
- bimodality: R,
281
+ effectiveRange: w,
282
+ iqr: b,
283
+ bimodality: U,
284
284
  histogram: r
285
285
  };
286
286
  }
287
- function Y(o) {
287
+ function $(o) {
288
288
  if (o.effectiveRange < 0.05 || o.stdDev < 0.02)
289
- return { ...W };
289
+ return { ...q };
290
290
  const t = o.effectiveRange - 0.5, e = o.bimodality - 0.4, r = g(
291
291
  0.05 - t * 0.03 + e * 0.01,
292
292
  0.035,
293
293
  0.065
294
- ), i = g(o.p5 - 0.03, 0, 0.25), a = g(o.p95 + 0.03, 0.75, 1), l = g((r - 0.03) / 0.05, 0, 1), n = g(0.6 - l * 0.25, 0.35, 0.6), c = g(0.6 - t * 0.2, 0.5, 0.7), h = g(0.4 + t * 0.2, 0.25, 0.5), d = 16, p = g(r + 0.03, 0.06, 0.1);
294
+ ), i = g(o.p5 - 0.03, 0, 0.25), a = g(o.p95 + 0.03, 0.75, 1), c = g((r - 0.03) / 0.05, 0, 1), n = g(0.6 - c * 0.25, 0.35, 0.6), l = g(0.6 - t * 0.2, 0.5, 0.7), h = g(0.4 + t * 0.2, 0.25, 0.5), d = 16, p = g(r + 0.03, 0.06, 0.1);
295
295
  return {
296
296
  parallaxStrength: r,
297
297
  contrastLow: i,
298
298
  contrastHigh: a,
299
299
  verticalReduction: n,
300
- dofStart: c,
300
+ dofStart: l,
301
301
  dofStrength: h,
302
302
  pomSteps: d,
303
303
  overscanPadding: p
304
304
  };
305
305
  }
306
- function $(o) {
306
+ function j(o) {
307
307
  if (o <= 0) return [];
308
308
  if (o === 1) return [0];
309
309
  const t = o - 1, e = [
@@ -317,13 +317,13 @@ function $(o) {
317
317
  r.has(a) || (r.add(a), i.push(a));
318
318
  return i;
319
319
  }
320
- function S(o, t) {
320
+ function D(o, t) {
321
321
  for (let e = 0; e < 256; e += 1)
322
322
  if (o[e] >= t)
323
323
  return e / 255;
324
324
  return 1;
325
325
  }
326
- function j(o) {
326
+ function K(o) {
327
327
  const t = new Float32Array(256);
328
328
  for (let s = 0; s < 256; s += 1) {
329
329
  let u = 0, m = 0;
@@ -339,22 +339,22 @@ function j(o) {
339
339
  for (let s = 1; s < 255; s += 1)
340
340
  t[s] > t[s - 1] && t[s] > t[s + 1] && t[s] >= r && a.push({ bin: s, height: t[s] });
341
341
  if (t[0] > t[1] && t[0] >= r && a.push({ bin: 0, height: t[0] }), t[255] > t[254] && t[255] >= r && a.push({ bin: 255, height: t[255] }), a.sort((s, u) => u.height - s.height), a.length < 2) return 0;
342
- const l = a[0];
342
+ const c = a[0];
343
343
  let n = null;
344
344
  for (let s = 1; s < a.length; s += 1)
345
- if (Math.abs(a[s].bin - l.bin) >= i) {
345
+ if (Math.abs(a[s].bin - c.bin) >= i) {
346
346
  n = a[s];
347
347
  break;
348
348
  }
349
349
  if (!n) return 0;
350
- const c = Math.min(l.bin, n.bin), h = Math.max(l.bin, n.bin);
350
+ const l = Math.min(c.bin, n.bin), h = Math.max(c.bin, n.bin);
351
351
  let d = 1 / 0;
352
- for (let s = c; s <= h; s += 1)
352
+ for (let s = l; s <= h; s += 1)
353
353
  t[s] < d && (d = t[s]);
354
- const p = Math.min(l.height, n.height);
354
+ const p = Math.min(c.height, n.height);
355
355
  return p <= 0 ? 0 : g(1 - d / p, 0, 1);
356
356
  }
357
- function _(o) {
357
+ function O(o) {
358
358
  return {
359
359
  mean: 0,
360
360
  stdDev: 0,
@@ -372,7 +372,7 @@ function _(o) {
372
372
  function g(o, t, e) {
373
373
  return Math.min(e, Math.max(t, o));
374
374
  }
375
- const K = (
375
+ const Z = (
376
376
  /* glsl */
377
377
  `#version 300 es
378
378
  in vec2 aPosition;
@@ -396,7 +396,7 @@ const K = (
396
396
  gl_Position = vec4(aPosition, 0.0, 1.0);
397
397
  }
398
398
  `
399
- ), Z = (
399
+ ), J = (
400
400
  /* glsl */
401
401
  `#version 300 es
402
402
  precision highp float;
@@ -567,14 +567,14 @@ const K = (
567
567
  fragColor = color;
568
568
  }
569
569
  `
570
- ), D = {
570
+ ), A = {
571
571
  contrastLow: 0.05,
572
572
  contrastHigh: 0.95,
573
573
  verticalReduction: 0.5,
574
574
  dofStart: 0.6,
575
575
  dofStrength: 0.4
576
576
  };
577
- function O(o, t, e) {
577
+ function I(o, t, e) {
578
578
  const r = o.createShader(t);
579
579
  if (!r) throw new Error("Failed to create shader.");
580
580
  if (o.shaderSource(r, e), o.compileShader(r), !o.getShaderParameter(r, o.COMPILE_STATUS)) {
@@ -584,7 +584,7 @@ ${i}`);
584
584
  }
585
585
  return r;
586
586
  }
587
- function J(o, t, e) {
587
+ function Q(o, t, e) {
588
588
  const r = o.createProgram();
589
589
  if (!r) throw new Error("Failed to create program.");
590
590
  if (o.attachShader(r, t), o.attachShader(r, e), o.linkProgram(r), !o.getProgramParameter(r, o.LINK_STATUS)) {
@@ -594,7 +594,7 @@ ${i}`);
594
594
  }
595
595
  return o.detachShader(r, t), o.detachShader(r, e), o.deleteShader(t), o.deleteShader(e), r;
596
596
  }
597
- function Q(o, t) {
597
+ function tt(o, t) {
598
598
  return {
599
599
  uImage: o.getUniformLocation(t, "uImage"),
600
600
  uDepth: o.getUniformLocation(t, "uDepth"),
@@ -612,7 +612,7 @@ function Q(o, t) {
612
612
  uUvScale: o.getUniformLocation(t, "uUvScale")
613
613
  };
614
614
  }
615
- class A {
615
+ class R {
616
616
  /** Debounce delay for resize events to avoid layout thrashing. */
617
617
  static RESIZE_DEBOUNCE_MS = 100;
618
618
  /** Compile-time upper bound for the POM for-loop in GLSL. */
@@ -667,11 +667,11 @@ class A {
667
667
  pomEnabled: e.pomEnabled,
668
668
  pomSteps: e.pomSteps,
669
669
  overscanPadding: e.overscanPadding,
670
- contrastLow: e.contrastLow ?? D.contrastLow,
671
- contrastHigh: e.contrastHigh ?? D.contrastHigh,
672
- verticalReduction: e.verticalReduction ?? D.verticalReduction,
673
- dofStart: e.dofStart ?? D.dofStart,
674
- dofStrength: e.dofStrength ?? D.dofStrength
670
+ contrastLow: e.contrastLow ?? A.contrastLow,
671
+ contrastHigh: e.contrastHigh ?? A.contrastHigh,
672
+ verticalReduction: e.verticalReduction ?? A.verticalReduction,
673
+ dofStart: e.dofStart ?? A.dofStart,
674
+ dofStrength: e.dofStrength ?? A.dofStrength
675
675
  }, this.canvas = document.createElement("canvas");
676
676
  const r = this.canvas.getContext("webgl2", {
677
677
  antialias: !1,
@@ -708,7 +708,7 @@ class A {
708
708
  * does everything (the pre-RVFC behavior).
709
709
  */
710
710
  start(t, e, r, i) {
711
- this.stop(), this.playbackVideo = t, this.readDepth = e, this.readInput = r, this.onVideoFrame = i ?? null, this.rvfcSupported = A.isRVFCSupported(), this.rvfcSupported && (this.rvfcHandle = t.requestVideoFrameCallback(this.videoFrameLoop)), this.animationFrameHandle = window.requestAnimationFrame(this.renderLoop);
711
+ this.stop(), this.playbackVideo = t, this.readDepth = e, this.readInput = r, this.onVideoFrame = i ?? null, this.rvfcSupported = R.isRVFCSupported(), this.rvfcSupported && (this.rvfcHandle = t.requestVideoFrameCallback(this.videoFrameLoop)), this.animationFrameHandle = window.requestAnimationFrame(this.renderLoop);
712
712
  }
713
713
  /** Stop both render loops and release callbacks. */
714
714
  stop() {
@@ -725,12 +725,12 @@ class A {
725
725
  initGPUResources() {
726
726
  const t = this.gl;
727
727
  if (!t) return;
728
- const e = Z.replace(
728
+ const e = J.replace(
729
729
  "#version 300 es",
730
730
  `#version 300 es
731
- #define MAX_POM_STEPS ${A.MAX_POM_STEPS}`
732
- ), r = O(t, t.VERTEX_SHADER, K), i = O(t, t.FRAGMENT_SHADER, e);
733
- this.program = J(t, r, i), this.uniforms = Q(t, this.program);
731
+ #define MAX_POM_STEPS ${R.MAX_POM_STEPS}`
732
+ ), r = I(t, t.VERTEX_SHADER, Z), i = I(t, t.FRAGMENT_SHADER, e);
733
+ this.program = Q(t, r, i), this.uniforms = tt(t, this.program);
734
734
  const a = new Float32Array([
735
735
  -1,
736
736
  -1,
@@ -746,8 +746,8 @@ class A {
746
746
  // top-right
747
747
  ]);
748
748
  this.vao = t.createVertexArray(), t.bindVertexArray(this.vao);
749
- const l = t.createBuffer();
750
- t.bindBuffer(t.ARRAY_BUFFER, l), t.bufferData(t.ARRAY_BUFFER, a, t.STATIC_DRAW);
749
+ const c = t.createBuffer();
750
+ t.bindBuffer(t.ARRAY_BUFFER, c), t.bufferData(t.ARRAY_BUFFER, a, t.STATIC_DRAW);
751
751
  const n = t.getAttribLocation(this.program, "aPosition");
752
752
  t.enableVertexAttribArray(n), t.vertexAttribPointer(n, 2, t.FLOAT, !1, 0, 0), t.bindVertexArray(null), t.disable(t.DEPTH_TEST);
753
753
  }
@@ -832,7 +832,7 @@ class A {
832
832
  scheduleResizeRecalculate = () => {
833
833
  this.resizeTimer !== null && window.clearTimeout(this.resizeTimer), this.resizeTimer = window.setTimeout(() => {
834
834
  this.resizeTimer = null, this.recalculateViewportLayout();
835
- }, A.RESIZE_DEBOUNCE_MS);
835
+ }, R.RESIZE_DEBOUNCE_MS);
836
836
  };
837
837
  /**
838
838
  * Recalculate the WebGL canvas size and UV transform to match the
@@ -844,12 +844,12 @@ class A {
844
844
  recalculateViewportLayout() {
845
845
  const t = this.gl;
846
846
  if (!t) return;
847
- const { width: e, height: r } = this.getViewportSize(), i = Math.min(window.devicePixelRatio, 2), a = Math.round(e * i), l = Math.round(r * i);
848
- (this.canvas.width !== a || this.canvas.height !== l) && (this.canvas.width = a, this.canvas.height = l, t.viewport(0, 0, a, l));
849
- const n = e / r, c = this.config.parallaxStrength + this.config.overscanPadding;
847
+ const { width: e, height: r } = this.getViewportSize(), i = Math.min(window.devicePixelRatio, 2), a = Math.round(e * i), c = Math.round(r * i);
848
+ (this.canvas.width !== a || this.canvas.height !== c) && (this.canvas.width = a, this.canvas.height = c, t.viewport(0, 0, a, c));
849
+ const n = e / r, l = this.config.parallaxStrength + this.config.overscanPadding;
850
850
  let h = 1, d = 1;
851
851
  n > this.videoAspect ? d = this.videoAspect / n : h = n / this.videoAspect;
852
- const p = 1 + c * 2;
852
+ const p = 1 + l * 2;
853
853
  h /= p, d /= p, this.uvOffset = [(1 - h) / 2, (1 - d) / 2], this.uvScale = [h, d], 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]));
854
854
  }
855
855
  /** Read the container's pixel dimensions, with a minimum of 1x1. */
@@ -890,9 +890,9 @@ const E = {
890
890
  loop: !0,
891
891
  muted: !0
892
892
  };
893
- class tt {
893
+ class V {
894
894
  constructor(t, e = 0.08, r = 0.06) {
895
- this.host = t, this.lerpFactor = e, this.motionLerpFactor = r, this.host.addEventListener("mousemove", this.handleMouseMove), this.host.addEventListener("mouseleave", this.resetPointerTarget), this.host.addEventListener("touchstart", this.handleFirstTouch, { once: !0 });
895
+ this.host = t, this.lerpFactor = e, this.motionLerpFactor = r, 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 });
896
896
  }
897
897
  pointerTarget = { x: 0, y: 0 };
898
898
  motionTarget = { x: 0, y: 0 };
@@ -900,24 +900,42 @@ class tt {
900
900
  usingMotionInput = !1;
901
901
  motionListenerAttached = !1;
902
902
  motionRequested = !1;
903
+ touchActive = !1;
904
+ touchAnchorX = 0;
905
+ touchAnchorY = 0;
903
906
  lerpFactor;
904
907
  motionLerpFactor;
908
+ /** Pixels of finger drag to reach full parallax offset (-1 or 1). */
909
+ static TOUCH_DRAG_RANGE = 100;
905
910
  update() {
906
- const t = this.usingMotionInput ? this.motionTarget : this.pointerTarget, e = this.usingMotionInput ? this.motionLerpFactor : this.lerpFactor;
907
- return this.smoothedOutput.x = P(this.smoothedOutput.x, t.x, e), this.smoothedOutput.y = P(this.smoothedOutput.y, t.y, e), this.smoothedOutput;
911
+ const t = this.touchActive ? this.pointerTarget : this.usingMotionInput ? this.motionTarget : this.pointerTarget, e = this.usingMotionInput && !this.touchActive ? this.motionLerpFactor : this.lerpFactor;
912
+ return this.smoothedOutput.x = F(this.smoothedOutput.x, t.x, e), this.smoothedOutput.y = F(this.smoothedOutput.y, t.y, e), this.smoothedOutput;
908
913
  }
909
914
  dispose() {
910
- this.host.removeEventListener("mousemove", this.handleMouseMove), this.host.removeEventListener("mouseleave", this.resetPointerTarget), this.host.removeEventListener("touchstart", this.handleFirstTouch), this.motionListenerAttached && (window.removeEventListener("deviceorientation", this.handleDeviceOrientation), this.motionListenerAttached = !1);
915
+ 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);
911
916
  }
912
917
  handleMouseMove = (t) => {
913
918
  const e = this.host.getBoundingClientRect(), r = (t.clientX - e.left) / e.width * 2 - 1, i = (t.clientY - e.top) / e.height * 2 - 1;
914
- this.pointerTarget.x = F(r, -1, 1), this.pointerTarget.y = F(i, -1, 1);
919
+ this.pointerTarget.x = S(r, -1, 1), this.pointerTarget.y = S(i, -1, 1);
915
920
  };
916
921
  resetPointerTarget = () => {
917
922
  this.pointerTarget.x = 0, this.pointerTarget.y = 0;
918
923
  };
919
- handleFirstTouch = async () => {
920
- if (this.motionRequested || (this.motionRequested = !0, typeof DeviceOrientationEvent > "u")) return;
924
+ handleTouchStart = (t) => {
925
+ const e = t.touches[0];
926
+ 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()));
927
+ };
928
+ handleTouchMove = (t) => {
929
+ const e = t.touches[0];
930
+ if (!e) return;
931
+ const r = e.clientX - this.touchAnchorX, i = e.clientY - this.touchAnchorY, a = V.TOUCH_DRAG_RANGE;
932
+ this.pointerTarget.x = S(r / a, -1, 1), this.pointerTarget.y = S(i / a, -1, 1);
933
+ };
934
+ handleTouchEnd = () => {
935
+ this.touchActive = !1, this.pointerTarget.x = 0, this.pointerTarget.y = 0;
936
+ };
937
+ async requestMotionPermission() {
938
+ if (typeof DeviceOrientationEvent > "u") return;
921
939
  const t = DeviceOrientationEvent;
922
940
  if (typeof t.requestPermission == "function")
923
941
  try {
@@ -926,10 +944,10 @@ class tt {
926
944
  return;
927
945
  }
928
946
  this.motionListenerAttached || (window.addEventListener("deviceorientation", this.handleDeviceOrientation), this.motionListenerAttached = !0), this.usingMotionInput = !0;
929
- };
947
+ }
930
948
  handleDeviceOrientation = (t) => {
931
- const e = F((t.gamma ?? 0) / 45, -1, 1), r = F((t.beta ?? 0) / 45, -1, 1);
932
- this.motionTarget.x = P(this.motionTarget.x, e, this.motionLerpFactor), this.motionTarget.y = P(this.motionTarget.y, r, this.motionLerpFactor);
949
+ const e = S((t.gamma ?? 0) / 45, -1, 1), r = S((t.beta ?? 0) / 45, -1, 1);
950
+ this.motionTarget.x = F(this.motionTarget.x, e, this.motionLerpFactor), this.motionTarget.y = F(this.motionTarget.y, r, this.motionLerpFactor);
933
951
  };
934
952
  }
935
953
  class C extends HTMLElement {
@@ -1077,28 +1095,28 @@ class C extends HTMLElement {
1077
1095
  try {
1078
1096
  const [i, a] = await Promise.all([
1079
1097
  this.createVideoElement(t),
1080
- H(e, r)
1098
+ z(e, r)
1081
1099
  ]);
1082
1100
  if (this.abortController.signal.aborted) {
1083
1101
  i.remove();
1084
1102
  return;
1085
1103
  }
1086
1104
  this.video = i, this.loopCount = 0, this.attachVideoEventListeners(i);
1087
- const l = q(
1105
+ const c = Y(
1088
1106
  a.frames,
1089
1107
  a.meta.width,
1090
1108
  a.meta.height
1091
- ), n = Y(l), c = this.hasAttribute("parallax-max") ? this.parallaxMax / Math.max(i.videoWidth, 1) : n.parallaxStrength, h = this.hasAttribute("overscan") ? this.overscan : n.overscanPadding;
1109
+ ), n = $(c), l = this.hasAttribute("parallax-max") ? this.parallaxMax / Math.max(i.videoWidth, 1) : n.parallaxStrength, h = this.hasAttribute("overscan") ? this.overscan : n.overscanPadding;
1092
1110
  let d;
1093
1111
  try {
1094
- const u = await V.create(
1112
+ const u = await _.create(
1095
1113
  a,
1096
1114
  a.meta.width,
1097
1115
  a.meta.height
1098
1116
  );
1099
1117
  this.depthWorker = u, d = (m) => u.sample(m);
1100
1118
  } catch {
1101
- const u = new I(
1119
+ const u = new H(
1102
1120
  a,
1103
1121
  a.meta.width,
1104
1122
  a.meta.height
@@ -1109,8 +1127,8 @@ class C extends HTMLElement {
1109
1127
  i.remove(), this.depthWorker?.dispose(), this.depthWorker = null;
1110
1128
  return;
1111
1129
  }
1112
- this.renderer = new A(this.container, {
1113
- parallaxStrength: c,
1130
+ this.renderer = new R(this.container, {
1131
+ parallaxStrength: l,
1114
1132
  pomEnabled: !0,
1115
1133
  pomSteps: n.pomSteps,
1116
1134
  overscanPadding: h,
@@ -1119,7 +1137,7 @@ class C extends HTMLElement {
1119
1137
  verticalReduction: n.verticalReduction,
1120
1138
  dofStart: n.dofStart,
1121
1139
  dofStrength: n.dofStrength
1122
- }), this.renderer.initialize(i, a.meta.width, a.meta.height), this.inputHandler = new tt(this);
1140
+ }), this.renderer.initialize(i, a.meta.width, a.meta.height), this.inputHandler = new V(this);
1123
1141
  const p = this.parallaxX, s = this.parallaxY;
1124
1142
  if (this.renderer.start(
1125
1143
  i,
@@ -1149,7 +1167,7 @@ class C extends HTMLElement {
1149
1167
  videoWidth: i.videoWidth,
1150
1168
  videoHeight: i.videoHeight,
1151
1169
  duration: i.duration,
1152
- depthProfile: l,
1170
+ depthProfile: c,
1153
1171
  derivedParams: n
1154
1172
  });
1155
1173
  } catch (i) {
@@ -1168,12 +1186,12 @@ class C extends HTMLElement {
1168
1186
  }
1169
1187
  const a = () => {
1170
1188
  n(), r();
1171
- }, l = () => {
1189
+ }, c = () => {
1172
1190
  n(), i(new Error("Failed to load video metadata."));
1173
1191
  }, n = () => {
1174
- e.removeEventListener("loadedmetadata", a), e.removeEventListener("error", l);
1192
+ e.removeEventListener("loadedmetadata", a), e.removeEventListener("error", c);
1175
1193
  };
1176
- e.addEventListener("loadedmetadata", a), e.addEventListener("error", l), e.load();
1194
+ e.addEventListener("loadedmetadata", a), e.addEventListener("error", c), e.load();
1177
1195
  }), e;
1178
1196
  }
1179
1197
  // --- Cleanup ---
@@ -1181,10 +1199,10 @@ class C extends HTMLElement {
1181
1199
  this.abortController?.abort(), this.abortController = null, 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.initialized = !1, this.loopCount = 0, this.container = null;
1182
1200
  }
1183
1201
  }
1184
- function F(o, t, e) {
1202
+ function S(o, t, e) {
1185
1203
  return Math.min(e, Math.max(t, o));
1186
1204
  }
1187
- function P(o, t, e) {
1205
+ function F(o, t, e) {
1188
1206
  return o + (t - o) * e;
1189
1207
  }
1190
1208
  customElements.get(C.TAG_NAME) || customElements.define(C.TAG_NAME, C);
@@ -1 +1 @@
1
- {"version":3,"file":"layershift-element.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/layershift-element.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmIH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,MAAM,CAAC,QAAQ,CAAC,QAAQ,yBAAyB;IAEjD,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAOxC;IAED,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,SAAS,CAAK;;IAStB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IASnB,OAAO,KAAK,SAAS,GAA0E;IAC/F,OAAO,KAAK,SAAS,GAA0E;IAC/F,OAAO,KAAK,WAAW,GAA8E;IACrG,OAAO,KAAK,QAAQ,GAAuE;IAC3F,OAAO,KAAK,cAAc,GAAuE;IACjG,OAAO,KAAK,UAAU,GAA+D;IACrF,OAAO,KAAK,UAAU,GAAiE;IAIvF;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAUZ;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IA2BjC,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAI5B,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAgB7F,OAAO,CAAC,cAAc;YAkCR,IAAI;YAsJJ,kBAAkB;IAuChC,OAAO,CAAC,OAAO;CAyBhB"}
1
+ {"version":3,"file":"layershift-element.d.ts","sourceRoot":"","sources":["../../../../src/components/layershift/layershift-element.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoLH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,MAAM,CAAC,QAAQ,CAAC,QAAQ,yBAAyB;IAEjD,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAOxC;IAED,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,SAAS,CAAK;;IAStB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IASnB,OAAO,KAAK,SAAS,GAA0E;IAC/F,OAAO,KAAK,SAAS,GAA0E;IAC/F,OAAO,KAAK,WAAW,GAA8E;IACrG,OAAO,KAAK,QAAQ,GAAuE;IAC3F,OAAO,KAAK,cAAc,GAAuE;IACjG,OAAO,KAAK,UAAU,GAA+D;IACrF,OAAO,KAAK,UAAU,GAAiE;IAIvF;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAUZ;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IA2BjC,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB,IAAI,IAAI;IAI5B,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAgB7F,OAAO,CAAC,cAAc;YAkCR,IAAI;YAsJJ,kBAAkB;IAuChC,OAAO,CAAC,OAAO;CAyBhB"}
@@ -9,6 +9,9 @@ export declare class InputHandler {
9
9
  private smoothedOutput;
10
10
  private usingMotionInput;
11
11
  private motionListenerAttached;
12
+ private touchActive;
13
+ private touchAnchorX;
14
+ private touchAnchorY;
12
15
  constructor(motionLerpFactor: number);
13
16
  get isMotionSupported(): boolean;
14
17
  get isMotionEnabled(): boolean;
@@ -17,6 +20,9 @@ export declare class InputHandler {
17
20
  dispose(): void;
18
21
  private readonly handleMouseMove;
19
22
  private readonly resetPointerTarget;
23
+ private readonly handleTouchStart;
24
+ private readonly handleTouchMove;
25
+ private readonly handleTouchEnd;
20
26
  private readonly handleDeviceOrientation;
21
27
  }
22
28
  //# sourceMappingURL=input-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"input-handler.d.ts","sourceRoot":"","sources":["../../src/input-handler.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAMD,qBAAa,YAAY;IAOX,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAN7C,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,sBAAsB,CAAS;gBAEV,gBAAgB,EAAE,MAAM;IAKrD,IAAI,iBAAiB,IAAI,OAAO,CAkB/B;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAEK,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAsB9C,MAAM,IAAI,aAAa;IAgBvB,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,QAAQ,CAAC,eAAe,CAK9B;IAEF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAGjC;IAEF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAOtC;CACH"}
1
+ {"version":3,"file":"input-handler.d.ts","sourceRoot":"","sources":["../../src/input-handler.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AASD,qBAAa,YAAY;IAUX,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAT7C,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAK;gBAEI,gBAAgB,EAAE,MAAM;IASrD,IAAI,iBAAiB,IAAI,OAAO,CAkB/B;IAED,IAAI,eAAe,IAAI,OAAO,CAE7B;IAEK,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAsB9C,MAAM,IAAI,aAAa;IAqBvB,OAAO,IAAI,IAAI;IAaf,OAAO,CAAC,QAAQ,CAAC,eAAe,CAK9B;IAEF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAGjC;IAEF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAQ/B;IAEF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAO9B;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAI7B;IAEF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAOtC;CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "layershift",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Embeddable video effects as Web Components. Drop-in parallax, depth-aware motion, and more.",
5
5
  "type": "module",
6
6
  "main": "dist/components/layershift.js",