Ambient Field
washiveil/ambient-fieldFreeComponent
Viewport-fixed tri-color light field the page scrolls over — WebGL glows with per-pixel dither, CSS fallback for first paint, film-grain overlay. Reduced-motion safe.
Install it
npx shadcn@latest add https://washiveil.alexchih.com/r/ambient-field.jsonSource
1'use client';23// Viewport-fixed tri-color ambient light field. Three engines:4// - WebGL canvas (primary): renders three glows in float precision with5// per-pixel dither — no 8-bit contour rings at any zoom. Adaptive loop:6// full-rate only while scroll inertia settles, ~15fps for the idle wander,7// paused on hidden tabs; reduced-motion users get a static render. Colors8// read from @theme tokens at render time — palette stays live.9// - CSS divs (fallback): the pre-JS FIRST PAINT — server-rendered, visible10// the instant HTML arrives, swapped invisibly once the canvas renders. This11// is why it stays: without it every navigation would flash a bare ground12// before the glows pop in. no-JS / no-WebGL / context-loss coverage is a13// bonus. Geometry: the shader anchors to these sizes at phone/desktop14// widths and interpolates continuously in the tablet band.15// - Film-grain overlay div with SVG turbulence data-URI background and a16// dark-mode radial mask.17//18// The inset-0 clip keeps negative offsets from widening the document19// (scrollWidth bug). Note: full-page screenshot tools paint fixed layers at the20// first viewport only — capture artifact, not a bug.2122import { useEffect, useRef } from 'react';23import { cn } from '@/lib/utils';2425const VERT = 'attribute vec2 p;void main(){gl_Position=vec4(p,0.,1.);}';26const FRAG = `27precision highp float;28uniform vec2 u_res;29uniform vec4 u_g0;uniform vec4 u_g1;uniform vec4 u_g2;30uniform vec3 u_s;31uniform vec3 u_c0;uniform vec3 u_c1;uniform vec3 u_c2;32uniform vec3 u_a;33float hash(vec2 p){return fract(sin(dot(p,vec2(12.9898,78.233)))*43758.5453);}34float glow(vec2 p,vec4 g,float s){35 vec2 q=(p-g.xy)/g.zw;36 float d=(length(q)-1.0)*min(g.z,g.w);37 return 1.0-smoothstep(-1.2*s,1.6*s,d);38}39void main(){40 vec2 p=vec2(gl_FragCoord.x,u_res.y-gl_FragCoord.y);41 float c0=glow(p,u_g0,u_s.x);42 float c1=glow(p,u_g1,u_s.y);43 float c2=glow(p,u_g2,u_s.z);44 vec3 rgb=vec3(0.0);float a=0.0;float ai;45 ai=u_a.x*c0;rgb+=(1.0-a)*ai*u_c0;a+=(1.0-a)*ai;46 ai=u_a.y*c1;rgb+=(1.0-a)*ai*u_c1;a+=(1.0-a)*ai;47 ai=u_a.z*c2;rgb+=(1.0-a)*ai*u_c2;a+=(1.0-a)*ai;48 // Full-strength dither wherever ANY coverage exists (the faint tails are49 // exactly where 8-bit steps live) — alpha-scaled dither was a bug that50 // switched the cure off where the disease is. Bare ground stays clean.51 float dn=(hash(gl_FragCoord.xy)-0.5)*(2.5/255.0)*smoothstep(0.0,0.005,max(c0,max(c1,c2)));52 rgb=max(rgb+vec3(dn),vec3(0.0));53// … truncated
What it pulls in
Other registry items
Files it writes
More from washiveil
All 58 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Chipchip | washiveil | Components | Free | 1 dep | |
| Code Badgecode-badge | washiveil | Components | Free | no deps | |
| Glass Accordionglass-accordion | washiveil | Components | Free | 2 deps | |
| Glass Alertglass-alert | washiveil | Components | Free | 1 dep | |
| Glass Alert Dialogglass-alert-dialog | washiveil | Components | Free | 1 dep | |
| Glass Aspect Ratioglass-aspect-ratio | washiveil | Components | Free | 1 dep | |
| Glass Avatarglass-avatar | washiveil | Components | Free | 1 dep | |
| Glass Breadcrumbglass-breadcrumb | washiveil | Components | Free | 2 deps |
