toon Water shader Godot 4.4+
took the toon shader 2d from another post here
Water Toon Torrent shader
Water Toon Torrent shader – Godot Shaders
and with a bit of fiddelling and some help made it workable for 3d just drag and drop it into a mader editor and your good most things
Shader code
shader_type spatial;
render_mode unshaded, blend_mix, cull_disabled, depth_draw_opaque;
// ===== Your existing params =====
uniform vec2 R = vec2(0.8, 0.6);
uniform float scale = 0.5;
uniform float speed = 1.0;
uniform vec3 direction = vec3(1.0, 1.0, 0.0);
uniform float distortion = 0.5;
uniform float layers = 2.0;
uniform float shades = 3.0;
uniform int steps = 6;
uniform vec3 tint = vec3(0.459, 0.765, 1.0);
// ===== Waves (Gerstner) =====
uniform vec2 wave1_dir = vec2(1.0, 0.2);
uniform float wave1_amp = 0.25;
uniform float wave1_len = 8.0;
uniform float wave1_steep = 0.6;
uniform float wave1_speed = 1.0;
uniform vec2 wave2_dir = vec2(0.3, 1.0);
uniform float wave2_amp = 0.12;
uniform float wave2_len = 3.5;
uniform float wave2_steep = 0.7;
uniform float wave2_speed = 1.6;
uniform float time_scale = 1.0;
// ---- noise for color ----
float gyroid(vec3 seed) { return dot(sin(seed), cos(seed.yzx)); }
float fbm(vec3 seed) {
float result = 0.0;
float a = 0.5;
for (int i = 0; i < steps; i++) {
seed += direction * TIME * speed * 0.01 / a;
seed.z += result * distortion;
result += gyroid(seed / a) * a;
a *= 0.5;
}
return result;
}
// Gerstner in object space
vec3 gerstner_obj(vec2 obj_xz, vec2 dir, float amp, float lambda, float steep, float spd, float t) {
dir = normalize(dir);
float k = 2.0 * PI / max(lambda, 0.001);
float phase = dot(dir, obj_xz) * k - spd * t;
float A = amp;
float Q = clamp(steep, 0.0, 1.0);
float c = cos(phase);
float s = sin(phase);
vec2 disp_xz = dir * (Q * A * c);
float disp_y = A * s;
return vec3(disp_xz.x, disp_y, disp_xz.y);
}
void vertex() {
float t = TIME * time_scale;
// Use local/object-space XZ for the wave phase (no world matrix needed)
vec2 obj_xz = VERTEX.xz;
vec3 d1 = gerstner_obj(obj_xz, wave1_dir, wave1_amp, wave1_len, wave1_steep, wave1_speed, t);
vec3 d2 = gerstner_obj(obj_xz, wave2_dir, wave2_amp, wave2_len, wave2_steep, wave2_speed, t);
vec3 disp = d1 + d2;
VERTEX += disp;
// Quick procedural normal (only matters if you later use lit shading)
vec2 eps = vec2(0.05, 0.0);
float h = (gerstner_obj(obj_xz, wave1_dir, wave1_amp, wave1_len, wave1_steep, wave1_speed, t).y
+ gerstner_obj(obj_xz, wave2_dir, wave2_amp, wave2_len, wave2_steep, wave2_speed, t).y);
float hx = (gerstner_obj(obj_xz + vec2(eps.x,0), wave1_dir, wave1_amp, wave1_len, wave1_steep, wave1_speed, t).y
+ gerstner_obj(obj_xz + vec2(eps.x,0), wave2_dir, wave2_amp, wave2_len, wave2_steep, wave2_speed, t).y);
float hz = (gerstner_obj(obj_xz + vec2(0,eps.x), wave1_dir, wave1_amp, wave1_len, wave1_steep, wave1_speed, t).y
+ gerstner_obj(obj_xz + vec2(0,eps.x), wave2_dir, wave2_amp, wave2_len, wave2_steep, wave2_speed, t).y);
vec3 dx = vec3(eps.x, hx - h, 0.0);
vec3 dz = vec3(0.0, hz - h, eps.x);
NORMAL = normalize(cross(dz, dx));
}
void fragment() {
// Keep your 2D-water look
vec2 p = (2.0 * UV - R) / R.y;
float shape = fbm(vec3(p * scale, 0.0));
float gradient = fract(shape * layers);
float shade = round(pow(gradient, 4.0) * shades) / shades;
vec3 color = mix(tint * mix(0.6, 0.8, gradient), vec3(1.0), shade);
ALBEDO = color;
EMISSION = color;
ALPHA = 1.0;
}


