fresnel_shader

The shader-based Liquid Glass fallback for fresnel.

Apps should not depend on this package directly. Depend on fresnel, which uses this automatically on every platform without native glass: Android, web, Windows, Linux, and iOS below 26.

What it does

Pure Dart, no native code, so it runs anywhere Flutter does.

ShaderGlassSurface renders fresnel_glass.frag as an ImageFilter.shader over the backdrop, composed on top of a hardware gaussian:

ui.ImageFilter.compose(
  outer: ui.ImageFilter.shader(shader),
  inner: ui.ImageFilter.blur(sigmaX: sigma, sigmaY: sigma),
)

Blurring in the filter chain rather than inside the shader matters — Flutter's blur is a tuned separable pass, and a hand-written multi-tap loop is both slower and worse. The shader is left to do only what the built-in filters cannot:

  • Edge refraction. A signed-distance field gives a surface normal; samples bend along it, strongest at the rim. This lensing is what separates glass from a frosted pane.
  • Specular rim. Directional highlight with an ambient floor so the rim stays legible on dark backgrounds.
  • Thickness falloff, so the surface reads as a slab rather than a decal.
  • System intensity. The whole effect scales toward "off" with the user's glass-intensity preference, so hand-rendered glass tracks the OS instead of drifting away from it.

FallbackGlassSurface is the last resort — a plain BackdropFilter with a tint and hairline rim, used on Skia and web where backdrop shaders are unavailable, and whenever the shader fails to compile.

Precision

The shader declares precision highp float. mediump's 10-bit mantissa quantises the displacement into roughly 1.5px of visible banding at typical thickness values on mobile GPUs.

Notes for anyone writing their own

Flutter's .frag dialect is GLSL, not SkSL: uniform sampler2D and texture(sampler, uv) with normalised coordinates. uniform shader and .eval() are SkSL and fail impellerc with a bare syntax error.

Size a glass surface from inside a Positioned.fill, not from an outer LayoutBuilder. LayoutBuilder reports the constraints handed down, so any unbounded parent — a Row, Column, or scrollable — yields infinity and silently disables the effect.

License

MIT

Libraries

fresnel_shader
Shader-based Liquid Glass fallback for fresnel.