Water is always moving.
Sometimes it forms gentle ripples across a lake.
Sometimes it crashes into waves.
Sometimes it reflects the sky so clearly that it almost looks like glass.
Although real water is incredibly complex, we can recreate many of its characteristics using simple mathematics.
What Makes Water Look Like Water?

Most procedural water begins with four simple ingredients.
Smooth waves.
Subtle distortion.
Continuous animation.
A cool color gradient.
The combination of these four ideas creates surprisingly convincing results.
Starting with the UV Coordinates
We'll begin with our familiar coordinates.
vec2 uv = vUv;
Everything in the shader will be built from these coordinates.
Creating the First Wave
The easiest way to make water is with a sine wave.
float wave =
sin(
uv.x * 12.0
);
This creates evenly spaced ripples.
At the moment they are perfectly straight.
Real water is never this perfect.
Animating the Ripples
Water is always moving.
We simply shift the wave over time.
float wave =
sin(
uv.x * 12.0 +
uTime * 2.0
);
The ripples now travel smoothly across the screen.
Adding Noise
Perfect waves still look artificial.
Let's distort them with FBM.
float n =
fbm(
uv * 3.0
);
This creates smooth variation.
Distorting the Waves
Add the noise into the sine function.
float water =
sin(
uv.x * 12.0 +
n * 4.0 +
uTime * 2.0
);
The waves now bend naturally instead of remaining perfectly straight.
Adding a Second Wave
Real water contains many overlapping waves.
Create another one.
water +=
sin(
uv.y * 18.0 -
uTime * 1.5
) * 0.5;
The two wave systems interact to create a richer surface.
Normalizing the Result
Bring everything back into the familiar range.
water =
water * 0.5 +
0.5;
Now the values are ready to use for colors.
Complete Shader
#ifdef GL_ES
precision mediump float;
#endif
uniform float uTime;
varying vec2 vUv;
void main(){
vec2 uv = vUv;
float n = fbm(uv * 3.0);
float water =
sin(
uv.x * 12.0 +
n * 4.0 +
uTime * 2.0
);
water +=
sin(
uv.y * 18.0 -
uTime * 1.5
) * 0.5;
water = water * 0.5 + 0.5;
gl_FragColor = vec4(vec3(water),1.0);
}
Even without colors, the animation already resembles moving water.
Adding Water Colours
Now apply a blue gradient.
vec3 color = mix(
vec3(0.05,0.15,0.45),
vec3(0.35,0.75,1.0),
water
);
Dark blue represents deeper areas.
Light blue highlights the wave peaks.
Making the Water Calmer
Reduce the animation speed.
uTime * 0.8
The water now resembles a quiet lake.
Creating Rough Water
Increase the FBM scale.
fbm(
uv * 6.0
);
The waves become much more detailed.
Adding Flow
Instead of moving only the waves, move the coordinates.
uv.x +=
uTime * 0.1;
The entire water surface begins to drift naturally.
Where Is Procedural Water Used?
Procedural water appears everywhere.
- Oceans.
- Rivers.
- Lakes.
- Swimming pools.
- Waterfalls.
- Fantasy environments.
- Motion graphics.
- Background animations.
- User interfaces.
- Video games.
Many professional water shaders begin with nothing more than animated sine waves and procedural noise.
Try These Experiments
Create gentle ripples.
Create stormy water.
Increase the distortion.
Slow the animation.
Speed it up.
Change the color gradient.
Combine three wave layers instead of two.
Observe how each adjustment changes the feeling of the water.
A Small Challenge
Can you create these effects?
A peaceful lake.
Ocean waves.
A magical glowing river.
Rain ripples.
A moving underwater background.
Every one of these begins with the same mathematical building blocks.
Posted Using INLEO
Congratulations @hey2d! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)
Your next target is to reach 80 posts.
You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOPCheck out our last posts: