1import{r as P,F as B,p as C,j as I}from"./index-DzYirT9B.js";const U=`#version 300 es 2precision highp float; 3in vec2 a_pos; 4void main() { 5 gl_Position = vec4(a_pos, 0.0, 1.0); 6}`,M=`#version 300 es 7precision mediump float; 8uniform float u_time; 9uniform vec2 u_res; 10uniform vec2 u_mouse; 11out vec4 fragColor; 12 13void main() { 14 vec2 uv = gl_FragCoord.xy / u_res; 15 uv.y = 1.0 - uv.y; 16 17 // ââ Primary specular blob (Gaussian, mouse-driven + slow liquid drift) ââ 18 vec2 specPos = vec2( 19 0.20 + u_mouse.x * 0.42 + 0.06 * sin(u_time * 0.41), 20 0.15 + u_mouse.y * 0.26 + 0.04 * cos(u_time * 0.29) 21 ); 22 float d1 = dot(uv - specPos, uv - specPos); 23 float spec = exp(-d1 * 8.5) * 0.72; 24 25 // ââ Secondary catch-light (tight, offset â two-point glass lighting) ââ 26 vec2 spec2Pos = specPos + vec2( 27 0.09 * cos(u_time * 0.19), 28 -0.07 * sin(u_time * 0.23) 29 ); 30 float d2 = dot(uv - spec2Pos, uv - spec2Pos); 31 float spec2 = exp(-d2 * 32.0) * 0.38; 32 33 // ââ Top-edge bevel (dominant â pane lit from above) âââââââââââââââââââ 34 float topBevel = pow(max(0.0, 1.0 - uv.y * 4.0), 2.0) * 0.40; 35 float leftBevel = pow(max(0.0, 1.0 - uv.x * 5.5), 2.0) * 0.15; 36 37 // ââ Fresnel rim glow on bottom + right edges ââââââââââââââââââââââââââ 38 float bottomRim = pow(max(0.0, 1.0 - (1.0 - uv.y) * 7.0), 3.0) * 0.09; 39 float rightRim = pow(max(0.0, 1.0 - (1.0 - uv.x) * 7.0), 3.0) * 0.07; 40 41 // ââ Slow shimmer sweep ââââââââââââââââââââââââââââââââââââââââââââââââ 42 float sweepX = fract(u_time * 0.05); 43 float sweep = smoothstep(sweepX - 0.16, sweepX, uv.x) 44 * (1.0 - smoothstep(sweepX, sweepX + 0.16, uv.x)); 45 sweep *= 0.13 * pow(1.0 - uv.y, 1.4); 46 47 float alpha = clamp( 48 spec + spec2 + topBevel + leftBevel + bottomRim + rightRim + sweep, 49 0.0, 0.84 50 ); 51 fragColor = vec4(1.0, 1.0, 1.0, alpha); 52}`;function y(n,t,e){const r=n.createShader(t);return r?(n.shaderSource(r,e),n.compileShader(r),n.getShaderParameter(r,n.COMPILE_STATUS)?r:(n.deleteShader(r),null)):null}function X(){const n=P.useRef(null);return P.useEffect(()=>{const t=n.current;if(!t||!B()||C())return;const e=t.getContext("webgl2",{alpha:!0,premultipliedAlpha:!1});if(!e)return;const r=y(e,e.VERTEX_SHADER,U),p=y(e,e.FRAGMENT_SHADER,M);if(!r||!p)return;const o=e.createProgram();if(!o||(e.attachShader(o,r),e.attachShader(o,p),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)))return;const g=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,g),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW);const _=e.getAttribLocation(o,"a_pos");e.enableVertexAttribArray(_),e.vertexAttribPointer(_,2,e.FLOAT,!1,0,0);const F=e.getUniformLocation(o,"u_time"),L=e.getUniformLocation(o,"u_res"),T=e.getUniformLocation(o,"u_mouse");e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA);const c={x:.3,y:.3},w=a=>{const m=t.parentElement;if(!m)return;const s=m.getBoundingClientRect();c.x=(a.clientX-s.left)/s.width,c.y=(a.clientY-s.top)/s.height},A=t.parentElement;A?.addEventListener("mousemove",w);let u=null,R=0,i=0,d=!0,v=!document.hidden;const h=a=>{u===null&&(u=a);const m=(a-u)/1e3-R,s=t.offsetWidth,f=t.offsetHeight;(t.width!==s||t.height!==f)&&(t.width=s,t.height=f,e.viewport(0,0,s,f)),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT),e.useProgram(o),e.uniform1f(F,m),e.uniform2f(L,s,f),e.uniform2f(T,c.x,c.y),e.drawArrays(e.TRIANGLE_STRIP,0,4),i=requestAnimationFrame(h)};let l=null;const b=()=>{i&&(cancelAnimationFrame(i),i=0,l=performance.now())},x=()=>{i||!d||!v||(l!==null&&u!==null&&(R+=(performance.now()-l)/1e3,l=null),i=requestAnimationFrame(h))},E=new IntersectionObserver(([a])=>{d=a.isIntersecting,d?x():b()},{threshold:0});E.observe(t);const S=()=>{v=!document.hidden,v?x():b()};return document.addEventListener("visibilitychange",S),i=requestAnimationFrame(h),()=>{cancelAnimationFrame(i),E.disconnect(),document.removeEventListener("visibilitychange",S),A?.removeEventListener("mousemove",w),e.deleteBuffer(g),e.deleteShader(r),e.deleteShader(p),e.deleteProgram(o)}},[]),I.jsx("canvas",{ref:n,"aria-hidden":"true",style:{position:"absolute",inset:0,width:"100%",height:"100%",pointerEvents:"none",zIndex:1,borderRadius:"inherit"}})}export{X as GlassLens};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.