Understanding UV Coordinates in GLSL

Understanding UV Coordinates in GLSL

Introduction

UV coordinates are one of the most important concepts in shader programming.

Almost every GLSL shader relies on UV coordinates for:

  • positioning
  • animation
  • textures
  • distortion
  • procedural patterns
  • and screen-space effects.

If you understand UV coordinates well, shader programming becomes dramatically easier.

And once the concept “clicks,” you begin to see how shaders build entire visual worlds mathematically.


What Are UV Coordinates?

UV coordinates are normalized coordinate values used to describe positions across a surface or screen.

Instead of using pixel positions like:

1920 x 1080

UV coordinates typically range from:

0.0 → 1.0

This creates a resolution-independent coordinate system.


Why Are They Called “UV”?

In graphics programming:

  • X and Y are often used for geometry positions
  • so texture/surface coordinates traditionally use:

U and V

Think of:

  • U = horizontal axis
  • V = vertical axis

Basic UV Setup

One of the most common lines in GLSL is:

vec2 uv = fragCoord.xy / iResolution.xy;

This converts pixel coordinates into normalized UV coordinates.


Breaking It Down

fragCoord

Represents the current pixel position.

Example:

(960, 540)

iResolution

Represents the screen resolution.

Example:

(1920, 1080)

Division

Dividing the pixel position by screen size converts the values into:

0.0 → 1.0

So:

  • left edge = 0.0
  • right edge = 1.0
  • bottom = 0.0
  • top = 1.0

Visualizing UV Space

Imagine the screen as a coordinate grid.

Bottom-left corner

(0.0, 0.0)

Center

(0.5, 0.5)

Top-right corner

(1.0, 1.0)

UV space allows shaders to work consistently regardless of screen resolution.


Simple UV Gradient Example

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    fragColor = vec4(uv.x, uv.y, 0.5, 1.0);
}

This creates:

  • red increasing horizontally
  • green increasing vertically
  • blue remaining constant.

The result is a smooth screen-space gradient.


Centering UV Coordinates

Often, shaders work better when UV space is centered.

Example:

vec2 uv = fragCoord.xy / iResolution.xy;
uv = uv * 2.0 - 1.0;

Now:

  • center = (0,0)
  • left = -1
  • right = +1
  • bottom = -1
  • top = +1

This makes:

  • symmetry
  • rotation
  • distance calculations
  • and procedural effects
    much easier.

Aspect Ratio Correction

Without correction, circles may appear stretched.

To fix this:

uv.x *= iResolution.x / iResolution.y;

This compensates for widescreen resolutions.


UV Coordinates And Textures

UVs are heavily used for texture sampling.

Example:

vec3 col = texture(iChannel0, uv).rgb;

The texture is sampled using UV coordinates.

This allows:

  • images
  • video
  • noise
  • feedback buffers
  • and procedural textures
    to map across the screen.

UV Distortion

One of the most powerful shader techniques is UV distortion.

Instead of sampling textures normally:

texture(iChannel0, uv)

you modify the UVs first.

Example:

uv.y += sin(uv.x * 10.0 + iTime) * 0.05;

This creates:

  • waves
  • ripples
  • liquid motion
  • and psychedelic distortion.

Repeating Patterns With UVs

Using functions like:

  • fract()
  • mod()
  • floor()

you can tile patterns infinitely.

Example:

vec2 gv = fract(uv * 10.0);

This divides UV space into repeating cells.

Very common in:

  • grids
  • procedural textures
  • sci-fi interfaces
  • and generative art.

Polar Coordinates

UVs can also be converted into:

  • angle
  • and distance.

Example:

float angle = atan(uv.y, uv.x);
float dist = length(uv);

This enables:

  • spirals
  • tunnels
  • radial patterns
  • kaleidoscopes
  • and vortex effects.

Animation Using UVs

UVs become especially powerful when combined with time.

Example:

uv.x += iTime * 0.2;

This scrolls the UVs horizontally.

Used for:

  • flowing textures
  • moving backgrounds
  • tunnels
  • starfields
  • and procedural motion.

UV Coordinates In Audio Reactive Shaders

Audio reactive shaders often distort UVs using music data.

For example:

float bass = texture(syn_Spectrum, 0.05).g;

uv += sin(uv.yx * 8.0 + iTime) * bass * 0.05;

This causes the screen to pulse and distort with bass frequencies.


Why UV Coordinates Matter So Much

UV coordinates are the foundation of:

  • screen-space rendering
  • procedural graphics
  • texture mapping
  • distortion
  • raymarching
  • post-processing
  • and generative animation.

They are essentially the “canvas coordinates” of shader programming.

Understanding UVs deeply unlocks a huge portion of GLSL.


Common Beginner Mistakes

Forgetting Aspect Ratio Correction

Causes stretched visuals.


Confusing Pixel Space And UV Space

Pixel coordinates are resolution-dependent.
UV coordinates are normalized.


Distorting UVs Too Aggressively

Large UV distortion can:

  • tear textures
  • create artifacts
  • or cause instability.

Final Thoughts

Nearly every shader begins with UV coordinates.

They define:

  • where things appear
  • how textures map
  • how effects distort
  • and how visuals animate across the screen.

At first, UV math can feel abstract.

But over time, you begin to think of shaders less as “drawing pixels” and more as:

manipulating coordinate space itself.

And that’s where shader programming becomes truly powerful.

WebGL shader preview unavailable on this device.