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;
input*=2.0;
scale*=0.5;
}
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);
}
Can you teach me how to change this shader to isometric?I don’t know much about shaders
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.
It’s also featured heavily in the trailer:
https://www.youtube.com/watch?v=v2BZei_-wUs
Aw, thanks! I really love your game… it is a very refreshing take on the platforming genre!
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?
Yeah, what you could do is sample points that are sort of “snapped” to a grid. For my game, it’s pixelated by virtue of the screen size, but if you wanted to “pixelate” it, you could totally just, instead of using UV, you’d make a new snapped UV by doing something like multiplying the UV by your screen resolution, then floor/ceil function, then dividing it by the screen resolution again.