Gemini read a Metal shader for me and explained what the light spill is doing
You
Someone left this fragment shader in a project I inherited. What is it doing, in plain English?
fragment float4 glassPanel(VertexOut in [[stage_in]],
texture2d<float> content [[texture(0)]],
texture2d<float> backdrop [[texture(1)]],
constant Params& p [[buffer(0)]]) {
constexpr sampler s(filter::linear, address::clamp_to_edge);
float2 uv = in.uv;
float4 c = content.sample(s, uv);
float4 bg = 0;
for (int i = -4; i <= 4; i++) {
for (int j = -4; j <= 4; j++) {
bg += backdrop.sample(s, uv + float2(i, j) * p.blurStep);
}
}
bg /= 81.0;
float edge = smoothstep(0.0, p.edgeWidth, min(min(uv.x, 1.0 - uv.x), min(uv.y, 1.0 - uv.y)));
float3 tint = mix(p.tint.rgb, bg.rgb, p.frost);
float3 spill = bg.rgb * p.spill * (1.0 - edge);
return float4(mix(tint + spill, c.rgb, c.a) , max(c.a, p.opacity) * edge);
}Gemini
It draws a “frosted glass” panel that floats over a background, with the background’s colours bleeding onto the panel’s edges. Step by step:
- Sample the panel’s own content (
c) — the app window or image being shown on the panel. - Blur the backdrop — a 9×9 box blur of whatever is behind the panel (81 samples, all weighted equally). That’s the “frost”. It’s the expensive line: 81 texture reads per pixel. A separable blur (9 horizontal + 9 vertical in two passes) would give the same look for 18 reads.
- Edge mask —
edgegoes from 0 at the very border of the panel to 1 once you’reedgeWidthin. It’s used twice: to fade the panel’s alpha out at the border (soft edges), and to decide where the spill shows. - Tint — the panel’s base colour is a mix between a fixed tint and the blurred backdrop, controlled by
frost.frost = 1means pure blurred background (very transparent glass);frost = 0means a solid tinted plate. - Light spill —
spilltakes the blurred background colour, scales it byp.spill, and applies it only near the edges (1 - edge). Visually: the environment’s light “leaks” onto the rim of the panel, which sells the idea that the panel is a physical sheet of glass sitting in the scene rather than a flat overlay. - Composite — where the content is opaque (
c.a), show the content; where it isn’t, show tint + spill. Final alpha is the larger of content alpha and the panel opacity, faded by the edge mask.
If you touch one thing: replace the 9×9 loop with a two-pass separable blur. Same picture, roughly 4× cheaper, and on a laptop GPU at 4K that is the difference between 120 fps and 60.
Comments (0)
No comments yet.
Sign in to comment.