Understanding Gradient Noise in GLSL

in #coding2 days ago

Value noise was a huge improvement over random pixels.

Instead of abrupt jumps, neighboring values blended together.

Even so, every grid cell still had a slight square appearance.

To solve this problem, computer graphics researchers came up with another idea.

Instead of storing random values at the corners, why not store random directions?

That simple change led to a much smoother form of procedural noise called gradient noise.

Looking at Value Noise Again

Imagine a square divided into four corners.

Each corner stores a random number.

As you move across the square, those numbers blend together.

The blending is smooth, but the corners still influence the final result in a noticeable way.

This is why large value noise patterns sometimes reveal a faint grid.

A Different Idea

Instead of assigning a random number to every corner, assign a random direction.

Each corner now contains a small arrow.

Some arrows point upward.

Some point sideways.

Others point diagonally.

The arrows never change.

Only the way they influence nearby pixels changes.

Choosing a Gradient

Each grid corner generates a direction.

A simple example might look like this.

vec2 gradient = vec2(

cos(angle),

sin(angle)

);

Instead of storing brightness, each corner stores a unit vector.

Measuring the Local Position

Just as we did with value noise, we first determine our position inside the current grid cell.

vec2 cell = floor(vUv * 8.0);

vec2 local = fract(vUv * 8.0);

The grid remains exactly the same.

Only the corner information changes.

Calculating Influence

Each corner now measures how well its direction matches the pixel.

This is done using the dot product.

float influence =

dot(

gradient,

local

);

Instead of blending random brightness values, we're blending directional influence.

This creates much smoother transitions.

Blending the Corners

The four corner influences are blended exactly as before.

float bottom = mix(a, b, local.x);

float top = mix(c, d, local.x);

float noise = mix(bottom, top, local.y);

The interpolation stays the same.

Only the values being blended are different.

Smoothing the Interpolation

We'll also continue using the smoothing function.

local = local * local *

(3.0 - 2.0 * local);

This softens the transitions near every edge.

Why Does Gradient Noise Look Better?

Imagine walking across rolling hills.

Value noise feels like walking over small plateaus.

Gradient noise feels like walking across gentle slopes.

The changes become more continuous.

The grid becomes much harder to notice.

This is why gradient noise became the foundation for many later algorithms.

A Simplified Shader

A complete gradient noise implementation is longer than value noise because each corner needs its own direction vector.

A simplified version begins like this.

vec2 cell = floor(vUv * 8.0);

vec2 local = fract(vUv * 8.0);

local = local * local *

(3.0 - 2.0 * local);

Next, each corner generates a gradient direction instead of a random value.

Those directional influences are then blended together.

Although the mathematics becomes longer, the overall idea stays surprisingly simple.

Adding Colour

Gradient noise works beautifully with color gradients.

vec3 color = mix(

vec3(0.15,0.25,0.6),

vec3(0.9,0.95,1.0),

noise

);

The smooth transitions make the result resemble soft clouds or mist.

Animating Gradient Noise

The coordinates can still move over time.

vec2 uv = vUv;

uv += uTime * 0.05;

The entire noise field appears to drift smoothly across the screen.

This technique is often used for clouds, smoke, and magical effects.

Comparing Three Approaches

Let's compare everything we've learned so far.

Random values.

Every neighboring pixel changes abruptly.

Value noise.

Random values blend together smoothly, but the grid is still visible.

Gradient noise.

Directional information blends together, creating much more natural patterns.

Each step builds directly on the previous one.

Where Is Gradient Noise Used?

Gradient noise appears in many procedural graphics.

  • Clouds.
  • Smoke.
  • Water.
  • Fire.
  • Fog.
  • Terrain generation.
  • Animated backgrounds.
  • Particle systems.
  • Procedural textures.
  • Visual effects.

Many modern shaders begin with some variation of gradient noise.

Try These Experiments

Compare value noise with gradient noise.

Animate the coordinates.

Increase the grid size.

Decrease the grid size.

Apply different color gradients.

Observe how much smoother the transitions become.

A Small Challenge

Can you create these effects?

  • Soft moving clouds.
  • Animated fog.
  • A magical energy field.
  • Flowing water.
  • A colorful procedural background.

Each effect starts with smooth gradient noise.

Posted Using INLEO