← all topics

Particle Text Shader

WebGL

Particles form text using WebGL gl.POINTS and a GLSL circle shader. A radial force field driven by mouse position displaces them — they spring back to formation via per-particle spring physics. Inspired by basement.studio's Vercel Ship effect.

Controls
110px
3
0.055
3.5px

concepts

WebGL pipeline

Two GPU programs run per frame: the vertex shader (where each point lands in clip space) and the fragment shader (what color each pixel within that point gets).

gl.POINTS

Draws one square sprite per vertex. gl_PointSize controls the size; gl_PointCoord in the fragment shader gives the position within that square (0,0) to (1,1).

circle masking

length(gl_PointCoord - vec2(0.5)) computes distance from the sprite center. Pixels where this exceeds 0.5 are discarded, turning the default square into a circle.

spring physics (JS side)

Each frame: vx += (homeX - x) * spring. Mouse applies a radial push/pull force. All physics run on the CPU — the GPU only handles rendering.

core pattern

// Vertex shader: position each particle
gl_Position  = vec4(pixelToClip(a_pos), 0.0, 1.0);
gl_PointSize = u_size * (1.0 + v_disp * 0.6);

// Fragment shader: clip square → circle
float d = length(gl_PointCoord - vec2(0.5));
if (d > 0.5) discard;  // outside circle → transparent
gl_FragColor = vec4(mix(restColor, accentColor, v_disp), 1.0);

// JS spring physics (per frame, per particle)
p.vx += (p.homeX - p.x) * spring;
p.vx *= damping;
p.x  += p.vx;