Skip to main content
GameDev.net gamedev.net

Animating with Time

by GameDev.net · GLSL ES 3.00 (WebGL2) · 25 Aug 2026

Beginner 2DAnimationwave
Use in your engine

Run the shader to adjust these controls.

What it demonstrates

This shader introduces iTime as a continuously changing input. It animates a sine wave across the viewport while exposing independent Speed and Amplitude sliders. The result shows how time changes phase, position changes the waveform across space, and a distance field gives that moving curve visible thickness.

Source Revision 1

Author notes are linked to specific lines.

Shader inputs

void mainImage(out vec4 fragColor, in vec2 fragCoord)

Called once per pixel. Write the colour to fragColor.

iResolution vec3
Viewport size in pixels (z is the pixel aspect ratio).
iTime float
Seconds since the shader started.
iTimeDelta float
Seconds since the previous frame.
iFrameRate float
Frames per second, smoothed.
iFrame int
Frames rendered since the start.
iMouse vec4
Mouse position: xy while held, zw of the last click.
iDate vec4
Year, month, day, and seconds within the day.
iChannel0 sampler2D
Texture bound to channel 0.
iChannel1 sampler2D
Texture bound to channel 1.
iChannel2 sampler2D
Texture bound to channel 2.
iChannel3 sampler2D
Texture bound to channel 3.
iChannelResolution vec3[4]
Pixel size of each bound channel texture.
iChannelTime float[4]
Playback time of each channel, in seconds.
iSampleRate float
Audio sample rate, always 44100.
Main Image5
1 uniform float uSpeed; // @param 0.0..4.0 = 1.0 "Speed"
2 uniform float uAmplitude; // @param 0.0..0.45 = 0.22 "Amplitude"
3
4 void mainImage(out vec4 fragColor, in vec2 fragCoord) {
5 vec2 uv = fragCoord / iResolution.xy;
6 float phase = iTime * uSpeed;
7 float wave = sin(phase + uv.x * 6.2831853);
8 float centerLine = 0.5 + wave * uAmplitude;
9 float distanceToLine = abs(uv.y - centerLine);
10 float stroke = 1.0 - smoothstep(0.012, 0.025, distanceToLine);
11 vec3 color = mix(vec3(0.025, 0.04, 0.09), vec3(0.20, 0.90, 0.72), stroke);
12 fragColor = vec4(color, 1.0);
13 }
14

Learn from this shader

How it works

ShaderLab supplies elapsed seconds in iTime. Multiplying time by Speed creates a phase that advances faster or slower without changing the curve's shape. Horizontal UV position is scaled by one full turn and added to that phase before calling sin. The resulting value ranges from negative one to one. Amplitude scales it, and adding one half places the wave around the screen center. For every pixel, the absolute vertical distance to that center line is measured. smoothstep converts a narrow distance range into a soft stroke mask used to blend foreground and background colors.

Try changing

Set Speed to zero to freeze the wave, then adjust Amplitude. Compare low and high speed without changing the spatial wavelength. In a fork, subtract phase instead of adding it to reverse travel, multiply uv.x by two full turns for two waves, or replace sin with cos and observe that only the starting phase changes.

Using it in a game

Time-driven waves can animate energy bars, force fields, water accents, and UI highlights. In an engine, use its time uniform and consider pause state, time scaling, and deterministic replay requirements. This full-screen example is opaque, but the stroke mask could drive emission or alpha in a material.

Explore the techniques

Continue with curated explanations and progressively related examples.

LicenseMIT
Views2
Forks0

Discussion

Loading comments...