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
|
|
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
|
-
`,
|
|
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
|
|
191
|
-
${i}`)}return r}function
|
|
192
|
-
${i}`)}return o.detachShader(r,t),o.detachShader(r,e),o.deleteShader(t),o.deleteShader(e),r}function
|
|
193
|
-
#define MAX_POM_STEPS ${
|
|
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),
|
|
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
|
|
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,
|
|
26
|
-
const h = new Uint8Array(
|
|
27
|
-
return h.set(
|
|
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((
|
|
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),
|
|
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 = (
|
|
52
|
-
if (
|
|
53
|
-
const h =
|
|
54
|
-
|
|
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
|
-
},
|
|
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
|
|
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,
|
|
104
|
-
if (!
|
|
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
|
|
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] *
|
|
110
|
-
|
|
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 &&
|
|
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
|
|
131
|
+
async function z(o, t, e) {
|
|
132
132
|
const [r, i] = await Promise.all([
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
k(t),
|
|
134
|
+
X(o)
|
|
135
135
|
]);
|
|
136
|
-
return
|
|
136
|
+
return B(i, r);
|
|
137
137
|
}
|
|
138
|
-
async function
|
|
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
|
|
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
|
|
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
|
|
161
|
+
const c = r.getReader();
|
|
162
162
|
for (; ; ) {
|
|
163
|
-
const { done: h, value: d } = await
|
|
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
|
|
169
|
+
let l = 0;
|
|
170
170
|
for (const h of i)
|
|
171
|
-
n.set(h,
|
|
171
|
+
n.set(h, l), l += h.byteLength;
|
|
172
172
|
return n;
|
|
173
173
|
}
|
|
174
|
-
function
|
|
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
|
|
187
|
-
for (let
|
|
188
|
-
const h =
|
|
189
|
-
n[
|
|
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
|
|
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
|
|
200
|
-
const
|
|
201
|
-
for (let
|
|
202
|
-
const h = (
|
|
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) *
|
|
205
|
-
a[
|
|
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
|
|
210
|
-
for (let
|
|
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
|
|
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 =
|
|
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
|
|
222
|
-
d +=
|
|
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[
|
|
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
|
|
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
|
|
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
|
|
245
|
-
const i =
|
|
246
|
-
let
|
|
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
|
|
250
|
-
for (let M = 0; M <
|
|
251
|
-
n[
|
|
252
|
-
|
|
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 (
|
|
255
|
-
return
|
|
256
|
-
const
|
|
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] *
|
|
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 =
|
|
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
|
|
267
|
+
let T = 0;
|
|
268
268
|
for (let f = 0; f < 256; f += 1) {
|
|
269
|
-
const
|
|
270
|
-
|
|
269
|
+
const x = f / 255 - v;
|
|
270
|
+
T += r[f] * x * x;
|
|
271
271
|
}
|
|
272
|
-
const
|
|
272
|
+
const y = Math.sqrt(T), w = m - d, b = u - p, U = K(r);
|
|
273
273
|
return {
|
|
274
274
|
mean: v,
|
|
275
|
-
stdDev:
|
|
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:
|
|
282
|
-
iqr:
|
|
283
|
-
bimodality:
|
|
281
|
+
effectiveRange: w,
|
|
282
|
+
iqr: b,
|
|
283
|
+
bimodality: U,
|
|
284
284
|
histogram: r
|
|
285
285
|
};
|
|
286
286
|
}
|
|
287
|
-
function
|
|
287
|
+
function $(o) {
|
|
288
288
|
if (o.effectiveRange < 0.05 || o.stdDev < 0.02)
|
|
289
|
-
return { ...
|
|
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),
|
|
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:
|
|
300
|
+
dofStart: l,
|
|
301
301
|
dofStrength: h,
|
|
302
302
|
pomSteps: d,
|
|
303
303
|
overscanPadding: p
|
|
304
304
|
};
|
|
305
305
|
}
|
|
306
|
-
function
|
|
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
|
|
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
|
|
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
|
|
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 -
|
|
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
|
|
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 =
|
|
352
|
+
for (let s = l; s <= h; s += 1)
|
|
353
353
|
t[s] < d && (d = t[s]);
|
|
354
|
-
const p = Math.min(
|
|
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
|
|
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
|
|
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
|
-
),
|
|
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
|
-
),
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 ??
|
|
671
|
-
contrastHigh: e.contrastHigh ??
|
|
672
|
-
verticalReduction: e.verticalReduction ??
|
|
673
|
-
dofStart: e.dofStart ??
|
|
674
|
-
dofStrength: e.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 =
|
|
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 =
|
|
728
|
+
const e = J.replace(
|
|
729
729
|
"#version 300 es",
|
|
730
730
|
`#version 300 es
|
|
731
|
-
#define MAX_POM_STEPS ${
|
|
732
|
-
), r =
|
|
733
|
-
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
|
|
750
|
-
t.bindBuffer(t.ARRAY_BUFFER,
|
|
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
|
-
},
|
|
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),
|
|
848
|
-
(this.canvas.width !== a || this.canvas.height !==
|
|
849
|
-
const n = e / r,
|
|
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 +
|
|
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
|
|
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.
|
|
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 =
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
920
|
-
|
|
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 =
|
|
932
|
-
this.motionTarget.x =
|
|
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
|
-
|
|
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
|
|
1105
|
+
const c = Y(
|
|
1088
1106
|
a.frames,
|
|
1089
1107
|
a.meta.width,
|
|
1090
1108
|
a.meta.height
|
|
1091
|
-
), n =
|
|
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
|
|
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
|
|
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
|
|
1113
|
-
parallaxStrength:
|
|
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
|
|
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:
|
|
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
|
-
},
|
|
1189
|
+
}, c = () => {
|
|
1172
1190
|
n(), i(new Error("Failed to load video metadata."));
|
|
1173
1191
|
}, n = () => {
|
|
1174
|
-
e.removeEventListener("loadedmetadata", a), e.removeEventListener("error",
|
|
1192
|
+
e.removeEventListener("loadedmetadata", a), e.removeEventListener("error", c);
|
|
1175
1193
|
};
|
|
1176
|
-
e.addEventListener("loadedmetadata", a), e.addEventListener("error",
|
|
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
|
|
1202
|
+
function S(o, t, e) {
|
|
1185
1203
|
return Math.min(e, Math.max(t, o));
|
|
1186
1204
|
}
|
|
1187
|
-
function
|
|
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;
|
|
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;
|
|
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