Snell’s Window

A simple, physically based Snell’s window term. The relevant portion is the snells_window function, which you can incorporate into your own water shader. The rest of the code is just for demo.

float snells_window(vec3 normal, vec3 view, float ior) {
	float cos_theta = dot(normal, view);
	return step(sqrt(1.0 - cos_theta * cos_theta) * ior, 1.0);
}
Shader code
shader_type spatial;
render_mode cull_disabled;

uniform sampler2D screen_texture : hint_screen_texture, source_color, repeat_disable;
uniform sampler2D normal_map_texture : hint_normal;
uniform vec3 water_color : source_color = vec3(0.0625, 0.1992, 0.3594);
uniform float index_of_refraction = 1.333;

// Returns 1.0 if we can see above the water, 0.0 otherwise
float snells_window(vec3 normal, vec3 view, float ior) {
	float cos_theta = dot(normal, view);
	return step(sqrt(1.0 - cos_theta * cos_theta) * ior, 1.0);
}

void fragment() {
	ROUGHNESS = 0.0;

	// Basic waves
	float time = TIME * 0.05;
	vec3 normal_sample_1 = texture(normal_map_texture, UV + vec2(-1, 1) * time).xyz * 2.0 - 1.0;
	vec3 normal_sample_2 = texture(normal_map_texture, -UV + vec2(0, 1) * time).xyz * 2.0 - 1.0;
	vec3 normal_map = vec3(normal_sample_1.xy + normal_sample_2.xy, 0.0);
	
	// Set NORMAL directly since we need to use it later
	NORMAL_MAP_DEPTH = 1.0;
	normal_map.z = sqrt(max(0.0, 1.0 - dot(normal_map.xy, normal_map.xy)));
	NORMAL = normalize(mix(NORMAL, TANGENT * normal_map.x + BINORMAL * normal_map.y + NORMAL * normal_map.z, NORMAL_MAP_DEPTH));
	
	// Screen distortion
	vec2 distorted_uv = SCREEN_UV - normal_map.xy * 2.0 / length(VERTEX);
	ALBEDO = texture(screen_texture, distorted_uv).rgb;
	
	// Apply Snell's window mask to water surface when viewed from below
	if(!FRONT_FACING) {
		float mask = snells_window(NORMAL, VIEW, index_of_refraction);
		ALBEDO = mix(water_color, ALBEDO, mask);
		RADIANCE = vec4(vec3(0.0), mask);
		IRRADIANCE = vec4(vec3(1.0), mask);
	}
}
Tags
reflection, refraction, snell's law, Subnautica, underwater, 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 tentabrobpy

N64 Style Skybox

Surface Embedded Sprites

Local Screen Space UV

Related shaders

Procedural Window Rain Drop Shader

Basic Skyscraper Window Lights

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Star_Zebra_10
Star_Zebra_10
23 days ago

this looks so cool! thanks for making it 🙂

Last edited 23 days ago by Star_Zebra_10