/** * GLSL shader sources for the liquid glass effect. * * All shaders target WebGL 1 (GLSL ES 1.0) for maximum compatibility. * The rendering pipeline has three stages: * 1. Blit — copy / UV-transform a texture (used for background upload & downsample) * 2. Blur — 9-tap Gaussian blur in a single direction (run H then V, multiple passes) * 3. Glass — the core liquid-glass composite (refraction, specular, shadow, etc.) */ export declare const VS_QUAD = "\nattribute vec2 a_pos;\nvarying vec2 v_uv;\nvoid main() {\n\tv_uv = a_pos * 0.5 + 0.5;\n\tgl_Position = vec4(a_pos, 0.0, 1.0);\n}"; export declare const FS_BLIT = "\nprecision mediump float;\nuniform sampler2D u_tex;\nuniform vec2 u_scale;\nuniform vec2 u_offset;\nvarying vec2 v_uv;\nvoid main() {\n\tgl_FragColor = texture2D(u_tex, v_uv * u_scale + u_offset);\n}"; export declare const FS_BLUR = "\nprecision mediump float;\nuniform sampler2D u_tex;\nuniform vec2 u_dir;\nvarying vec2 v_uv;\nvoid main() {\n\tvec4 s = texture2D(u_tex, v_uv) * 0.227027;\n\ts += texture2D(u_tex, v_uv + u_dir * 1.0) * 0.194594;\n\ts += texture2D(u_tex, v_uv - u_dir * 1.0) * 0.194594;\n\ts += texture2D(u_tex, v_uv + u_dir * 2.0) * 0.121622;\n\ts += texture2D(u_tex, v_uv - u_dir * 2.0) * 0.121622;\n\ts += texture2D(u_tex, v_uv + u_dir * 3.0) * 0.054054;\n\ts += texture2D(u_tex, v_uv - u_dir * 3.0) * 0.054054;\n\ts += texture2D(u_tex, v_uv + u_dir * 4.0) * 0.016216;\n\ts += texture2D(u_tex, v_uv - u_dir * 4.0) * 0.016216;\n\tgl_FragColor = s;\n}"; export declare const VS_GLASS = "\nattribute vec2 a_pos;\nuniform vec2 u_center; // panel centre in root-pixel coords (top-left origin)\nuniform vec2 u_size; // panel size in px\nuniform vec2 u_res; // root element size in px\nuniform float u_pad; // shadow padding in px\nvarying vec2 v_localPx;\nvarying vec2 v_screenUV;\n\nvoid main() {\n\tvec2 total = u_size + vec2(u_pad * 2.0);\n\tv_localPx = a_pos * total; // px from panel centre\n\tvec2 px = u_center + a_pos * total; // screen px (DOM)\n\tv_screenUV = vec2(px.x / u_res.x, 1.0 - px.y / u_res.y);\n\tvec2 ndc = (px / u_res) * 2.0 - 1.0;\n\tndc.y = -ndc.y;\n\tgl_Position = vec4(ndc, 0.0, 1.0);\n}"; export declare const FS_GLASS = "\nprecision highp float;\n\nuniform sampler2D u_bgTex;\nuniform sampler2D u_blurTex;\nuniform vec2 u_size; // panel px\nuniform float u_radius; // corner radius px\nuniform vec2 u_res;\n\nuniform float u_refract;\nuniform float u_chroma;\nuniform float u_edgeHL;\nuniform float u_spec;\nuniform float u_fresnel;\nuniform float u_distort;\nuniform float u_alpha;\nuniform float u_sat;\nuniform float u_tint;\nuniform float u_zRadius;\nuniform float u_brightness;\nuniform float u_shadowAlpha;\nuniform float u_shadowSpread;\nuniform float u_shadowOffY;\nuniform float u_bevelMode;\n\nvarying vec2 v_localPx;\nvarying vec2 v_screenUV;\n\n// Rounded-rect signed distance\nfloat rrSDF(vec2 p, vec2 b, float r) {\n\tvec2 q = abs(p) - b + vec2(r);\n\treturn min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - r;\n}\n\n// Bevel height field.\n// Both modes use the same half-circle profile (smooth peak at centre,\n// steep at edges). The difference is in the refraction model:\n// mode 0 = biconvex pill \u2014 light refracts at both surfaces (entry + exit).\n// mode 1 = dome (plano-convex) \u2014 flat bottom, so only exit refraction.\n// d = distance inside from edge (-sdf), zR = z-radius of the bevel.\nfloat bevelHeight(float d, float zR) {\n\tif (d <= 0.0) return 0.0;\n\tif (d >= zR) return zR;\n\treturn sqrt(d * (2.0 * zR - d));\n}\n\nfloat hash(vec2 p) {\n\treturn fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);\n}\n\nvoid main() {\n\tvec2 half_ = u_size * 0.5;\n\tfloat r = min(u_radius, min(half_.x, half_.y));\n\tfloat sdf = rrSDF(v_localPx, half_, r);\n\n\t// \u2500\u2500 Shadow (outside panel, offset by shadowOffY) \u2500\u2500\n\tif (sdf > 0.0) {\n\t\tfloat sdfShadow = rrSDF(v_localPx - vec2(0.0, u_shadowOffY), half_, r);\n\t\tfloat d = max(sdfShadow - 1.0, 0.0);\n\t\tfloat spread = max(u_shadowSpread, 1.0);\n\t\tfloat falloff = 1.0 / (spread * spread);\n\t\tfloat outerShadow = exp(-d * d * falloff) * 0.65;\n\t\tfloat contactShadow = exp(-d * 0.08 / max(spread * 0.04, 0.01)) * 0.35;\n\t\tfloat shadow = (outerShadow + contactShadow) * u_shadowAlpha;\n\t\tgl_FragColor = vec4(0.0, 0.0, 0.0, shadow);\n\t\treturn;\n\t}\n\n\t// \u2500\u2500 Anti-aliased mask \u2500\u2500\n\tfloat mask = 1.0 - smoothstep(-1.5, 0.5, sdf);\n\n\tfloat maxD = min(half_.x, half_.y);\n\tfloat inside = -sdf;\n\tfloat edge = smoothstep(maxD * 0.35, 0.0, inside);\n\n\t// \u2500\u2500 Surface normal (top surface) via bevel height field \u2500\u2500\n\tfloat zR = u_zRadius;\n\tfloat e = 2.0;\n\tfloat dC = inside;\n\tfloat dR = -rrSDF(v_localPx + vec2(e, 0.0), half_, r);\n\tfloat dL = -rrSDF(v_localPx - vec2(e, 0.0), half_, r);\n\tfloat dU = -rrSDF(v_localPx + vec2(0.0, e), half_, r);\n\tfloat dD = -rrSDF(v_localPx - vec2(0.0, e), half_, r);\n\tfloat hC = bevelHeight(dC, zR);\n\tfloat hR = bevelHeight(dR, zR);\n\tfloat hL = bevelHeight(dL, zR);\n\tfloat hU = bevelHeight(dU, zR);\n\tfloat hD = bevelHeight(dD, zR);\n\tvec2 hGrad = vec2(hR - hL, hU - hD) / (2.0 * e);\n\tvec3 N = normalize(vec3(-hGrad, 1.0));\n\n\tfloat depth = smoothstep(0.0, zR, inside);\n\n\t// \u2500\u2500 Refraction \u2500\u2500\n\tvec2 pxToUV = vec2(1.0, -1.0) / u_res;\n\tfloat ior = 1.5;\n\tfloat refrPow = 1.0 - 1.0 / ior;\n\tfloat thickness = hC * 2.0;\n\tfloat thickNorm = thickness / max(zR * 2.0, 1.0);\n\tvec2 refrPx;\n\tif (u_bevelMode < 0.5) {\n\t\t// Biconvex: physically-based dual-surface refraction\n\t\tvec2 exitRefr = hGrad * refrPow;\n\t\tvec2 entryRefr = hGrad * refrPow;\n\t\tvec2 throughRefr = entryRefr * thickNorm * 0.5;\n\t\trefrPx = (exitRefr + entryRefr + throughRefr) * u_refract * 30.0;\n\t\tvec2 centerDir = -v_localPx / max(half_, vec2(1.0));\n\t\trefrPx += centerDir * u_refract * 4.0 * depth;\n\t} else {\n\t\t// Dome (plano-convex): uniform magnification by contracting UV toward center.\n\t\t// Each pixel samples from closer to center \u2192 content appears larger.\n\t\trefrPx = -v_localPx * u_refract * depth * 0.35;\n\t}\n\tvec2 refr = refrPx * pxToUV;\n\n\t// \u2500\u2500 Micro-distortion noise \u2500\u2500\n\tvec2 ns = v_localPx * 0.08;\n\tvec2 absPxToUV = vec2(1.0) / u_res;\n\tvec2 micro = (vec2(hash(ns), hash(ns + vec2(37.0))) - 0.5) * u_distort * 4.0 * absPxToUV;\n\n\t// \u2500\u2500 Chromatic aberration \u2500\u2500\n\tfloat caS = u_chroma * 18.0 * (edge * 0.7 + 0.3) * 2.0;\n\tvec2 caD = N.xy * caS * pxToUV;\n\tvec2 base = v_screenUV + refr + micro;\n\n\tvec3 sharp = vec3(\n\t\ttexture2D(u_bgTex, base + caD).r,\n\t\ttexture2D(u_bgTex, base).g,\n\t\ttexture2D(u_bgTex, base - caD).b\n\t);\n\tvec3 blur = vec3(\n\t\ttexture2D(u_blurTex, base + caD).r,\n\t\ttexture2D(u_blurTex, base).g,\n\t\ttexture2D(u_blurTex, base - caD).b\n\t);\n\t// \u2500\u2500 Edge-weighted blur mix \u2500\u2500\n\t// Centre of the panel uses the blurred sample; the rim blends\n\t// toward the sharp sample so refraction edges stay crisp.\n\tfloat edgeMix = (1.0 - edge * 0.15);\n\tvec3 col = mix(sharp, blur, edgeMix);\n\n\t// \u2500\u2500 Brightness \u2500\u2500\n\tcol *= 1.0 + u_brightness;\n\n\t// \u2500\u2500 Saturation \u2500\u2500\n\tfloat lum = dot(col, vec3(0.299, 0.587, 0.114));\n\tcol = mix(vec3(lum), col, 1.0 + u_sat);\n\n\t// \u2500\u2500 Cool glass tint \u2500\u2500\n\tcol = mix(col, col * vec3(0.92, 0.95, 1.05), u_tint);\n\tcol *= 1.0 + 0.06 * depth;\n\n\t// \u2500\u2500 Fresnel \u2500\u2500\n\tfloat fres = pow(1.0 - abs(N.z), 4.0) * u_fresnel;\n\n\t// \u2500\u2500 Specular highlights (multi-light Blinn-Phong) \u2500\u2500\n\tvec3 V = vec3(0.0, 0.0, 1.0);\n\tvec3 L1 = normalize(vec3(0.4, 0.7, 1.0));\n\tvec3 H1 = normalize(L1 + V);\n\tfloat sp1 = pow(max(dot(N, H1), 0.0), 90.0);\n\tvec3 L2 = normalize(vec3(-0.3, -0.5, 1.0));\n\tvec3 H2 = normalize(L2 + V);\n\tfloat sp2 = pow(max(dot(N, H2), 0.0), 50.0) * 0.3;\n\tvec3 L3 = normalize(vec3(0.1, 0.3, 1.0));\n\tfloat spB = pow(max(dot(N, L3), 0.0), 6.0) * 0.1;\n\tvec3 L4 = normalize(vec3(0.0, 0.9, 0.4));\n\tvec3 H4 = normalize(L4 + V);\n\tfloat sp4 = pow(max(dot(N, H4), 0.0), 120.0) * 0.6;\n\tfloat totalSpec = (sp1 + sp2 + spB + sp4) * u_spec;\n\n\t// \u2500\u2500 Inner border / stroke highlight \u2500\u2500\n\tfloat borderWidth = 1.5;\n\tfloat innerStroke = smoothstep(-borderWidth - 1.0, -borderWidth, sdf)\n\t * (1.0 - smoothstep(-1.0, 0.0, sdf));\n\tfloat topBias = 0.5 + 0.5 * (-v_localPx.y / half_.y);\n\tinnerStroke *= (0.4 + 0.6 * topBias);\n\n\t// \u2500\u2500 Edge highlight & inner glow \u2500\u2500\n\tfloat rim = edge * u_edgeHL * 0.22;\n\tfloat innerGlow = smoothstep(5.0, 0.0, -sdf) * u_edgeHL * 0.15;\n\n\t// \u2500\u2500 Environment-like reflection (fake) \u2500\u2500\n\tfloat envRefl = (N.y * 0.5 + 0.5) * fres * 0.08;\n\n\t// \u2500\u2500 Composite \u2500\u2500\n\tvec3 fin = col;\n\tfin += vec3(totalSpec);\n\tfin += vec3(rim + innerGlow);\n\tfin += vec3(innerStroke * u_edgeHL * 0.55);\n\tfin += vec3(envRefl);\n\tfin = mix(fin, vec3(1.0), fres * 0.2);\n\n\tgl_FragColor = vec4(fin, mask * u_alpha);\n}"; //# sourceMappingURL=shaders.d.ts.map