Water Shader

Another water shader I found on YouTube, I did NOT create this shader, I’m just uploading it here for more people to use it and prestige the creator.

Original creator: StayAtHomeDev

Original video: https://youtu.be/7L6ZUYj1hs8

 

This are the default values:

shader_parameter/albedo = Color(0, 0.321569, 0.431373, 1)
shader_parameter/albedo2 = Color(0, 0.47451, 0.764706, 1)
shader_parameter/beers_law = 2.0
shader_parameter/color_deep = Color(0.105882, 0.294118, 0.329412, 1)
shader_parameter/color_shallow = Color(0, 0.552941, 0.65098, 1)
shader_parameter/depth_offset = -0.75
shader_parameter/edge_color = Color(1, 1, 1, 1)
shader_parameter/edge_scale = 0.1
shader_parameter/far = 100.0
shader_parameter/height_scale = 0.15
shader_parameter/metallic = 0.0
shader_parameter/near = 1.0
shader_parameter/noise_scale = 10.0
shader_parameter/roughness = 0.02
shader_parameter/texture_normal = NoiseTexture2D(perlin noise, with riged FBM, seamless and as normal)
shader_parameter/texture_normal2 = NoiseTexture2D(perlin noise, with riged FBM, seamless and as normal)
shader_parameter/time_scale = 0.025
shader_parameter/wave = NoiseTexture2D(perlin noise, seamless)
shader_parameter/wave_direction = Vector2(2, 0)
shader_parameter/wave_direction2 = Vector2(0, 1)

Shader code
shader_type spatial;
render_mode cull_disabled;

uniform vec3 albedo : source_color;
uniform vec3 albedo2 : source_color;
uniform float metallic : hint_range(0.0, 1.0) = 0;
uniform float roughness : hint_range(0.0, 1.0) = 0.02;
uniform sampler2D wave;
uniform sampler2D texture_normal;
uniform sampler2D texture_normal2;
uniform vec2 wave_direction = vec2(2.0,0.0); // Direction of wave 1
uniform vec2 wave_direction2 = vec2(0.0,1.0); // Direction of wave 2
uniform float time_scale : hint_range(0.0, 0.2, 0.005) = 0.025; // Rate of movement multiplied by TIME
uniform float noise_scale = 10.0;
uniform float height_scale = 0.15;

uniform vec4 color_deep : source_color; // Deep depth color
uniform vec4 color_shallow : source_color; // Shallow depth color
uniform float beers_law = 2.0; // Beer's law application
uniform float depth_offset = -0.75; // Offset

uniform float edge_scale = 0.1;
uniform float near = 1.0;
uniform float far = 100.0;
uniform vec3 edge_color : source_color;
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;

// Varying variables
varying float height;
varying vec3 world_pos;

float fresnel(float amount, vec3 normal, vec3 view)
{
	return pow((1.0 - clamp(dot(normalize(normal), normalize(view)), 0.0, 1.0 )), amount);
}
float edge(float depth){
	depth = 2.0 * depth - 1.0;
	return near * far / (far + depth * (near - far));
}

void vertex() {
	world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
	height = texture(wave, world_pos.xz / noise_scale + TIME * time_scale).r;
	VERTEX.y += height * height_scale;
}

void fragment() {
	// Depth variables and calc
	float depth_texture = texture(DEPTH_TEXTURE, SCREEN_UV).r * 2.0 - 1.0;
	float depth = PROJECTION_MATRIX[3][2] / (depth_texture + PROJECTION_MATRIX[2][2]);
	float depth_blend = exp((depth+VERTEX.z + depth_offset) * -beers_law);
	depth_blend = clamp(1.0 - depth_blend, 0.0, 1.0);	
	float depth_blend_power = clamp(pow(depth_blend, 2.5), 0.0, 1.0);

	// Retrieving depth color and applying the deep and shallow colors
	vec3 screen_color = textureLod(SCREEN_TEXTURE, SCREEN_UV, depth_blend_power * 2.5).rgb;
	vec3 depth_color = mix(color_shallow.rgb, color_deep.rgb, depth_blend_power);
	vec3 color = mix(screen_color * depth_color, depth_color * 0.25, depth_blend_power * 0.5);
	
	// Getting edge depth calc
	float z_depth = edge(texture(DEPTH_TEXTURE, SCREEN_UV).x);
	float z_pos = edge(FRAGCOORD.z);
	float z_dif = z_depth - z_pos;
	
	// Time calculations for wave (normal map) movement
	vec2 time = (TIME * wave_direction) * time_scale; // Movement rate of first wave
	vec2 time2 = (TIME * wave_direction2) * time_scale; // Movement rate of second wave
	
	// Blend normal maps into one
	vec3 normal_blend = mix(texture(texture_normal,world_pos.xz + time).rgb, texture(texture_normal2,world_pos.xz + time2).rgb, 0.5);
	
	// Calculate Fresnel
	float fresnel = fresnel(5.0, NORMAL, VIEW);
	vec3 surface_color = mix(albedo, albedo2, fresnel); // Interpolate albedo values by frensel
	
	vec3 depth_color_adj = mix(edge_color, color, step(edge_scale, z_dif));
	
	ALBEDO = clamp(surface_color + depth_color_adj,vec3(0.0),vec3(1.0));
	METALLIC = metallic;
	ROUGHNESS = roughness;
	NORMAL_MAP = normal_blend;
}
Tags
3d, 4, godot4, low, lowpoly, poly, shader, shaders, Spatial, 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 Verssales

Low poly water

(Another) Water Shader

Related shaders

Stylized Water Shader

Toon Style 3D Water Shader – No textures needed

Pixel Art Water Shader

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
maleykith
maleykith
9 months ago

This is great but beers law seem to have no effect on depth – if I use a sloped plane under my water plane, it has the same color all the way

onzelin
4 months ago

Text version of the tutorial from the original creator of the shader: https://stayathomedev.com/tutorials/single-plane-water-shader/