2D Procedural Water

This shader is based off Legend of Zelda’s Wind Waker. It uses fractal brownian motion on perlin noise to create a complex texture whose values can be mapped to different colors.

Shader code
shader_type canvas_item;
uniform int OCTAVE = 6;
uniform float mulscale = 5.0;
uniform float height = 0.6;
uniform float tide = 0.1;
uniform float foamthickness = 0.1;
uniform float timescale = 1.0;
uniform float waterdeep = 0.3;
uniform vec4 WATER_COL : hint_color =  vec4(0.04, 0.38, 0.88, 1.0);
uniform vec4 WATER2_COL : hint_color =  vec4(0.04, 0.35, 0.78, 1.0);
uniform vec4 FOAM_COL : hint_color = vec4(0.8125, 0.9609, 0.9648, 1.0);

float rand(vec2 input){
	return fract(sin(dot(input,vec2(23.53,44.0)))*42350.45);

float perlin(vec2 input){
	vec2 i = floor(input);
	vec2 j = fract(input);
	vec2 coord = smoothstep(0.,1.,j);
	float a = rand(i);
	float b = rand(i+vec2(1.0,0.0));
	float c = rand(i+vec2(0.0,1.0));
	float d = rand(i+vec2(1.0,1.0));

	return mix(mix(a,b,coord.x),mix(c,d,coord.x),coord.y);

float fbm(vec2 input){
	float value = 0.0;
	float scale = 0.5;
	for(int i = 0; i < OCTAVE; i++){
		value += perlin(input)*scale;
	return value;

void fragment(){
	float newtime = TIME*timescale;
	float fbmval = fbm(vec2(UV.x*mulscale+0.2*sin(0.3*newtime)+0.15*newtime,-0.05*newtime+UV.y*mulscale+0.1*cos(0.68*newtime)));
	float fbmvalshadow = fbm(vec2(UV.x*mulscale+0.2*sin(-0.6*newtime + 25.0 * UV.y)+0.15*newtime+3.0,-0.05*newtime+UV.y*mulscale+0.13*cos(-0.68*newtime))-7.0+0.1*sin(0.43*newtime));
	float myheight = height+tide*sin(newtime+5.0*UV.x-8.0*UV.y);
	float shadowheight = height+tide*1.3*cos(newtime+2.0*UV.x-2.0*UV.y);
	float withinFoam = step(myheight, fbmval)*step(fbmval, myheight + foamthickness);
	float shadow = (1.0-withinFoam)*step(shadowheight, fbmvalshadow)*step(fbmvalshadow, shadowheight + foamthickness * 0.7);
	COLOR = withinFoam*FOAM_COL + shadow*WATER2_COL + ((1.0-withinFoam)*(1.0-shadow))*WATER_COL;
	//COLOR = vec4(1.0,1.0,1.0,fbmval);
2d, water
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from flytrap

2d Nebula Shader

2D Sonar

Related shaders

Procedural Pixelated Sea Shader

Procedural Electric Background Shader

Pixelated animated water/clouds

Notify of

Newest Most Voted
Inline Feedbacks
View all comments
1 year ago

Can you teach me how to change this shader to isometric?I don’t know much about shaders

1 year ago

Howdy, I used this water shader in my game, Synesthesia (It only appears in the desktop versions and not the browser version due to performance constraints). This shader was an incredibly valuable aesthetic flourish for the game. Thank you for making it available to the community.

Last edited 1 year ago by breather
1 year ago
Reply to  breather

It’s also featured heavily in the trailer:

6 months ago

This is a great shader! Just an update hint_color will be source_color in Godot 4 now if people cannot get it to work. Any idea on how I can get this texture to pixelate for a pixel art style game?