lensfx 0.1.1 → 0.1.3

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.
@@ -0,0 +1,371 @@
1
+ "use strict";var lensfx=(()=>{var Ve=Object.defineProperty;var xt=Object.getOwnPropertyDescriptor;var Et=Object.getOwnPropertyNames;var _t=Object.prototype.hasOwnProperty;var Tt=(o,n)=>{for(var e in n)Ve(o,e,{get:n[e],enumerable:!0})},Rt=(o,n,e,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of Et(n))!_t.call(o,r)&&r!==e&&Ve(o,r,{get:()=>n[r],enumerable:!(t=xt(n,r))||t.enumerable});return o};var vt=o=>Rt(Ve({},"__esModule",{value:!0}),o);var Dt={};Tt(Dt,{DEFAULT_LENS_PARAMS:()=>at,QRRefractionRenderer:()=>Ie,SLIDER_DARK_OVERRIDES:()=>ct,SLIDER_GLASS_DEFAULTS:()=>lt,SLIDER_LIGHT_OVERRIDES:()=>mt,SLIDER_SAFARI_OVERRIDES:()=>dt,SWITCH_DARK_OVERRIDES:()=>st,SWITCH_GLASS_DEFAULTS:()=>it,SWITCH_LIGHT_OVERRIDES:()=>ut,VideoRefractionRenderer:()=>Be,colorMatrixValues:()=>Ge,computeDomeConstants:()=>Pe,createDisplacementMapGeneratorSync:()=>Le,createLens:()=>ot,domeGradient:()=>Me,erf:()=>Ce,generateDisplacementMapAsync:()=>nt,getSvgMaskDataUri:()=>Fe});function Ce(o){return Math.tanh(1.7724538509*o)}function tt(o,n){let e=0;for(let t=0;t<=200;t++){let r=t/200*n,s=r/Math.sqrt(o*o-r*r);e+=t===0||t===200?.5*s:s}return e/200}function Pe(o,n,e){let t=Math.max(.01,Math.min(o,Math.min(n,e)-1)),r=(n*n+t*t)/(2*t),s=(e*e+t*t)/(2*t),d=tt(r,n),f=tt(s,e);return{Rx:r,Ry:s,scaleX:d>0?.5/d:1,scaleY:f>0?.5/f:1}}function Me(o,n,e){let t=Math.min(o,.999*n);return t/Math.sqrt(n*n-t*t)*e}function Ge(o,n){return`${o} 0 0 0 ${.5*(1-o)} 0 ${n} 0 0 ${.5*(1-n)} 0 0 1 0 0 0 0 0 1 0`}var rt=new Map;function Fe(o,n,e){let t=Math.max(1,Math.round(o)),r=Math.max(1,Math.round(n)),s=Math.max(0,Math.min(Math.round(e),Math.min(t,r)/2)),d=`${t}|${r}|${s}`,f=rt.get(d);if(f)return{uri:f,key:d};let M=Math.max(0,t-1),m=Math.max(0,r-1),l=Math.max(0,s-.5),W=`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${t} ${r}' preserveAspectRatio='none'><rect x='0.5' y='0.5' width='${M}' height='${m}' rx='${l}' ry='${l}' fill='black'/></svg>`,a=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(W)}`;return rt.set(d,a),{uri:a,key:d}}function Le(o){let n=null,e=null,t=null,r=null,s=-1/0,d=-1/0,f=-1/0,M=null,m=0,l=!0;return{generate(W){n||(n=document.createElement("canvas"),n.width=o,n.height=o,e=n.getContext("2d"),t=e.createImageData(o,o));let{lensHalfWidth:a,lensHalfHeight:u,borderRadius:k,depth:$,sdfBoundary:ne,edgeFalloff:v,specularRotation:se=45,glowStrength:S=0,glowSpread:H=1,glowExponent:N=1.5,edgeStrength:Q=0,edgeWidth:oe=3,edgeExponent:me=1.5,domeDepth:j=0,splayAmount:Y=1}=W,p=t.data,O=o>>1,ue=Math.min(k,Math.min(a,u)),de=Math.max(0,a-$),B=Math.max(0,u-$),fe=Math.max(0,Math.min(k,Math.min(de,B))),i=$>0?1/($*Math.SQRT2):1e6,g=S>0||Q>0,E=se*Math.PI/180,_=Math.cos(E),y=Math.sin(E),L=(1-H)*Math.SQRT2,z=H*Math.SQRT2,D=z>.001?1/z:0,te=oe>0?1/oe:0,C=2*a/o,P=2*u/o,U=1/a,w=1/u,K=j>0,V=Y<1;if(K&&((!r||Math.abs(j-s)>.5||Math.abs(a-d)>1||Math.abs(u-f)>1)&&(r=Pe(j,a,u),s=j,d=a,f=u,l=!0),m!==O&&(M=new Float32Array(O),m=O,l=!0),l&&M&&r)){let h=r.Rx*r.Rx,b=.999*r.Rx;for(let T=0;T<O;T++){let q=-((T+.5)*C-a),pe=q<b?q:b;M[T]=pe/Math.sqrt(h-pe*pe)*r.scaleX}l=!1}let I=K?M:null,A=.5*Math.min(a,u),c=A>0?1/A:0,x=performance.now();for(let h=0;h<O;h++){let b=o-1-h,T=-((h+.5)*P-u),q=T-u+ue,pe=v?T-B+fe:0,De=K&&r?Me(T,r.Ry,r.scaleY):T*w>1?1:T*w,Ue=T*w>1?1:T*w,gt=V?Math.max(0,1-(u-T)*c):0;for(let he=0;he<O;he++){let We=o-1-he,be=-((he+.5)*C-a),Te=be-a+ue,Ne=Te>0?Te:0,Ye=q>0?q:0,Oe=Ne*Ne+Ye*Ye,Xe=(Oe>0?Math.sqrt(Oe):0)+(Te>q?Te>0?0:Te:q>0?0:q)-ue,Re=(h*o+he)*4,ve=(h*o+We)*4,Se=(b*o+he)*4,Ae=(b*o+We)*4;if(!ne||Xe<0){let ge=128,ze=128,qe=128,$e=128,xe=I?I[he]:be*U>1?1:be*U,Ee=De;if(V){let Z=1-Y,ee=gt*Z,ae=Math.max(0,1-(a-be)*c)*Z;if(ee>.001||ae>.001){let re=xe,le=Ee;xe=re*(1-ee),Ee=le*(1-ae);let we=Math.sqrt(re*re+le*le),ce=Math.sqrt(xe*xe+Ee*Ee);if(ce>.001){let ie=we/ce;xe*=ie,Ee*=ie}}}let ye=1;if(v){let Z=be-de+fe,ee=pe,ae=Z>0?Z:0,re=ee>0?ee:0,le=Math.sqrt(ae*ae+re*re)+(Z>ee?Z>0?0:Z:ee>0?0:ee)-fe;ye=.5*(1+Ce(le*i))}let Qe=.5*xe*ye,je=.5*Ee*ye,Ke=(.5+Qe)*255+.5|0,Je=(.5-Qe)*255+.5|0,Ze=(.5+je)*255+.5|0,et=(.5-je)*255+.5|0;if(g){let Z=(be*U>1?1:be*U)*_,ee=Ue*y,ae=Z+ee,re=Z-ee,le=ae<0?-ae:ae,we=re<0?-re:re,ce=0;Q>0&&(ce=Xe<0?1+Xe*te:0,ce<0&&(ce=0));let ie=0,_e=0;if(S>0){let ke=(le-L)*D;ie+=S*Math.pow(ke<0?0:ke>1?1:ke,N)*ye;let He=(we-L)*D;_e+=S*Math.pow(He<0?0:He>1?1:He,N)*ye}Q>0&&(ie+=Q*ce*Math.pow(le,me),_e+=Q*ce*Math.pow(we,me)),ie>1&&(ie=1),_e>1&&(_e=1),ge=127*ie+128+.5|0,$e=127*ie+128+.5|0,ze=127*_e+128+.5|0,qe=127*_e+128+.5|0}p[Re]=Ke,p[Re+1]=Ze,p[Re+2]=ge,p[Re+3]=255,p[ve]=Je,p[ve+1]=Ze,p[ve+2]=ze,p[ve+3]=255,p[Se]=Ke,p[Se+1]=et,p[Se+2]=qe,p[Se+3]=255,p[Ae]=Je,p[Ae+1]=et,p[Ae+2]=$e,p[Ae+3]=255}else for(let ge of[Re,ve,Se,Ae])p[ge]=128,p[ge+1]=128,p[ge+2]=128,p[ge+3]=255}}let X=performance.now()-x;e.putImageData(t,0,0);let G=performance.now(),F=n.toDataURL(),J=performance.now()-G;return{dataUrl:F,loopMs:X,encodeMs:J}},dispose(){n&&(n.width=0,n.height=0,n=null),e=null,t=null,r=null,s=-1/0,d=-1/0,f=-1/0,l=!0}}}async function nt(o,n){let{canvasSize:e,lensHalfWidth:t,lensHalfHeight:r,borderRadius:s,depth:d,sdfBoundary:f,edgeFalloff:M,specularRotation:m=45,glowStrength:l=0,glowSpread:W=1,glowExponent:a=1.5,edgeStrength:u=0,edgeWidth:k=3,edgeExponent:$=1.5,domeDepth:ne=0,splayAmount:v=1}=n;o.width=e,o.height=e;let se=o.getContext("2d");if(!se)return null;let S=se.createImageData(e,e),H=Math.min(s,Math.min(t,r)),N=Math.max(0,t-d),Q=Math.max(0,r-d),oe=Math.max(0,Math.min(s,Math.min(N,Q))),me=d>0?1/(d*Math.SQRT2):1e6,j=l>0||u>0,Y=m*Math.PI/180,p=Math.cos(Y),O=Math.sin(Y),ue=(1-W)*Math.SQRT2,de=W*Math.SQRT2,B=ne>0?Pe(ne,t,r):null,fe=v<1,i=.5*Math.min(t,r),g=i>0?1/i:0;for(let _=0;_<e;_+=64){let y=Math.min(_+64,e);for(let L=_;L<y;L++)for(let z=0;z<e;z++){let D=(L*e+z)*4,te=(z+.5)/e*(2*t)-t,C=(L+.5)/e*(2*r)-r,P=Math.abs(te),U=Math.abs(C),w=P-t+H,K=U-r+H,V=Math.max(w,0),I=Math.max(K,0),A=V*V+I*I,c=(A>0?Math.sqrt(A):0)+Math.min(Math.max(w,K),0)-H;if(!f||c<0){let x,X;B?(x=Math.sign(te)*Me(P,B.Rx,B.scaleX),X=Math.sign(C)*Me(U,B.Ry,B.scaleY)):(x=Math.max(-1,Math.min(1,te/t)),X=Math.max(-1,Math.min(1,C/r)));let G=x,F=X;if(fe){let h=Math.max(0,1-(r-U)*g)*(1-v),b=Math.max(0,1-(t-P)*g)*(1-v);if(h>.001||b>.001){let T=G,q=F;G=T*(1-h),F=q*(1-b);let pe=Math.sqrt(T*T+q*q),De=Math.sqrt(G*G+F*F);if(De>.001){let Ue=pe/De;G*=Ue,F*=Ue}}}let J=1;if(M){let h=P-N+oe,b=U-Q+oe,T=Math.sqrt(Math.max(h,0)**2+Math.max(b,0)**2)+Math.min(Math.max(h,b),0)-oe;J=.5*(1+Ce(T*me))}if(S.data[D]=Math.round((.5-.5*G*J)*255),S.data[D+1]=Math.round((.5-.5*F*J)*255),j){let h=Math.abs(Math.max(-1,Math.min(1,te/t))*p+Math.max(-1,Math.min(1,C/r))*O),b=0;if(l>0){let T=de>.001?Math.min(1,Math.max(0,h-ue)/de):0;b+=l*Math.pow(T,a)*J}if(u>0){let T=c<0?Math.max(0,1+c/k):0;b+=u*T*Math.pow(h,$)}b=Math.min(1,b),S.data[D+2]=Math.round(127*b+128)}else S.data[D+2]=128}else S.data[D]=128,S.data[D+1]=128,S.data[D+2]=128;S.data[D+3]=255}_+64<e&&await new Promise(L=>setTimeout(L,0))}se.putImageData(S,0,0);let E=await new Promise(_=>o.toBlob(_,"image/png"));return E?URL.createObjectURL(E):null}var R="http://www.w3.org/2000/svg",St=0;function ot(o,n={}){if(typeof document>"u")throw new Error("[lensfx] createLens can only be called in a browser environment.");let e=typeof o=="string"?document.querySelector(o):o;if(!e)throw new Error(`[lensfx] Target element "${o}" was not found.`);let t=e,r={...n},s=t;if(r.refractionTarget){let i=typeof r.refractionTarget=="string"?t.querySelector(r.refractionTarget)||document.querySelector(r.refractionTarget):r.refractionTarget;i&&(s=i)}let d=window.getComputedStyle(t),f=t.style.position;d.position==="static"&&(t.style.position="relative");let m=`${`lensfx-${++St}-${Math.random().toString(36).substring(2,7)}`}-filter`,l=document.createElementNS(R,"svg");l.setAttribute("class","lensfx-svg-root"),l.setAttribute("aria-hidden","true"),l.style.cssText="position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;left:0;top:0;";let W=document.createElementNS(R,"defs"),a=document.createElementNS(R,"filter");a.id=m,a.setAttribute("filterUnits","objectBoundingBox"),a.setAttribute("primitiveUnits","objectBoundingBox"),a.setAttribute("color-interpolation-filters","sRGB"),a.setAttribute("x","0"),a.setAttribute("y","0"),a.setAttribute("width","1"),a.setAttribute("height","1"),W.appendChild(a),l.appendChild(W),t.appendChild(l);let u=document.createElement("div");u.className="lensfx-lens-overlay",u.style.cssText="position:absolute;top:0;left:0;pointer-events:none;box-sizing:border-box;will-change:transform;",t.appendChild(u);let k=r.displacementMapUrl||"",$=r.mapSize||256,ne=Le($),v=null,se=null,S=!1,H=r.x??.5,N=r.y??.5;function Q(){let i=r.width??r.lensW??160,g=r.height??r.lensH??100,E=r.radius??r.borderRadius??Math.min(i,g)/4;return{width:i,height:g,radius:E}}function oe(){if(S)return;if(r.displacementMapUrl){k=r.displacementMapUrl,v&&v.setAttribute("href",k),r.onMapChange?.(k);return}let{width:i,height:g,radius:E}=Q(),_=r.mapSize||256;_!==$&&(ne.dispose(),$=_,ne=Le($));let y=r.depth??2;k=ne.generate({lensHalfWidth:i/2,lensHalfHeight:g/2,borderRadius:E,depth:y,sdfBoundary:r.sdfBoundary??!0,edgeFalloff:r.edgeFalloff??!0,specularRotation:r.specularRotation??45,glowStrength:r.glowStrength??.3,glowSpread:r.glowSpread??1,glowExponent:r.glowExponent??1.5,edgeStrength:r.edgeStrength??.4,edgeWidth:r.edgeWidth??3,edgeExponent:1.5,domeDepth:r.domeDepth??6,splayAmount:r.splayAmount??.8}).dataUrl,v&&v.setAttribute("href",k),r.onMapChange?.(k)}function me(){for(;a.firstChild;)a.removeChild(a.firstChild);let i=r.depth??2,g=r.chroma??r.chromaAmount??.6,E=r.scaleX??.25,_=r.scaleY??.25,y=Math.max(E,_),L=y>0?E/y:0,z=y>0?_/y:0,D=L!==1||z!==1,te=Ge(L,z),C=document.createElementNS(R,"feFlood");C.setAttribute("flood-color","rgb(128,128,128)"),C.setAttribute("flood-opacity","1"),C.setAttribute("result","mapBg"),a.appendChild(C),v=document.createElementNS(R,"feImage"),v.setAttribute("href",k),v.setAttribute("preserveAspectRatio","none"),v.setAttribute("result","rawMap"),a.appendChild(v);let P=document.createElementNS(R,"feComposite");if(P.setAttribute("in","rawMap"),P.setAttribute("in2","mapBg"),P.setAttribute("operator","over"),P.setAttribute("result","map"),a.appendChild(P),D){let c=document.createElementNS(R,"feColorMatrix");c.setAttribute("in","map"),c.setAttribute("type","matrix"),c.setAttribute("values",te),c.setAttribute("result","scaledMap"),a.appendChild(c)}let U=D?"scaledMap":"map",w="SourceGraphic";if(r.blur&&r.blur>0){let c=document.createElementNS(R,"feGaussianBlur");c.setAttribute("in","SourceGraphic");let x=t.getBoundingClientRect(),X=x.width>0?r.blur/x.width:.01,G=x.height>0?r.blur/x.height:.01;c.setAttribute("stdDeviation",`${X} ${G}`),c.setAttribute("result","blurred"),a.appendChild(c),w="blurred"}if(g>0){let c=document.createElementNS(R,"feDisplacementMap");c.setAttribute("in",w),c.setAttribute("in2",U),c.setAttribute("scale",String(y*(1+.2*g))),c.setAttribute("xChannelSelector","R"),c.setAttribute("yChannelSelector","G"),a.appendChild(c);let x=document.createElementNS(R,"feColorMatrix");x.setAttribute("type","matrix"),x.setAttribute("values","1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"),x.setAttribute("result","dispR"),a.appendChild(x);let X=document.createElementNS(R,"feDisplacementMap");X.setAttribute("in",w),X.setAttribute("in2",U),X.setAttribute("scale",String(y*(1+.1*g))),X.setAttribute("xChannelSelector","R"),X.setAttribute("yChannelSelector","G"),a.appendChild(X);let G=document.createElementNS(R,"feColorMatrix");G.setAttribute("type","matrix"),G.setAttribute("values","0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0"),G.setAttribute("result","dispG"),a.appendChild(G);let F=document.createElementNS(R,"feDisplacementMap");F.setAttribute("in",w),F.setAttribute("in2",U),F.setAttribute("scale",String(y)),F.setAttribute("xChannelSelector","R"),F.setAttribute("yChannelSelector","G"),a.appendChild(F);let J=document.createElementNS(R,"feColorMatrix");J.setAttribute("type","matrix"),J.setAttribute("values","0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0"),J.setAttribute("result","dispB"),a.appendChild(J);let h=document.createElementNS(R,"feComposite");h.setAttribute("in","dispR"),h.setAttribute("in2","dispG"),h.setAttribute("operator","arithmetic"),h.setAttribute("k1","0"),h.setAttribute("k2","1"),h.setAttribute("k3","1"),h.setAttribute("k4","0"),a.appendChild(h);let b=document.createElementNS(R,"feComposite");b.setAttribute("in2","dispB"),b.setAttribute("operator","arithmetic"),b.setAttribute("k1","0"),b.setAttribute("k2","1"),b.setAttribute("k3","1"),b.setAttribute("k4","0"),b.setAttribute("result","lensResult"),a.appendChild(b)}else{let c=document.createElementNS(R,"feDisplacementMap");c.setAttribute("in",w),c.setAttribute("in2",U),c.setAttribute("scale",String(y)),c.setAttribute("xChannelSelector","R"),c.setAttribute("yChannelSelector","G"),c.setAttribute("result","lensResult"),a.appendChild(c)}let K=r.specularStrength??1;if(K>0){let c=document.createElementNS(R,"feColorMatrix");c.setAttribute("in","map"),c.setAttribute("type","matrix"),c.setAttribute("values","0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 1 0 -0.50196"),c.setAttribute("result","specMask"),a.appendChild(c);let x=document.createElementNS(R,"feComposite");x.setAttribute("in","specMask"),x.setAttribute("in2","lensResult"),x.setAttribute("operator","arithmetic"),x.setAttribute("k1","0"),x.setAttribute("k2",String(K)),x.setAttribute("k3","1"),x.setAttribute("k4","0"),x.setAttribute("result","lensResult"),a.appendChild(x)}let V=document.createElementNS(R,"feFlood");V.setAttribute("flood-color","black"),V.setAttribute("flood-opacity","1"),V.setAttribute("result","lensMask"),a.appendChild(V);let I=document.createElementNS(R,"feComposite");I.setAttribute("in","SourceGraphic"),I.setAttribute("in2","lensMask"),I.setAttribute("operator","out"),I.setAttribute("result","holedSG"),a.appendChild(I);let A=document.createElementNS(R,"feComposite");A.setAttribute("in","lensResult"),A.setAttribute("in2","holedSG"),A.setAttribute("operator","over"),a.appendChild(A)}function j(){if(S)return;let i=t.getBoundingClientRect(),g=i.width||t.clientWidth||300,E=i.height||t.clientHeight||200,{width:_,height:y,radius:L}=Q(),z=H<=1&&H>=0?H*g:H,D=N<=1&&N>=0?N*E:te(N,E);function te(A,c){return A<=1&&A>=0?A*c:A}let C=z-_/2,P=D-y/2;v&&g>0&&E>0&&(v.setAttribute("x",String(C/g)),v.setAttribute("y",String(P/E)),v.setAttribute("width",String(_/g)),v.setAttribute("height",String(y/E))),u.style.width=`${_}px`,u.style.height=`${y}px`,u.style.borderRadius=`${L}px`,u.style.transform=`translate3d(${C}px, ${P}px, 0)`,r.shadow===!1?u.style.boxShadow="none":typeof r.shadow=="string"?u.style.boxShadow=r.shadow:u.style.boxShadow="0 8px 32px rgba(0, 0, 0, 0.2), 0 2px 8px rgba(0, 0, 0, 0.12), inset 0 1px 1px rgba(255, 255, 255, 0.35), inset 0 -1px 1px rgba(0, 0, 0, 0.15)",r.border===!1?u.style.border="none":typeof r.border=="string"?u.style.border=r.border:u.style.border="1px solid rgba(255, 255, 255, 0.2)";let U=r.tintColor??"rgba(255, 255, 255, 0.05)";u.style.background=U;let w=r.tintBlur??0;if(w>0){let A=`blur(${w}px)`;u.style.backdropFilter=A,u.style.setProperty("-webkit-backdrop-filter",A)}else u.style.backdropFilter="none",u.style.setProperty("-webkit-backdrop-filter","none");let{uri:K,key:V}=Fe(_,y,L);if(se!==V){let A=`url("${K}")`;u.style.maskImage=A,u.style.setProperty("-webkit-mask-image",A),u.style.maskSize="100% 100%",u.style.setProperty("-webkit-mask-size","100% 100%"),se=V}let I=`url("#${m}")`;s.style.filter!==I&&(s.style.filter=I)}let Y=!1,p=i=>{if(!r.interactive||S)return;let g=t.getBoundingClientRect(),E=i.clientX-g.left,_=i.clientY-g.top;ue(E,_)};function O(i){r.interactive=i,i&&!Y?(t.addEventListener("pointermove",p),Y=!0):!i&&Y&&(t.removeEventListener("pointermove",p),Y=!1)}function ue(i,g){H=i,N=g,r.onPositionChange?.(i,g),j()}function de(i){if(S)return;let g={...r};r={...r,...i},i.x!==void 0&&(H=i.x),i.y!==void 0&&(N=i.y),i.interactive!==void 0&&O(i.interactive);let E=i.width!==void 0||i.lensW!==void 0||i.height!==void 0||i.lensH!==void 0||i.radius!==void 0||i.borderRadius!==void 0||i.depth!==void 0||i.domeDepth!==void 0||i.specularRotation!==void 0||i.glowStrength!==void 0||i.glowSpread!==void 0||i.edgeStrength!==void 0||i.edgeWidth!==void 0||i.splayAmount!==void 0||i.displacementMapUrl!==void 0||i.mapSize!==void 0;E&&oe(),(i.chroma!==void 0||i.chromaAmount!==void 0||i.scaleX!==void 0||i.scaleY!==void 0||i.specularStrength!==void 0||i.blur!==void 0||E)&&me(),j()}let B=null;typeof ResizeObserver<"u"&&(B=new ResizeObserver(()=>{j()}),B.observe(t)),oe(),me(),j(),r.interactive&&O(!0);function fe(){S||(S=!0,Y&&(t.removeEventListener("pointermove",p),Y=!1),B&&(B.disconnect(),B=null),s.style.filter.includes(m)&&(s.style.filter=""),t.style.position==="relative"&&f===""&&(t.style.position=""),l.parentNode&&l.parentNode.removeChild(l),u.parentNode&&u.parentNode.removeChild(u),ne.dispose())}return{el:t,targetEl:s,svgEl:l,filterEl:a,overlayEl:u,get options(){return r},get mapDataUrl(){return k},setPosition:ue,update:de,setInteractive:O,destroy:fe}}var at={lensW:90,lensH:60,depth:0,chromaAmount:0,scaleX:0,scaleY:0,mapSize:256,borderRadius:0,blurAmount:0,sdfBoundary:!1,edgeFalloff:!1,brightness:0,specularStrength:0,specularRotation:0,glowStrength:0,glowSpread:1,glowExponent:1.5,tint:0,edgeStrength:0,edgeWidth:3,edgeExponent:1.5,specularDark:!1,domeDepth:0,splayAmount:0};var it={lensW:90,lensH:60,borderRadius:30,mapSize:256,depth:2,chromaAmount:1,scaleX:.25,scaleY:.25,sdfBoundary:!0,edgeFalloff:!0,domeDepth:6,splayAmount:.4,blurAmount:0,brightness:.06,specularStrength:1,specularRotation:45,specularDark:!1,tint:0,glowStrength:0,glowSpread:.5,glowExponent:1.5,edgeStrength:0,edgeWidth:2,edgeExponent:1.5,edgeShadow:"0 2px 6px rgba(0, 0, 0, 0.16)",edgeInsetShadow:"0 -4px 10px rgba(0, 0, 0, 0.12)"},st={brightness:.12,glowStrength:.4,edgeStrength:.5},ut={brightness:-.02,specularRotation:30,specularStrength:1.5,glowStrength:.4,glowSpread:.5,glowExponent:2,edgeStrength:1,edgeWidth:1.5,edgeExponent:1},lt={lensW:90,lensH:60,borderRadius:30,mapSize:256,depth:2,chromaAmount:.65,scaleX:.06,scaleY:.06,sdfBoundary:!0,edgeFalloff:!0,domeDepth:5,splayAmount:.5,blurAmount:0,brightness:.06,specularStrength:1.5,specularRotation:45,specularDark:!1,tint:0,glowStrength:.4,glowSpread:.5,glowExponent:1.5,edgeStrength:0,edgeWidth:3,edgeExponent:1.5,edgeShadow:"0 2px 6px rgba(0, 0, 0, 0.16)",edgeInsetShadow:"0 -4px 10px rgba(0, 0, 0, 0.12)",restEdgeShadow:"0 1.333px 5.333px var(--lensfx-shadow-strong, rgba(0,0,0,0.3))"},ct={scaleX:.133,scaleY:.135,brightness:.12,specularRotation:45,glowExponent:1.5,edgeStrength:.5,edgeWidth:1,edgeExponent:1.5},mt={scaleX:.1,scaleY:.1,brightness:-.02,specularRotation:30,glowExponent:2,edgeStrength:1,edgeWidth:1,edgeExponent:1},dt={scaleY:.25};var ft=`
2
+ attribute vec2 a_pos;
3
+ varying vec2 v_uv;
4
+ void main() {
5
+ // Flip Y so UV (0,0) = top-left, matching HTML/CSS coordinates.
6
+ v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
7
+ gl_Position = vec4(a_pos, 0.0, 1.0);
8
+ }
9
+ `,At=`
10
+ precision highp float;
11
+ uniform sampler2D u_source;
12
+ uniform vec2 u_dir;
13
+ varying vec2 v_uv;
14
+
15
+ void main() {
16
+ vec4 c = texture2D(u_source, v_uv) * 0.2042;
17
+ c += (texture2D(u_source, v_uv + 1.0 * u_dir) + texture2D(u_source, v_uv - 1.0 * u_dir)) * 0.1801;
18
+ c += (texture2D(u_source, v_uv + 2.0 * u_dir) + texture2D(u_source, v_uv - 2.0 * u_dir)) * 0.1240;
19
+ c += (texture2D(u_source, v_uv + 3.0 * u_dir) + texture2D(u_source, v_uv - 3.0 * u_dir)) * 0.0663;
20
+ c += (texture2D(u_source, v_uv + 4.0 * u_dir) + texture2D(u_source, v_uv - 4.0 * u_dir)) * 0.0276;
21
+ gl_FragColor = c;
22
+ }
23
+ `,yt=`
24
+ #extension GL_OES_standard_derivatives : enable
25
+ precision highp float;
26
+
27
+ uniform sampler2D u_video;
28
+ uniform sampler2D u_map;
29
+ uniform sampler2D u_blurred;
30
+ uniform float u_baseScale[3];
31
+ uniform float u_ratioX[3];
32
+ uniform float u_ratioY[3];
33
+ uniform float u_chromaAmount;
34
+ uniform float u_specStrength;
35
+ uniform float u_adaptStrength;
36
+ uniform float u_specLumaLow;
37
+ uniform float u_specLumaHigh;
38
+ uniform float u_hasBlur;
39
+ uniform vec4 u_bbox; // (x, y, w, h) normalised, y=0 at top
40
+ uniform vec3 u_circles[3]; // (cx, cy, radius) in bbox pixel space
41
+ uniform float u_scale[3]; // per-circle geometric press scale (1 = unscaled)
42
+ uniform vec4 u_bar; // (cx, cy, w, h) in bbox pixel space; w<=0 means inactive
43
+ uniform float u_barRadius; // corner radius for the rounded-rect bar lens
44
+ uniform float u_barBaseScale;
45
+ uniform float u_barRatioX;
46
+ uniform float u_barRatioY;
47
+ uniform vec2 u_bboxSize; // bbox (width, height) in pixels
48
+
49
+ varying vec2 v_uv;
50
+
51
+ void main() {
52
+ vec2 uv = v_uv;
53
+ vec2 bMin = u_bbox.xy;
54
+ vec2 bSize = u_bbox.zw;
55
+ vec2 bMax = bMin + bSize;
56
+
57
+ // Outside bounding box -> pass-through video
58
+ if (uv.x < bMin.x || uv.x > bMax.x || uv.y < bMin.y || uv.y > bMax.y) {
59
+ gl_FragColor = texture2D(u_video, uv);
60
+ return;
61
+ }
62
+
63
+ // Map fragment UV -> displacement texture UV
64
+ vec2 mUV = (uv - bMin) / bSize;
65
+
66
+ // Analytical SDF mask (pixel-perfect at any resolution). Tracks the
67
+ // dominant region so per-region scale/ratio can be picked up via the
68
+ // loop-constant index (safe in WebGL 1). After the circle loop we test the
69
+ // rounded-rect "bar" region (when active) and take whichever has the
70
+ // larger mask value. domCenter/domScale track the dominant lens so the
71
+ // displacement map is sampled in its (press-)scaled space below.
72
+ vec2 pxPos = mUV * u_bboxSize;
73
+ float mask = 0.0;
74
+ float baseScale = 0.0;
75
+ float ratioX = 0.0;
76
+ float ratioY = 0.0;
77
+
78
+ // Map-sample scale assignment, tracked SEPARATELY from the tight SDF mask: a
79
+ // pixel adopts a circle's press scale across the union of its original and
80
+ // scaled radius (R * max(1, s)). That way the annulus a shrunk lens vacates
81
+ // samples empty space instead of leaving the original rim stuck behind.
82
+ // domScale = 1 (bar + background) -> identity sample.
83
+ vec2 domCenter = pxPos;
84
+ float domScale = 1.0;
85
+ float domDist = 1.0; // nearest normalised assignment distance (<1 = inside)
86
+
87
+ for (int i = 0; i < 3; i++) {
88
+ if (u_circles[i].z < 0.1) continue; // skip inactive circles
89
+ float s = max(u_scale[i], 0.001);
90
+ float R = u_circles[i].z;
91
+ float rho = length(pxPos - u_circles[i].xy);
92
+
93
+ // Visible lens SDF at the scaled radius -> blur / specular gating.
94
+ float dist = rho - R * s;
95
+ float aa = fwidth(dist);
96
+ float m = 1.0 - smoothstep(-aa, aa, dist);
97
+ if (m > mask) {
98
+ mask = m;
99
+ baseScale = u_baseScale[i];
100
+ ratioX = u_ratioX[i];
101
+ ratioY = u_ratioY[i];
102
+ }
103
+
104
+ // Scale assignment over max(original, scaled) radius, PLUS a small FIXED
105
+ // pixel margin so the region boundary clears the map's hard content edge at
106
+ // r = R. A *fractional* margin scales with R, so a big lens (play) would
107
+ // swallow its neighbours' regions and drag their rings in. 4px clears the
108
+ // edge's AA band without ever reaching the gap to the next control.
109
+ float nd = rho / (R * max(1.0, s) + 4.0);
110
+ if (nd < domDist) {
111
+ domDist = nd;
112
+ domCenter = u_circles[i].xy;
113
+ domScale = s;
114
+ }
115
+ }
116
+
117
+ // Bar (rounded-rect) SDF - only when u_bar.zw > 0. The bar never scales, so
118
+ // it keeps the identity map sample (domScale stays 1 for bar + background).
119
+ if (u_bar.z > 0.1 && u_bar.w > 0.1) {
120
+ vec2 q = abs(pxPos - u_bar.xy) - u_bar.zw * 0.5 + vec2(u_barRadius);
121
+ float barDist =
122
+ length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - u_barRadius;
123
+ float aaBar = fwidth(barDist);
124
+ float mBar = 1.0 - smoothstep(-aaBar, aaBar, barDist);
125
+ if (mBar > mask) {
126
+ mask = mBar;
127
+ baseScale = u_barBaseScale;
128
+ ratioX = u_barRatioX;
129
+ ratioY = u_barRatioY;
130
+ }
131
+ }
132
+
133
+ // Sample the displacement map at the dominant lens's scaled coordinate, so a
134
+ // per-lens press scale shrinks the baked pattern around its center in
135
+ // lockstep with the SDF radius above. domScale = 1 -> identity (unscaled).
136
+ vec2 scaledPx = domCenter + (pxPos - domCenter) / domScale;
137
+ vec4 d = texture2D(u_map, scaledPx / u_bboxSize);
138
+
139
+ // mapMatrix (feColorMatrix equivalent)
140
+ float sr = d.r * ratioX + 0.5 * (1.0 - ratioX);
141
+ float sg = d.g * ratioY + 0.5 * (1.0 - ratioY);
142
+
143
+ // Displacement offset in full-video UV space
144
+ vec2 off = vec2(sr - 0.5, sg - 0.5) * baseScale;
145
+
146
+ // Choose source: blurred or raw video
147
+ // Inside lens -> blurred (if blur active), outside lens -> raw
148
+ // Blend by mask so the transition at edges is clean
149
+ vec4 color;
150
+ if (u_chromaAmount > 0.001) {
151
+ float sR = 1.0 + u_chromaAmount * 0.2;
152
+ float sG = 1.0 + u_chromaAmount * 0.1;
153
+ if (u_hasBlur > 0.5) {
154
+ color.r = mix(
155
+ texture2D(u_video, clamp(uv + off * sR, 0.0, 1.0)).r,
156
+ texture2D(u_blurred, clamp(uv + off * sR, 0.0, 1.0)).r,
157
+ mask
158
+ );
159
+ color.g = mix(
160
+ texture2D(u_video, clamp(uv + off * sG, 0.0, 1.0)).g,
161
+ texture2D(u_blurred, clamp(uv + off * sG, 0.0, 1.0)).g,
162
+ mask
163
+ );
164
+ color.b = mix(
165
+ texture2D(u_video, clamp(uv + off, 0.0, 1.0)).b,
166
+ texture2D(u_blurred, clamp(uv + off, 0.0, 1.0)).b,
167
+ mask
168
+ );
169
+ } else {
170
+ color.r = texture2D(u_video, clamp(uv + off * sR, 0.0, 1.0)).r;
171
+ color.g = texture2D(u_video, clamp(uv + off * sG, 0.0, 1.0)).g;
172
+ color.b = texture2D(u_video, clamp(uv + off, 0.0, 1.0)).b;
173
+ }
174
+ color.a = 1.0;
175
+ } else {
176
+ vec2 duv = clamp(uv + off, 0.0, 1.0);
177
+ if (u_hasBlur > 0.5) {
178
+ color = mix(texture2D(u_video, duv), texture2D(u_blurred, duv), mask);
179
+ } else {
180
+ color = texture2D(u_video, duv);
181
+ }
182
+ }
183
+
184
+ // Adaptive specular + brightness (Apple-style vibrancy)
185
+ // Compute perceptual luminance of the displaced video sample
186
+ float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114));
187
+
188
+ // Specular: blend between additive (dark bg) and multiplicative (bright bg)
189
+ float spec = d.b - 0.502;
190
+ float lumaLo = min(u_specLumaLow, u_specLumaHigh);
191
+ float lumaHi = max(u_specLumaLow, u_specLumaHigh);
192
+ float darkBlend = smoothstep(lumaLo, lumaHi, luma);
193
+ vec3 specAdd = color.rgb + spec * u_specStrength;
194
+ vec3 specMul = color.rgb * (1.0 - spec * u_specStrength);
195
+ color.rgb = mix(specAdd, specMul, darkBlend);
196
+ color.rgb = max(color.rgb, vec3(0.0));
197
+
198
+ // Brightness: pull toward mid-gray - darkens bright areas, brightens dark
199
+ float correction = (0.5 - luma) * u_adaptStrength * mask;
200
+ color.rgb += correction;
201
+
202
+ gl_FragColor = color;
203
+ }
204
+ `;function pt(o,n,e){let t=o.createShader(n);return t?(o.shaderSource(t,e),o.compileShader(t),o.getShaderParameter(t,o.COMPILE_STATUS)?t:(console.error("Shader compile error:",o.getShaderInfoLog(t)),o.deleteShader(t),null)):null}function ht(o,n,e){let t=pt(o,o.VERTEX_SHADER,n),r=pt(o,o.FRAGMENT_SHADER,e);if(!t||!r)return null;let s=o.createProgram();return s?(o.attachShader(s,t),o.attachShader(s,r),o.linkProgram(s),o.detachShader(s,t),o.detachShader(s,r),o.deleteShader(t),o.deleteShader(r),o.getProgramParameter(s,o.LINK_STATUS)?s:(console.error("Program link error:",o.getProgramInfoLog(s)),o.deleteProgram(s),null)):null}var Be=class{constructor(n){this.blurFboA=null;this.blurTexA=null;this.blurFboB=null;this.blurTexB=null;this.fboWidth=0;this.fboHeight=0;let e=n.getContext("webgl",{alpha:!1,antialias:!1,premultipliedAlpha:!1});if(!e)throw new Error("WebGL not supported");this.gl=e,e.getExtension("OES_standard_derivatives");let t=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.quadBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.quadBuffer),e.bufferData(e.ARRAY_BUFFER,t,e.STATIC_DRAW),this.blurProgram=ht(e,ft,At),this.refractionProgram=ht(e,ft,yt),this.videoTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.videoTexture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),this.mapTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.mapTexture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR)}setDisplacementMap(n){let e=this.gl;e.bindTexture(e.TEXTURE_2D,this.mapTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,n)}initBlurFBO(n,e){let t=this.gl,r=n>>1,s=e>>1;if(this.fboWidth===r&&this.fboHeight===s)return;this.fboWidth=r,this.fboHeight=s;let d=()=>{let m=t.createTexture();t.bindTexture(t.TEXTURE_2D,m),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,r,s,0,t.RGBA,t.UNSIGNED_BYTE,null);let l=t.createFramebuffer();return t.bindFramebuffer(t.FRAMEBUFFER,l),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,m,0),{fbo:l,tex:m}},f=d();this.blurFboA=f.fbo,this.blurTexA=f.tex;let M=d();this.blurFboB=M.fbo,this.blurTexB=M.tex,t.bindFramebuffer(t.FRAMEBUFFER,null)}render(n,e){let t=this.gl,r=t.canvas.width,s=t.canvas.height;if(t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.videoTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,n),e.hasBlur){this.initBlurFBO(r,s),t.bindFramebuffer(t.FRAMEBUFFER,this.blurFboA),t.viewport(0,0,this.fboWidth,this.fboHeight),t.useProgram(this.blurProgram);let a=t.getAttribLocation(this.blurProgram,"a_pos");t.bindBuffer(t.ARRAY_BUFFER,this.quadBuffer),t.enableVertexAttribArray(a),t.vertexAttribPointer(a,2,t.FLOAT,!1,0,0),t.uniform1i(t.getUniformLocation(this.blurProgram,"u_source"),0),t.uniform2f(t.getUniformLocation(this.blurProgram,"u_dir"),1/this.fboWidth,0),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindFramebuffer(t.FRAMEBUFFER,this.blurFboB),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.blurTexA),t.uniform1i(t.getUniformLocation(this.blurProgram,"u_source"),2),t.uniform2f(t.getUniformLocation(this.blurProgram,"u_dir"),0,1/this.fboHeight),t.drawArrays(t.TRIANGLE_STRIP,0,4)}t.bindFramebuffer(t.FRAMEBUFFER,null),t.viewport(0,0,r,s),t.useProgram(this.refractionProgram);let d=t.getAttribLocation(this.refractionProgram,"a_pos");t.bindBuffer(t.ARRAY_BUFFER,this.quadBuffer),t.enableVertexAttribArray(d),t.vertexAttribPointer(d,2,t.FLOAT,!1,0,0),t.uniform1i(t.getUniformLocation(this.refractionProgram,"u_video"),0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.mapTexture),t.uniform1i(t.getUniformLocation(this.refractionProgram,"u_map"),1),e.hasBlur&&this.blurTexB?(t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,this.blurTexB),t.uniform1i(t.getUniformLocation(this.refractionProgram,"u_blurred"),2),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_hasBlur"),1)):t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_hasBlur"),0);let f=new Float32Array(9),M=new Float32Array(3),m=new Float32Array(3),l=new Float32Array(3),W=new Float32Array(3);for(let a=0;a<3;a++)if(a<e.circles.length){let u=e.circles[a];f[a*3+0]=u.cx,f[a*3+1]=u.cy,f[a*3+2]=u.radius,M[a]=u.scale,m[a]=u.baseScale,l[a]=u.ratioX,W[a]=u.ratioY}t.uniform3fv(t.getUniformLocation(this.refractionProgram,"u_circles"),f),t.uniform1fv(t.getUniformLocation(this.refractionProgram,"u_scale"),M),t.uniform1fv(t.getUniformLocation(this.refractionProgram,"u_baseScale"),m),t.uniform1fv(t.getUniformLocation(this.refractionProgram,"u_ratioX"),l),t.uniform1fv(t.getUniformLocation(this.refractionProgram,"u_ratioY"),W),e.bar?(t.uniform4f(t.getUniformLocation(this.refractionProgram,"u_bar"),e.bar.cx,e.bar.cy,e.bar.w,e.bar.h),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_barRadius"),e.bar.radius),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_barBaseScale"),e.bar.baseScale),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_barRatioX"),e.bar.ratioX),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_barRatioY"),e.bar.ratioY)):t.uniform4f(t.getUniformLocation(this.refractionProgram,"u_bar"),0,0,-1,-1),t.uniform4f(t.getUniformLocation(this.refractionProgram,"u_bbox"),e.bbox.x,e.bbox.y,e.bbox.w,e.bbox.h),t.uniform2f(t.getUniformLocation(this.refractionProgram,"u_bboxSize"),e.bboxSize.w,e.bboxSize.h),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_chromaAmount"),e.chromaAmount),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_specStrength"),e.specStrength),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_adaptStrength"),e.adaptStrength),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_specLumaLow"),e.specLumaLow),t.uniform1f(t.getUniformLocation(this.refractionProgram,"u_specLumaHigh"),e.specLumaHigh),t.drawArrays(t.TRIANGLE_STRIP,0,4)}dispose(){let n=this.gl;n.deleteBuffer(this.quadBuffer),n.deleteProgram(this.blurProgram),n.deleteProgram(this.refractionProgram),n.deleteTexture(this.videoTexture),n.deleteTexture(this.mapTexture),this.blurFboA&&n.deleteFramebuffer(this.blurFboA),this.blurTexA&&n.deleteTexture(this.blurTexA),this.blurFboB&&n.deleteFramebuffer(this.blurFboB),this.blurTexB&&n.deleteTexture(this.blurTexB)}};var Mt=`#version 300 es
205
+ in vec2 a_position;
206
+ out vec2 v_uv;
207
+
208
+ void main() {
209
+ v_uv = (a_position * 0.5) + 0.5;
210
+ gl_Position = vec4(a_position, 0.0, 1.0);
211
+ }
212
+ `,Lt=`#version 300 es
213
+ precision highp float;
214
+ precision highp sampler2D;
215
+
216
+ in vec2 v_uv;
217
+ out vec4 fragColor;
218
+
219
+ uniform float u_dotRadius;
220
+ uniform vec3 u_backgroundColor;
221
+ uniform sampler2D u_PaintingTexture;
222
+
223
+ // QR dot grid for the O(1) occupancy lookup (replaces a per-pixel scan over
224
+ // every dot). Occupancy is matrixLength x matrixLength, R8, 0/1 per module.
225
+ uniform sampler2D u_occupancyTexture;
226
+ uniform float u_gridOriginUV; // padding / size, in UV
227
+ uniform float u_cellUV; // cellSize / size, in UV
228
+ uniform float u_invCellUV; // 1 / cellUV - avoids a per-pixel divide
229
+ uniform int u_matrixLength;
230
+
231
+ uniform sampler2D u_displacementMap;
232
+ uniform sampler2D u_paintingColorTexture;
233
+ uniform int u_displacementActive;
234
+ uniform vec2 u_lensOrigin;
235
+ uniform vec2 u_lensSize;
236
+ uniform vec2 u_displacementScale;
237
+ uniform float u_chromaAmount;
238
+
239
+ // Eye uniforms (3 corner finder groups)
240
+ uniform vec2 u_eyeCenter[3];
241
+ uniform vec3 u_eyeHalf[3]; // x=outer, y=mid, z=inner half-size
242
+ uniform vec3 u_eyeRadius[3]; // x=outer, y=mid, z=inner corner radius
243
+ uniform vec3 u_eyeColor[3]; // fill color per group (animated)
244
+ uniform float u_eyeScale[3]; // hover scale per group
245
+ uniform float u_eyeRefractionScale; // 0-1 multiplier for eye displacement
246
+
247
+ // QR dots sit on a uniform grid, and the radius (~0.35 of a cell) never
248
+ // spills past a cell boundary, so the nearest dot is always the one in pos's
249
+ // own cell. Map pos -> module (i,j), check occupancy, then test distance to
250
+ // that module's center.
251
+ float testDot(vec2 pos, float r2) {
252
+ int i = int(floor((pos.x - u_gridOriginUV) * u_invCellUV));
253
+ int j = int(floor((pos.y - u_gridOriginUV) * u_invCellUV));
254
+ if (i < 0 || i >= u_matrixLength || j < 0 || j >= u_matrixLength)
255
+ return 1.0;
256
+ if (texelFetch(u_occupancyTexture, ivec2(i, j), 0).r < 0.5)
257
+ return 1.0;
258
+ vec2 c = vec2(u_gridOriginUV) + (vec2(float(i), float(j)) + 0.5) * u_cellUV;
259
+ vec2 d = pos - c;
260
+ return dot(d, d) < r2 ? 0.0 : 1.0;
261
+ }
262
+
263
+ float roundedRectSDF(vec2 p, float half_, float radius) {
264
+ vec2 d = abs(p) - vec2(half_) + vec2(radius);
265
+ return length(max(d, vec2(0.0))) + min(max(d.x, d.y), 0.0) - radius;
266
+ }
267
+
268
+ // Test all eye groups. Returns vec4(color, 1.0) if inside an eye, vec4(0) if not.
269
+ vec4 testEyes(vec2 pos) {
270
+ for (int g = 0; g < 3; g++) {
271
+ vec2 local = (pos - u_eyeCenter[g]) / u_eyeScale[g];
272
+ if (roundedRectSDF(local, u_eyeHalf[g].z, u_eyeRadius[g].z) < 0.0)
273
+ return vec4(u_eyeColor[g], 1.0);
274
+ if (roundedRectSDF(local, u_eyeHalf[g].y, u_eyeRadius[g].y) < 0.0)
275
+ return vec4(u_backgroundColor, 1.0);
276
+ if (roundedRectSDF(local, u_eyeHalf[g].x, u_eyeRadius[g].x) < 0.0)
277
+ return vec4(u_eyeColor[g], 1.0);
278
+ }
279
+ return vec4(0.0);
280
+ }
281
+
282
+ // Test scene (eyes + dots) at a position, returning color for a non-displaced pixel.
283
+ // Returns vec4(color, 1.0) for solid, vec4(0, 0, 0, -1.0) for dot hole (discard).
284
+ vec4 sampleStatic(vec2 pos, float r2) {
285
+ vec4 eye = testEyes(pos);
286
+ if (eye.a > 0.5) return eye;
287
+ float hole = testDot(pos, r2);
288
+ if (hole < 0.5) return vec4(0.0, 0.0, 0.0, -1.0);
289
+ return vec4(u_backgroundColor, 1.0);
290
+ }
291
+
292
+ void main() {
293
+ vec2 uv = vec2(v_uv.x, 1.0 - v_uv.y);
294
+ float paint = texture(u_PaintingTexture, uv).r;
295
+ float r2 = pow(u_dotRadius * (1.0 - paint), 2.0);
296
+
297
+ if (u_displacementActive == 0) {
298
+ vec4 s = sampleStatic(uv, r2);
299
+ if (s.a < 0.0) discard;
300
+ fragColor = s;
301
+ return;
302
+ }
303
+
304
+ vec2 lensUV = (uv - u_lensOrigin) / u_lensSize;
305
+ bool insideLens = lensUV.x >= 0.0 && lensUV.x <= 1.0 &&
306
+ lensUV.y >= 0.0 && lensUV.y <= 1.0;
307
+
308
+ if (!insideLens) {
309
+ vec4 s = sampleStatic(uv, r2);
310
+ if (s.a < 0.0) discard;
311
+ fragColor = s;
312
+ return;
313
+ }
314
+
315
+ vec4 dispSample = texture(u_displacementMap, lensUV);
316
+ if (dispSample.a < 0.01) {
317
+ vec4 s = sampleStatic(uv, r2);
318
+ if (s.a < 0.0) discard;
319
+ fragColor = s;
320
+ return;
321
+ }
322
+ vec2 disp = (dispSample.rg - 0.5) * u_displacementScale;
323
+
324
+ float scaleR = 1.0 + u_chromaAmount * 2.0;
325
+ float scaleG = 1.0 + u_chromaAmount * 1.0;
326
+
327
+ vec2 uvR = uv + disp * scaleR;
328
+ vec2 uvG = uv + disp * scaleG;
329
+ vec2 uvB = uv + disp;
330
+
331
+ // Attenuated displacement for eyes
332
+ vec2 eyeDisp = disp * u_eyeRefractionScale;
333
+ vec2 eyeUvR = uv + eyeDisp * scaleR;
334
+ vec2 eyeUvG = uv + eyeDisp * scaleG;
335
+ vec2 eyeUvB = uv + eyeDisp;
336
+
337
+ // Per-channel: test eyes at attenuated displacement, dots at full displacement
338
+ vec4 eyeR = testEyes(eyeUvR);
339
+ vec4 eyeG = testEyes(eyeUvG);
340
+ vec4 eyeB = testEyes(eyeUvB);
341
+
342
+ float r, g, b;
343
+
344
+ if (eyeR.a > 0.5) {
345
+ r = eyeR.r;
346
+ } else {
347
+ float holeR = testDot(uvR, r2);
348
+ float paintR = texture(u_paintingColorTexture, uvR).r;
349
+ r = mix(paintR, u_backgroundColor.r, holeR);
350
+ }
351
+
352
+ if (eyeG.a > 0.5) {
353
+ g = eyeG.g;
354
+ } else {
355
+ float holeG = testDot(uvG, r2);
356
+ float paintG = texture(u_paintingColorTexture, uvG).g;
357
+ g = mix(paintG, u_backgroundColor.g, holeG);
358
+ }
359
+
360
+ if (eyeB.a > 0.5) {
361
+ b = eyeB.b;
362
+ } else {
363
+ float holeB = testDot(uvB, r2);
364
+ float paintB = texture(u_paintingColorTexture, uvB).b;
365
+ b = mix(paintB, u_backgroundColor.b, holeB);
366
+ }
367
+
368
+ fragColor = vec4(r, g, b, 1.0);
369
+ }
370
+ `;function bt(o,n,e){let t=o.createShader(n);if(!t)throw new Error("Failed to create shader");if(o.shaderSource(t,e),o.compileShader(t),!o.getShaderParameter(t,o.COMPILE_STATUS)){let r=o.getShaderInfoLog(t);throw o.deleteShader(t),new Error(`Shader compilation error: ${r??""}`)}return t}var Ie=class{constructor(n){let e=n.canvas.getContext("webgl2",{alpha:!0,antialias:!1,premultipliedAlpha:!1});if(!e)throw new Error("WebGL 2 not supported");this.gl=e,this.matrixLength=n.matrixLength,this.gridOriginUV=n.gridOriginUV,this.cellUV=n.cellUV,this.dotRadius=n.dotRadius,this.backgroundColor=n.backgroundColor??[1,1,1];let t=bt(e,e.VERTEX_SHADER,Mt),r=bt(e,e.FRAGMENT_SHADER,Lt),s=e.createProgram();if(e.attachShader(s,t),e.attachShader(s,r),e.linkProgram(s),!e.getProgramParameter(s,e.LINK_STATUS))throw new Error(`QR Program link error: ${e.getProgramInfoLog(s)??""}`);this.program=s;let d=new Float32Array([-1,-1,1,-1,-1,1,1,1]);this.quadBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.quadBuffer),e.bufferData(e.ARRAY_BUFFER,d,e.STATIC_DRAW),this.occupancyTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.occupancyTexture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texImage2D(e.TEXTURE_2D,0,e.R8,this.matrixLength,this.matrixLength,0,e.RED,e.UNSIGNED_BYTE,n.occupancyMatrix),this.displacementTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.displacementTexture),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR);let f=new Uint8Array([0,0,0,0]);this.paintingTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.paintingTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,1,1,0,e.RGBA,e.UNSIGNED_BYTE,f),this.paintingColorTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.paintingColorTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,1,1,0,e.RGBA,e.UNSIGNED_BYTE,f)}setDisplacementMap(n){let e=this.gl;e.bindTexture(e.TEXTURE_2D,this.displacementTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,n)}render(n){let e=this.gl;e.viewport(0,0,e.canvas.width,e.canvas.height),e.useProgram(this.program);let t=e.getAttribLocation(this.program,"a_position");e.bindBuffer(e.ARRAY_BUFFER,this.quadBuffer),e.enableVertexAttribArray(t),e.vertexAttribPointer(t,2,e.FLOAT,!1,0,0),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.occupancyTexture),e.uniform1i(e.getUniformLocation(this.program,"u_occupancyTexture"),0),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.displacementTexture),e.uniform1i(e.getUniformLocation(this.program,"u_displacementMap"),1),e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,this.paintingTexture),e.uniform1i(e.getUniformLocation(this.program,"u_PaintingTexture"),2),e.activeTexture(e.TEXTURE3),e.bindTexture(e.TEXTURE_2D,this.paintingColorTexture),e.uniform1i(e.getUniformLocation(this.program,"u_paintingColorTexture"),3),e.uniform1f(e.getUniformLocation(this.program,"u_dotRadius"),this.dotRadius),e.uniform3fv(e.getUniformLocation(this.program,"u_backgroundColor"),this.backgroundColor),e.uniform1f(e.getUniformLocation(this.program,"u_gridOriginUV"),this.gridOriginUV),e.uniform1f(e.getUniformLocation(this.program,"u_cellUV"),this.cellUV),e.uniform1f(e.getUniformLocation(this.program,"u_invCellUV"),1/this.cellUV),e.uniform1i(e.getUniformLocation(this.program,"u_matrixLength"),this.matrixLength),e.uniform1i(e.getUniformLocation(this.program,"u_displacementActive"),n.displacementActive?1:0),e.uniform2f(e.getUniformLocation(this.program,"u_lensOrigin"),n.lensOrigin[0],n.lensOrigin[1]),e.uniform2f(e.getUniformLocation(this.program,"u_lensSize"),n.lensSize[0],n.lensSize[1]),e.uniform2f(e.getUniformLocation(this.program,"u_displacementScale"),n.displacementScale[0],n.displacementScale[1]),e.uniform1f(e.getUniformLocation(this.program,"u_chromaAmount"),n.chromaAmount),e.uniform1f(e.getUniformLocation(this.program,"u_eyeRefractionScale"),n.eyeRefractionScale??.2);let r=new Float32Array(6),s=new Float32Array(9),d=new Float32Array(9),f=new Float32Array(9),M=new Float32Array(3);for(let m=0;m<3;m++)if(m<n.eyes.length){let l=n.eyes[m];r[m*2+0]=l.center[0],r[m*2+1]=l.center[1],s[m*3+0]=l.half[0],s[m*3+1]=l.half[1],s[m*3+2]=l.half[2],d[m*3+0]=l.radius[0],d[m*3+1]=l.radius[1],d[m*3+2]=l.radius[2],f[m*3+0]=l.color[0],f[m*3+1]=l.color[1],f[m*3+2]=l.color[2],M[m]=l.scale}e.uniform2fv(e.getUniformLocation(this.program,"u_eyeCenter"),r),e.uniform3fv(e.getUniformLocation(this.program,"u_eyeHalf"),s),e.uniform3fv(e.getUniformLocation(this.program,"u_eyeRadius"),d),e.uniform3fv(e.getUniformLocation(this.program,"u_eyeColor"),f),e.uniform1fv(e.getUniformLocation(this.program,"u_eyeScale"),M),e.drawArrays(e.TRIANGLE_STRIP,0,4)}dispose(){let n=this.gl;n.deleteBuffer(this.quadBuffer),n.deleteProgram(this.program),n.deleteTexture(this.occupancyTexture),n.deleteTexture(this.displacementTexture),n.deleteTexture(this.paintingTexture),n.deleteTexture(this.paintingColorTexture)}};return vt(Dt);})();
371
+ //# sourceMappingURL=lensfx.min.js.map