Ocean Test_1
re
Shader code
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_disabled, diffuse_burley, specular_schlick_ggx;
// Core Color Uniforms
uniform vec4 primary_colour : source_color;
uniform vec4 secondary_color: source_color;
uniform float roughness : hint_range(0.0, 1.0) = 0.2;
uniform bool fernalEnabled = true;
// Texture Uniforms
uniform sampler2D normalmapA : hint_normal, filter_linear_mipmap_anisotropic;
uniform sampler2D normalmapB : hint_normal, filter_linear_mipmap_anisotropic;
uniform bool enable_second_normalmap = true;
uniform sampler2D screeen_texture : hint_screen_texture, repeat_disable, filter_nearest;
uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;
// Global Control Toggles
uniform bool enable_depth_effects = true;
uniform bool use_compatibility_mode = false; // Turn ON if running on Mobile/WebGL/Compatibility backend
// Depth & Beer's Law Variables
uniform float depth_distance : hint_range(0.0, 20.0, 0.1) = 4.0;
uniform float beers_law : hint_range(0.0, 20.0, 0.1) = 12.0;
uniform float water_transpareny : hint_range(0.0, 1.0, 0.01) = 0.05;
// Refraction Uniforms
uniform float refraction_strength : hint_range(0.0, 1.0, 0.01) = 0.02;
// Ripples Tuning
uniform float normalmapAstrength : hint_range(0.0, 1.0) = 0.3;
uniform float model_normal_b_strength : hint_range(0.0, 1.0) = 0.4;
uniform vec2 movementdirection = vec2(0.2, 0.1);
uniform float movementstrength = 0.1;
uniform float UV_Scale = 25.0;
// Contrast Sharpening
uniform float smooth_edge_low : hint_range(-1.0, 1.0) = -0.5;
uniform float smooth_edge_high : hint_range(-1.0, 1.0) = 0.5;
void fragment() {
// --- 1. CORE MOVING NORMAL MAPS GENERATION ---
vec2 scaled_uv = UV * UV_Scale;
float time_scaled = TIME * movementstrength;
// Sample primary moving map
vec3 texA = texture(normalmapA, scaled_uv + (movementdirection * time_scaled)).rgb;
vec3 blended_normal = texA * vec3(normalmapAstrength, normalmapAstrength, 1.0);
// Dynamically blend secondary rotated moving map to hide repetition
if (enable_second_normalmap) {
vec2 dirB = vec2(movementdirection.x * 0.5 - movementdirection.y * 0.866, movementdirection.x * 0.866 + movementdirection.y * 0.5);
vec2 uvB = scaled_uv - (dirB * (time_scaled * 1.15)) + vec2(0.32, 0.71);
vec3 texB = texture(normalmapB, uvB).rgb;
vec3 n2 = texB * vec3(model_normal_b_strength, model_normal_b_strength, 1.0);
blended_normal = vec3(blended_normal.xy + n2.xy, blended_normal.z * n2.z);
}
// Apply visual sharpening pass to normal values
blended_normal.x = smoothstep(smooth_edge_low, smooth_edge_high, blended_normal.x) * 2.0 - 1.0;
blended_normal.y = smoothstep(smooth_edge_low, smooth_edge_high, blended_normal.y) * 2.0 - 1.0;
// Set baseline outputs
vec3 final_albedo = primary_colour.rgb;
float depth_blend_factor = 0.0;
float basic_frenel = pow(1.0 - clamp(dot(normalize(NORMAL), normalize(VIEW)), 0.0, 1.0), 3.0);
// --- 2. DEPTH EFFECTS, BEER'S LAW, AND REFRACTION ---
if (enable_depth_effects) {
// Distort screen space coordinate using normal vectors
vec2 refracted_uv = SCREEN_UV + (blended_normal.xy * refraction_strength);
float depth_raw = textureLod(depth_texture, refracted_uv, 0.0).r;
float water_depth = 0.0;
if (use_compatibility_mode) {
// Compatibility (OpenGL) depth-reconstruction pass
vec4 upos = INV_PROJECTION_MATRIX * vec4(refracted_uv * 2.0 - 1.0, depth_raw, 1.0);
water_depth = (-upos.z / upos.w) + VERTEX.z;
// Shoreline bleeding cleanup safety catch
if (water_depth < 0.0) {
refracted_uv = SCREEN_UV;
depth_raw = textureLod(depth_texture, SCREEN_UV, 0.0).r;
upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth_raw, 1.0);
water_depth = (-upos.z / upos.w) + VERTEX.z;
}
} else {
// Forward++ (Vulkan) world-space depth-reconstruction pass
vec3 ndc = vec3(refracted_uv * 2.0 - 1.0, depth_raw);
vec4 world = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
float vertex_y = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).y;
water_depth = vertex_y - (world.y / world.w);
// Shoreline bleeding cleanup safety catch
if (water_depth < 0.0) {
refracted_uv = SCREEN_UV;
depth_raw = textureLod(depth_texture, SCREEN_UV, 0.0).r;
ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth_raw);
world = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
vertex_y = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).y;
water_depth = vertex_y - (world.y / world.w);
}
}
// Map linear depth to exponential Beer's law curve
float linear_depth_blend = clamp(water_depth / depth_distance, 0.0, 1.0);
depth_blend_factor = exp(-linear_depth_blend * beers_law);
// Grab background screen buffer and compile final color stack
vec3 screen = texture(screeen_texture, refracted_uv).rgb;
vec3 depth_color = mix(secondary_color, primary_colour, depth_blend_factor).rgb;
vec3 background_mix = mix(depth_color, screen, water_transpareny);
if (fernalEnabled) {
final_albedo = mix(background_mix, screen, depth_blend_factor * (1.0 - basic_frenel));
} else {
final_albedo = mix(background_mix, screen, depth_blend_factor);
}
} else {
// Baseline color mode fallback when depth logic is checked off completely
if (fernalEnabled) {
final_albedo = primary_colour.rgb + (0.2 * basic_frenel);
}
}
// --- 3. FINAL PIPELINE ASSIGNMENTS ---
ALBEDO = final_albedo;
NORMAL_MAP = normalize(blended_normal);
ROUGHNESS = (fernalEnabled) ? roughness * (1.0 - basic_frenel) : roughness;
ALPHA = (enable_depth_effects) ? 1.0 : water_transpareny;
}
