initial shit

This commit is contained in:
2026-06-04 16:53:41 -05:00
parent f019615187
commit d3779cff20
828 changed files with 512567 additions and 0 deletions

View File

@@ -0,0 +1,195 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
uniform sampler2D blend_noise : source_color;
group_uniforms Surface_detail;
uniform float normal_scale : hint_range(-16.0, 16.0) = 1.0;
uniform float specular : hint_range(0.0, 1.0, 0.01);
uniform float metallic : hint_range(0.0, 1.0, 0.01);
uniform float roughness : hint_range(0.0, 1.0);
group_uniforms MainTexture;
uniform sampler2D main_texture : source_color, repeat_enable, filter_linear_mipmap;
uniform vec4 main_texture_color : source_color = vec4(1.0);
uniform float main_uv_scale = 1.0;
uniform vec3 main_uv_offset;
uniform bool main_uv_triplanar = false;
uniform float main_uv_blend_sharpness: hint_range(0.0, 150.0, 0.001) = 1.0;
uniform sampler2D main_normal: hint_roughness_normal, filter_linear_mipmap, repeat_enable;
group_uniforms SecondaryTexture;
uniform sampler2D secondary_texture : source_color, repeat_enable, filter_linear_mipmap;
uniform vec4 secondary_texture_color : source_color = vec4(1.0);
uniform float secondary_uv_scale = 1.0;
uniform vec3 secondary_uv_offset;
uniform bool secondary_uv_triplanar = false;
uniform float secondary_uv_blend_sharpness : hint_range(0.0, 150.0, 0.001) = 1.0;
uniform sampler2D secondary_normal: hint_roughness_normal, filter_linear_mipmap, repeat_enable;
varying vec3 main_uv_power_normal;
varying vec3 main_uv_triplanar_pos;
varying vec3 secondary_uv_power_normal;
varying vec3 secondary_uv_triplanar_pos;
varying vec3 world_position;
vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {
vec4 sampler = vec4(0.0);
sampler += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;
sampler += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;
sampler += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;
return sampler;
}
// Cheapest method, better performance and good results.
vec3 simple_blending(vec3 a, vec3 b) {
a = a * 2.0 - 1.0;
b = b * 2.0 - 1.0;
vec3 result = vec3(a.xy + b.xy, 1.0);
return result * 0.5 + 0.5;
}
// Better results but more performant cost
vec3 unity_blending(vec3 a, vec3 b) {
a = a * 2.0 - 1.0;
b = b * 2.0 - 1.0;
mat3 basis = mat3(
vec3(a.z, a.y, -a.x),
vec3(a.x, a.z, -a.y),
a
);
vec3 result = normalize(basis * b);
return result * 0.5 + 0.5;
}
// Performance friendly, good results
vec3 whiteout_blending(vec3 a, vec3 b) {
a = a * 2.0 - 1.0;
b = b * 2.0 - 1.0;
vec3 result = normalize(vec3(a.xy + b.xy, a.z * b.z));
return result * 0.5 + 0.5;
}
vec3 udm_blending(vec3 a, vec3 b) {
a = a * 2.0 - 1.0;
b = b * 2.0 - 1.0;
vec3 result = normalize(vec3(a.xy + b.xy, a.z));
return result * 0.5 + 0.5;
}
void vertex() {
world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
vec3 normal = NORMAL;
TANGENT = vec3(0.0, 0.0, -1.0) * abs(normal.x);
TANGENT += vec3(1.0, 0.0, 0.0) * abs(normal.y);
TANGENT += vec3(1.0, 0.0, 0.0) * abs(normal.z);
TANGENT = normalize(TANGENT);
BINORMAL = vec3(0.0, 1.0, 0.0) * abs(normal.x);
BINORMAL += vec3(0.0, 0.0, -1.0) * abs(normal.y);
BINORMAL += vec3(0.0, 1.0, 0.0) * abs(normal.z);
BINORMAL = normalize(BINORMAL);
// Main UV Triplanar: Enabled
if (main_uv_triplanar) {
main_uv_power_normal = pow(abs(NORMAL), vec3(main_uv_blend_sharpness));
main_uv_triplanar_pos = VERTEX * main_uv_scale + main_uv_offset;
main_uv_power_normal /= dot(main_uv_power_normal, vec3(1.0));
main_uv_triplanar_pos *= vec3(1.0, -1.0, 1.0);
}
// Secondary UV Triplanar: Enabled
if (secondary_uv_triplanar) {
secondary_uv_power_normal = pow(abs(NORMAL), vec3(secondary_uv_blend_sharpness));
secondary_uv_triplanar_pos = VERTEX * secondary_uv_scale + secondary_uv_offset;
secondary_uv_power_normal /= dot(secondary_uv_power_normal, vec3(1.0));
secondary_uv_triplanar_pos *= vec3(1.0, -1.0, 1.0);
}
}
void fragment() {
vec4 main_albedo;
vec4 m_normal;
vec4 s_normal;
if (main_uv_triplanar) {
main_albedo = triplanar_texture(main_texture, main_uv_power_normal, main_uv_triplanar_pos);
m_normal = triplanar_texture(main_normal, main_uv_power_normal, main_uv_triplanar_pos);
} else {
main_albedo = texture(main_texture, UV * vec2(main_uv_scale));
m_normal = texture(main_normal, UV * vec2(main_uv_scale));
}
main_albedo *= main_texture_color;
vec4 secondary_albedo;
if (secondary_uv_triplanar) {
secondary_albedo = triplanar_texture(secondary_texture, secondary_uv_power_normal, secondary_uv_triplanar_pos);
s_normal = triplanar_texture(secondary_normal, secondary_uv_power_normal, secondary_uv_triplanar_pos);
} else {
secondary_albedo = texture(secondary_texture, UV * vec2(secondary_uv_scale));
s_normal = texture(secondary_normal, UV * vec2(secondary_uv_scale));
}
secondary_albedo *= secondary_texture_color;
vec4 blend_noise_texture = texture(blend_noise, UV);
vec3 blended_albedo = mix(vec3(main_albedo.xyz), vec3(secondary_albedo.xyz), vec3(blend_noise_texture.xyz));
vec3 combined_normal = whiteout_blending(m_normal.rgb, s_normal.rgb);
// Makes the final texture uniform decomposing & composing the rgb channels
vec3 albedo_rgb_to_hsv;
{
vec3 c = blended_albedo;
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
albedo_rgb_to_hsv = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// VectorDecompose
float rgb_x = albedo_rgb_to_hsv.x;
float rgb_y = albedo_rgb_to_hsv.y;
float rgb_z = albedo_rgb_to_hsv.z;
// VectorCompose:
vec3 rgb_composed = vec3(rgb_x, rgb_y, rgb_z);
vec3 final_rgb_albedo;
{
vec3 c = rgb_composed;
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
final_rgb_albedo = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
ALBEDO = final_rgb_albedo;
NORMAL_MAP = combined_normal;
NORMAL_MAP_DEPTH = normal_scale;
ROUGHNESS = roughness;
METALLIC = metallic;
SPECULAR = specular;
}

View File

@@ -0,0 +1 @@
uid://51hjja8kpjgn

View File

@@ -0,0 +1,52 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
uniform sampler2D albedo_texture : source_color, repeat_enable, filter_linear_mipmap;
uniform sampler2D albedo_seam : source_color, repeat_enable, filter_linear_mipmap;
uniform float uv_scale = 1.0;
uniform vec2 pivot_point = vec2(0.500000, 0.500000);
// Noise type should be "cellular", fractal type "none" and return type "cell_value"
uniform sampler2D rotation_noise : source_color;
// This Noise type should be exactly the same as the rotation noise except for return type as "distance2sub"
// When changing any parameter of the rotation noise, the seam mending noise must be updated too
// The color ramp needs to be from white(left) and black(right) so the seams can be hidden.
uniform sampler2D seam_mending_noise : source_color;
void fragment() {
vec2 albedo_uv = UV * vec2(uv_scale);
float rotation_degrees;
// Remap noise value [0, 1] to degrees [0, 360]
float input_min_value = 0.00000;
float input_max_value = 1.00000;
float output_min_value = 0.00000;
float output_max_value = 360.00000;
{
float __input_range = input_max_value - input_min_value;
float __output_range = output_max_value - output_min_value;
rotation_degrees = output_min_value + __output_range * ((texture(rotation_noise, UV).x - input_min_value) / __input_range);
}
vec2 final_albedo;
// Expression:7
final_albedo = vec2(0.0, 0.0);
{
albedo_uv -= pivot_point;
float rotation_radians = radians(rotation_degrees);
float c = cos(rotation_radians);
float s = sin(rotation_radians);
final_albedo.x = albedo_uv.x * c + albedo_uv.y * s;
final_albedo.y = albedo_uv.y * c - albedo_uv.x * s;
final_albedo += pivot_point;
}
ALBEDO = mix(vec3(texture(albedo_seam, final_albedo).xyz), vec3(texture(albedo_texture, albedo_uv).xyz), vec3(texture(seam_mending_noise, UV).xyz));
}

View File

@@ -0,0 +1 @@
uid://0tuphwonvajg

View File

@@ -0,0 +1,369 @@
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform float blend_factor : hint_range(0.1, 50.0) = 5.0;
uniform float fade_range = 5.0;
uniform float height_dirt = 5.0;
uniform float height_grass = 15.0;
uniform float height_mountain = 30.0;
//uniform float roughness : hint_range(0.0, 1.0) = 1.0;
//uniform float ao_light_affect : hint_range(0.0, 1.0);
group_uniforms Dirt;
uniform sampler2D dirt_albedo : source_color, repeat_enable, filter_linear_mipmap, hint_default_white;
//uniform sampler2D dirt_orm : source_color;
uniform float dirt_blend_sharpness = 1.0;
uniform float dirt_uv_scale : hint_range(0.01, 10.0, 0.01) = 1.0;
uniform float dirt_stochastic_strength : hint_range(0.0, 1.0) = 0;
uniform float dirt_stochastic_rotation_max_angle : hint_range(0.0, 3.14159) = 0;
group_uniforms Grass;
uniform sampler2D grass_albedo : source_color, repeat_enable, filter_linear_mipmap, hint_default_white;
//uniform sampler2D grass_orm : source_color;
uniform float grass_blend_sharpness = 1.0;
uniform float grass_uv_scale : hint_range(0.01, 10.0, 0.01) = 1.0;
uniform float grass_stochastic_strength : hint_range(0.0, 1.0) = 0;
uniform float grass_stochastic_rotation_max_angle : hint_range(0.0, 3.14159) = 0;
group_uniforms Mountain;
uniform sampler2D mountain_albedo : source_color, repeat_enable, filter_linear_mipmap, hint_default_white;
//uniform sampler2D mountain_orm : source_color;
uniform float mountain_blend_sharpness = 1.0;
uniform float mountain_uv_scale : hint_range(0.01, 10.0, 0.01) = 1.0;
uniform float mountain_stochastic_strength : hint_range(0.0, 1.0) = 0;
uniform float mountain_stochastic_rotation_max_angle : hint_range(0.0, 3.14159) = 0;
// ================================================================
// Varyings
// Data passed from Vertex Shader to Fragment Shader
// ================================================================
varying vec3 world_pos; // Original vertex position in world space
varying vec3 triplanar_normal_abs; // Absolute world-space normal for triplanar blending weights
varying mat3 tangent_2_local;
// Simple hash function to generate pseudo-random numbers based on a 2D input.
// Used for consistent random offsets per "tile" in stochastic sampling.
float hash21(vec2 p) {
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
}
mat2 rotate2d(float angle) {
float s = sin(angle);
float c = cos(angle);
return mat2(vec2(c, s), vec2(-s, c));
}
// Helper function to unpack a normal from 0-1 range (texture) to -1 to 1 range (vector).
vec3 unpack_normal(vec3 packed_normal) {
return packed_normal * 2.0 - 1.0;
}
// Helper function to pack a normal from -1 to 1 range (vector) to 0-1 range (for NORMAL_MAP output).
vec3 pack_normal(vec3 unpacked_normal) {
return unpacked_normal * 0.5 + 0.5;
}
vec2 rotate_uv(vec2 uv, float angle) {
float s = sin(angle);
float c = cos(angle);
return mat2(vec2(c, -s), vec2(s, c)) * uv;
}
vec2 stochastic_uv(vec2 uv, float strength, float max_rotation_angle) {
// Get the tile index based on floor of UV
vec2 tile_index = floor(uv);
// Use tile index to generate rotation and offset
float angle = hash21(tile_index) * max_rotation_angle;
vec2 offset = vec2(hash21(tile_index + 1.3), hash21(tile_index + 2.1)) - 0.5;
// Apply rotation and offset within each tile
vec2 local_uv = fract(uv) + offset * strength;
local_uv = rotate_uv(local_uv - 0.5, angle) + 0.5;
return local_uv;
}
// Triplanar texture sampling with 4-sample stochastic anti-tiling for RGB textures.
// Includes random per-tile rotation and offset.
// tex: The texture to sample.
// p: Scaled world position (uv_scale * world_pos).
// normal_abs: Absolute world normal for blending between X, Y, Z projections.
// k: Triplanar blend factor (blend_factor).
// strength: Stochastic displacement strength (stochastic_strength).
// max_rotation_angle: Maximum random rotation angle (stochastic_rotation_max_angle).
vec3 apply_triplanar_texture_stochastic_rgb(sampler2D tex, vec3 p, vec3 normal_abs, float k, float strength, float max_rotation_angle) {
// Calculate base UVs for each projection plane
vec2 uv_xy = p.xy; // For Z-axis projection (top-down)
vec2 uv_yz = p.yz; // For X-axis projection (side)
vec2 uv_xz = p.xz; // For Y-axis projection (side)
// --- XY Plane Projection (Z-axis) ---
// Get the integer part of UV for a consistent random seed per tile
vec2 tile_id_xy = floor(uv_xy);
// Generate random rotation angle for this tile
float random_angle_xy = hash21(tile_id_xy) * max_rotation_angle;
mat2 rot_mat_xy = rotate2d(random_angle_xy);
// Generate two random offsets for displacement (ensure distinct hashes for x,y components)
vec2 rand_offset_xy = vec2(hash21(tile_id_xy + vec2(0.1, 0.0)), hash21(tile_id_xy + vec2(0.0, 0.1))) * strength;
// Calculate the 'base' sampling UV by applying rotation around tile center
// and then adding the random offset.
// This 'base_sampling_uv' is the reference point for the 4 samples and the blending.
vec2 base_sampling_uv_xy = (uv_xy - tile_id_xy - vec2(0.5)) * rot_mat_xy + tile_id_xy + vec2(0.5) + rand_offset_xy;
// Use the fractional part of this base sampling UV for the blending weights
vec2 frac_uv_for_blend_xy = fract(base_sampling_uv_xy);
float blend_x_xy = smoothstep(0.4, 0.6, frac_uv_for_blend_xy.x);
float blend_y_xy = smoothstep(0.4, 0.6, frac_uv_for_blend_xy.y);
// Sample the texture 4 times. The (0,0), (1,0), etc. offsets are relative to the
// potentially rotated and offset grid.
vec3 s00_xy = texture(tex, base_sampling_uv_xy).rgb;
vec3 s10_xy = texture(tex, base_sampling_uv_xy + vec2(1.0, 0.0)).rgb;
vec3 s01_xy = texture(tex, base_sampling_uv_xy + vec2(0.0, 1.0)).rgb;
vec3 s11_xy = texture(tex, base_sampling_uv_xy + vec2(1.0, 1.0)).rgb;
// Blend the 4 samples using bilinear interpolation based on fractional UV
vec3 color_xy = mix(mix(s00_xy, s10_xy, blend_x_xy), mix(s01_xy, s11_xy, blend_x_xy), blend_y_xy);
// --- YZ Plane Projection (X-axis) ---
vec2 tile_id_yz = floor(uv_yz);
float random_angle_yz = hash21(tile_id_yz) * max_rotation_angle;
mat2 rot_mat_yz = rotate2d(random_angle_yz);
vec2 rand_offset_yz = vec2(hash21(tile_id_yz + vec2(0.1, 0.0)), hash21(tile_id_yz + vec2(0.0, 0.1))) * strength;
vec2 base_sampling_uv_yz = (uv_yz - tile_id_yz - vec2(0.5)) * rot_mat_yz + tile_id_yz + vec2(0.5) + rand_offset_yz;
vec2 frac_uv_for_blend_yz = fract(base_sampling_uv_yz);
float blend_x_yz = smoothstep(0.4, 0.6, frac_uv_for_blend_yz.x);
float blend_y_yz = smoothstep(0.4, 0.6, frac_uv_for_blend_yz.y);
vec3 s00_yz = texture(tex, base_sampling_uv_yz).rgb;
vec3 s10_yz = texture(tex, base_sampling_uv_yz + vec2(1.0, 0.0)).rgb;
vec3 s01_yz = texture(tex, base_sampling_uv_yz + vec2(0.0, 1.0)).rgb;
vec3 s11_yz = texture(tex, base_sampling_uv_yz + vec2(1.0, 1.0)).rgb;
vec3 color_yz = mix(mix(s00_yz, s10_yz, blend_x_yz), mix(s01_yz, s11_yz, blend_x_yz), blend_y_yz);
// --- XZ Plane Projection (Y-axis) ---
vec2 tile_id_xz = floor(uv_xz);
float random_angle_xz = hash21(tile_id_xz) * max_rotation_angle;
mat2 rot_mat_xz = rotate2d(random_angle_xz);
vec2 rand_offset_xz = vec2(hash21(tile_id_xz + vec2(0.1, 0.0)), hash21(tile_id_xz + vec2(0.0, 0.1))) * strength;
vec2 base_sampling_uv_xz = (uv_xz - tile_id_xz - vec2(0.5)) * rot_mat_xz + tile_id_xz + vec2(0.5) + rand_offset_xz;
vec2 frac_uv_for_blend_xz = fract(base_sampling_uv_xz);
float blend_x_xz = smoothstep(0.4, 0.6, frac_uv_for_blend_xz.x);
float blend_y_xz = smoothstep(0.4, 0.6, frac_uv_for_blend_xz.y);
vec3 s00_xz = texture(tex, base_sampling_uv_xz).rgb;
vec3 s10_xz = texture(tex, base_sampling_uv_xz + vec2(1.0, 0.0)).rgb;
vec3 s01_xz = texture(tex, base_sampling_uv_xz + vec2(0.0, 1.0)).rgb;
vec3 s11_xz = texture(tex, base_sampling_uv_xz + vec2(1.0, 1.0)).rgb;
vec3 color_xz = mix(mix(s00_xz, s10_xz, blend_x_xz), mix(s01_xz, s11_xz, blend_x_xz), blend_y_xz);
// Calculate blend weights for triplanar projection itself (based on normal direction)
vec3 blend_weights = pow(normal_abs, vec3(k));
blend_weights /= dot(blend_weights, vec3(1.0)); // Normalize weights to sum to 1
// Final triplanar blend: combine the three projected colors using the calculated weights
return color_yz * blend_weights.x + color_xz * blend_weights.y + color_xy * blend_weights.z;
}
vec4 apply_triplanar_texture_stochastic_rgba(
sampler2D tex,
vec3 p,
vec3 normal_abs,
float k,
float strength,
float max_rotation_angle
) {
vec2 uv_xy = p.xy;
vec2 uv_yz = p.yz;
vec2 uv_xz = p.xz;
// XY
vec2 tile_id_xy = floor(uv_xy);
float random_angle_xy = hash21(tile_id_xy) * max_rotation_angle;
mat2 rot_mat_xy = rotate2d(random_angle_xy);
vec2 rand_offset_xy = vec2(hash21(tile_id_xy + vec2(0.1, 0.0)), hash21(tile_id_xy + vec2(0.0, 0.1))) * strength;
vec2 base_uv_xy = (uv_xy - tile_id_xy - vec2(0.5)) * rot_mat_xy + tile_id_xy + vec2(0.5) + rand_offset_xy;
vec2 frac_uv_xy = fract(base_uv_xy);
float blend_x_xy = smoothstep(0.4, 0.6, frac_uv_xy.x);
float blend_y_xy = smoothstep(0.4, 0.6, frac_uv_xy.y);
vec4 s00_xy = texture(tex, base_uv_xy);
vec4 s10_xy = texture(tex, base_uv_xy + vec2(1.0, 0.0));
vec4 s01_xy = texture(tex, base_uv_xy + vec2(0.0, 1.0));
vec4 s11_xy = texture(tex, base_uv_xy + vec2(1.0, 1.0));
vec4 color_xy = mix(mix(s00_xy, s10_xy, blend_x_xy), mix(s01_xy, s11_xy, blend_x_xy), blend_y_xy);
// YZ
vec2 tile_id_yz = floor(uv_yz);
float random_angle_yz = hash21(tile_id_yz) * max_rotation_angle;
mat2 rot_mat_yz = rotate2d(random_angle_yz);
vec2 rand_offset_yz = vec2(hash21(tile_id_yz + vec2(0.1, 0.0)), hash21(tile_id_yz + vec2(0.0, 0.1))) * strength;
vec2 base_uv_yz = (uv_yz - tile_id_yz - vec2(0.5)) * rot_mat_yz + tile_id_yz + vec2(0.5) + rand_offset_yz;
vec2 frac_uv_yz = fract(base_uv_yz);
float blend_x_yz = smoothstep(0.4, 0.6, frac_uv_yz.x);
float blend_y_yz = smoothstep(0.4, 0.6, frac_uv_yz.y);
vec4 s00_yz = texture(tex, base_uv_yz);
vec4 s10_yz = texture(tex, base_uv_yz + vec2(1.0, 0.0));
vec4 s01_yz = texture(tex, base_uv_yz + vec2(0.0, 1.0));
vec4 s11_yz = texture(tex, base_uv_yz + vec2(1.0, 1.0));
vec4 color_yz = mix(mix(s00_yz, s10_yz, blend_x_yz), mix(s01_yz, s11_yz, blend_x_yz), blend_y_yz);
// XZ
vec2 tile_id_xz = floor(uv_xz);
float random_angle_xz = hash21(tile_id_xz) * max_rotation_angle;
mat2 rot_mat_xz = rotate2d(random_angle_xz);
vec2 rand_offset_xz = vec2(hash21(tile_id_xz + vec2(0.1, 0.0)), hash21(tile_id_xz + vec2(0.0, 0.1))) * strength;
vec2 base_uv_xz = (uv_xz - tile_id_xz - vec2(0.5)) * rot_mat_xz + tile_id_xz + vec2(0.5) + rand_offset_xz;
vec2 frac_uv_xz = fract(base_uv_xz);
float blend_x_xz = smoothstep(0.4, 0.6, frac_uv_xz.x);
float blend_y_xz = smoothstep(0.4, 0.6, frac_uv_xz.y);
vec4 s00_xz = texture(tex, base_uv_xz);
vec4 s10_xz = texture(tex, base_uv_xz + vec2(1.0, 0.0));
vec4 s01_xz = texture(tex, base_uv_xz + vec2(0.0, 1.0));
vec4 s11_xz = texture(tex, base_uv_xz + vec2(1.0, 1.0));
vec4 color_xz = mix(mix(s00_xz, s10_xz, blend_x_xz), mix(s01_xz, s11_xz, blend_x_xz), blend_y_xz);
// Triplanar blending with control over blending strength
vec3 weights = pow(normal_abs, vec3(k));
weights /= max(dot(weights, vec3(1.0)), 0.0001);
return color_yz * weights.x + color_xz * weights.y + color_xy * weights.z;
}
vec3 apply_triplanar_texture_stochastic_normal(
sampler2D normal_map,
vec3 pos,
vec3 normal_abs,
float blend_sharpness,
float strength,
float max_rotation_angle
) {
// === Weights ===
vec3 weights = pow(normal_abs, vec3(blend_sharpness));
weights /= max(dot(weights, vec3(1.0)), 0.0001);
// === Projected stochastic UVs ===
vec2 uv_yz = stochastic_uv(pos.yz, strength, max_rotation_angle);
vec2 uv_xz = stochastic_uv(pos.xz, strength, max_rotation_angle);
vec2 uv_xy = stochastic_uv(pos.xy, strength, max_rotation_angle);
// === Sample and unpack normal maps ===
vec3 n_yz = unpack_normal(texture(normal_map, uv_yz).rgb);
vec3 n_xz = unpack_normal(texture(normal_map, uv_xz).rgb);
vec3 n_xy = unpack_normal(texture(normal_map, uv_xy).rgb);
n_yz *= tangent_2_local;
n_xz *= tangent_2_local;
n_xy *= tangent_2_local;
// === Reorient normals from tangent space to world-space projection axis ===
// YZ projection (X facing) → local Z = +X
vec3 world_n_yz = vec3(n_yz.z, n_yz.x, n_yz.y);
// XZ projection (Y facing) → local Z = +Y
vec3 world_n_xz = vec3(n_xz.x, n_xz.z, n_xz.y);
// XY projection (Z facing) → local Z = +Z
vec3 world_n_xy = vec3(n_xy.x, n_xy.y, n_xy.z);
// === Blend and normalize ===
vec3 blended = normalize(
world_n_yz * weights.x +
world_n_xz * weights.y +
world_n_xy * weights.z
);
return blended;
}
// ================================================================
// Vertex Shader
// Prepares world-space position and absolute normal for triplanar mapping
// ================================================================
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
triplanar_normal_abs = abs(NORMAL);
TANGENT = vec3(0.0,0.0,-1.0) * abs(triplanar_normal_abs.x);
TANGENT += vec3(1.0,0.0,0.0) * abs(triplanar_normal_abs.y);
TANGENT += vec3(1.0,0.0,0.0) * abs(triplanar_normal_abs.z);
TANGENT = normalize(TANGENT);
BINORMAL = vec3(0.0,1.0,0.0) * abs(triplanar_normal_abs.x);
BINORMAL += vec3(0.0,0.0,-1.0) * abs(triplanar_normal_abs.y);
BINORMAL += vec3(0.0,1.0,0.0) * abs(triplanar_normal_abs.z);
BINORMAL = normalize(BINORMAL);
tangent_2_local = MODEL_NORMAL_MATRIX * mat3(TANGENT, BINORMAL, NORMAL);
//normalize all components, so the UVs don't get scaled when scaling mesh
tangent_2_local[0] = normalize(tangent_2_local[0]);
tangent_2_local[1] = normalize(tangent_2_local[1]);
tangent_2_local[2] = normalize(tangent_2_local[2]);
}
// ================================================================
// Fragment Shader
// Calculates final material properties
// ================================================================
void fragment() {
float height = world_pos.y;
float blend_dirt = 1.0 - smoothstep(height_dirt, height_dirt + fade_range, height);
float blend_grass = smoothstep(height_dirt, height_grass, height) * (1.0 - smoothstep(height_grass, height_mountain, height));
float blend_mountain = smoothstep(height_grass, height_mountain, height);
//Apply blend sharpness
blend_dirt = pow(blend_dirt, dirt_blend_sharpness);
blend_grass = pow(blend_grass, grass_blend_sharpness);
blend_mountain = pow(blend_mountain, mountain_blend_sharpness);
// Normalize weights (if necessary — this makes sure they add up to 1.0)
float total = blend_dirt + blend_grass + blend_mountain;
blend_dirt /= total;
blend_grass /= total;
blend_mountain /= total;
vec3 albedo_dirt = apply_triplanar_texture_stochastic_rgb(
dirt_albedo,
world_pos * dirt_uv_scale,
triplanar_normal_abs,
blend_factor,
dirt_stochastic_strength,
dirt_stochastic_rotation_max_angle
);
vec3 albedo_grass = apply_triplanar_texture_stochastic_rgb(
grass_albedo,
world_pos * grass_uv_scale,
triplanar_normal_abs,
blend_factor,
grass_stochastic_strength,
grass_stochastic_rotation_max_angle
);
vec3 albedo_mountain = apply_triplanar_texture_stochastic_rgb(
mountain_albedo,
world_pos * mountain_uv_scale,
triplanar_normal_abs,
blend_factor,
mountain_stochastic_strength,
mountain_stochastic_rotation_max_angle
);
//vec3 orm_dirt = texture(dirt_orm, UV * dirt_uv_scale).rgb;
//vec3 orm_grass = texture(grass_orm, UV * grass_uv_scale).rgb;
//vec3 orm_mountain = texture(mountain_orm, UV * mountain_uv_scale).rgb;
//
//vec3 mixed_orm = mix(orm_dirt, orm_grass, blend_factor);
//mixed_orm = mix(mixed_orm, orm_mountain, blend_factor);
//
ALBEDO = albedo_dirt * blend_dirt + albedo_grass * blend_grass + albedo_mountain * blend_mountain;
//AO = mixed_orm.r;
//AO_LIGHT_AFFECT = ao_light_affect;
//ROUGHNESS = mixed_orm.g * roughness;
//METALLIC = mixed_orm.b;
}

View File

@@ -0,0 +1 @@
uid://b4hwimgi2bi6n

View File

@@ -0,0 +1,96 @@
shader_type spatial;
render_mode depth_draw_always, cull_disabled;
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, repeat_disable, filter_nearest;
group_uniforms Surface_Details;
uniform float uv_scale: hint_range(0.0, 100.0, 0.1) = 1.0;
uniform bool uv_triplanar = false;
uniform float roughness : hint_range(0.0, 1.0) = 0.2;
uniform float metallic: hint_range(0.0, 1.0) = 0.6;
uniform float specular : hint_range(0.0, 1.0, 0.01);
group_uniforms Water_Colors;
uniform vec3 shallow_color : source_color = vec3(0.22, 0.66, 1.0);
uniform vec3 deep_color : source_color = vec3(0.0, 0.25, 0.45);
uniform float depth_fade_distance : hint_range(0.0, 10.0) = 1.0;
uniform float absorbance : hint_range(0.0, 10.0) = 2.0;
group_uniforms Normals;
uniform sampler2D water_normal_noise: hint_default_white;
uniform float normal_strength: hint_range(0.0, 1.0, 0.01) = 0.5;
group_uniforms Foam;
uniform float foam_amount : hint_range(0.0, 2.0) = 0.2;
uniform vec3 foam_color : source_color = vec3(1);
group_uniforms Waves;
uniform float wave_time_scale: hint_range(0.0, 10.0, 0.1) = 1.0;
varying vec3 uv_world_pos;
vec3 screen(vec3 base, vec3 blend){
return 1.0 - (1.0 - base) * (1.0 - blend);
}
void vertex() {
uv_world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
void fragment() {
vec2 base_uv = UV;
vec2 screen_uv = SCREEN_UV;
if (uv_triplanar) {
base_uv = uv_world_pos.xz;
}
base_uv.x += sin(TIME * wave_time_scale + (base_uv.x + base_uv.y) * 25.0) * 0.01;
base_uv.y += cos(TIME * wave_time_scale + (base_uv.x - base_uv.y) * 25.0) * 0.01;
screen_uv.x += sin(TIME * wave_time_scale + (screen_uv.x + screen_uv.y) * 25.0) * 0.01;
screen_uv.y += cos(TIME * wave_time_scale + (screen_uv.x - screen_uv.y) * 25.0) * 0.01;
/// DEPTH TEXTURE MANIPULATION ///
float depth = texture(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;
vec3 ndc = vec3(screen_uv * 2.0 - 1.0, depth);
vec4 world = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
float depth_texture_y = world.y / world.w;
float vertex_y = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).y;
float vertical_depth = vertex_y - depth_texture_y;
// CHANGES THE COLOR OF GEOMETRY BEHIND IT AS THE WATER GETS DEEPER
float depth_fade_blend = exp(-vertical_depth / depth_fade_distance);
depth_fade_blend = clamp(depth_fade_blend, 0.0, 1.0);
/// END DEPTH TEXTURE MANIPULATION ///
// WHEN THE WATER GETS MORE SHALLOW, MORE TRANSPARENT
float alpha_blend = -vertical_depth * absorbance;
alpha_blend = clamp(1.0 - exp(alpha_blend), 0.0, 1.0);
float foam_blend = clamp(1.0 - (vertical_depth / foam_amount), 0.0, 1.0);
vec3 foam = foam_blend * foam_color;
vec3 final_albedo = mix(deep_color, shallow_color, depth_fade_blend);
final_albedo = screen(final_albedo, foam);
ALBEDO = final_albedo;
NORMAL_MAP = texture(water_normal_noise, base_uv * uv_scale).rgb;
NORMAL *= normal_strength;
METALLIC = metallic;
ROUGHNESS = roughness;
SPECULAR = specular;
if (FRONT_FACING) {
ALPHA = alpha_blend;
} else {
ALPHA = 1.0;
}
}
//void light() {
// // Called for every pixel for every light affecting the material.
// // Uncomment to replace the default light processing function with this one.
//}

View File

@@ -0,0 +1 @@
uid://cjbhb3sukklvt

View File

@@ -0,0 +1,432 @@
// Modified version from https://github.com/LesusX/YouTube/blob/main/WaterShader/water.gdshader
// The following shader is used in order to simulate a simple ocean using Gerstner waves.
// This shader can be added in a plane mesh. For a more detailed ocean, increase the width and depth subdivison.
// Note: On larger planes ex. 500x500, increasing the subdivision above 1000 comes at great performance cost
shader_type spatial;
// Set render modes: always draw depth and disable backface culling
render_mode depth_draw_always, cull_disabled;
// Uniforms for screen and depth textures
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;
// Group uniforms for wave parameters
group_uniforms Waves;
// Each wave is defined by a vec4: direction (x,y), amplitude, frequency
uniform vec4 wave_1 = vec4(0.3, 4.0, 0.2, 0.6);
uniform vec4 wave_2 = vec4(-0.26, -0.19, 0.01, 0.47);
uniform vec4 wave_3 = vec4(-7.67, 5.63, 0.1, 0.38);
uniform vec4 wave_4 = vec4(-0.42, -1.63, 0.1, 0.28);
uniform vec4 wave_5 = vec4(1.66, 0.07, 0.15, 1.81);
uniform vec4 wave_6 = vec4(1.20, 1.14, 0.01, 0.33);
uniform vec4 wave_7 = vec4(-1.6, 7.3, 0.11, 0.73);
uniform vec4 wave_8 = vec4(-0.42, -1.63, 0.15, 1.52);
// Uniforms for time factor, noise zoom, and noise amplitude
uniform float time_factor = 2.5;
uniform float noise_zoom = 2.0;
uniform float noise_amp = 1.0;
// Group uniforms for water colors
group_uniforms Water_colours;
uniform vec3 base_water_color:source_color;
uniform vec3 fresnel_water_color:source_color;
uniform vec4 deep_water_color : source_color;
uniform vec4 shallow_water_color : source_color;
// Group uniforms for depth-related parameters
group_uniforms Depth;
uniform float beers_law = 0.5;
uniform float depth_offset = -1.2;
uniform float near = 7.0;
uniform float far = 10000.0;
// Group uniforms for edge detection and foam effects
group_uniforms Edge_Detection;
uniform float edge_texture_scale = 3.5;
uniform float edge_texture_offset = 1.0;
uniform float edge_texture_speed = 0.1;
uniform float edge_foam_intensity = 2.0;
uniform float edge_fade_start = -3.0;
uniform float edge_fade_end = 6.6;
uniform sampler2D edge_foam_texture;
// Group uniforms for wave peak effects
group_uniforms WavePeakEffect;
uniform float peak_height_threshold = 1.0;
uniform vec3 peak_color = vec3(1.0, 1.0, 1.0);
uniform float peak_intensity = 1.0;
uniform sampler2D foam_texture;
uniform float foam_intensity = 1.0;
uniform float foam_scale = 1.0;
// Group uniforms for surface details
group_uniforms Surface_details;
uniform float metallic = 0.6;
uniform float roughness = 0.045;
uniform float uv_scale_text_a = 0.1;
uniform vec2 uv_speed_text_a = vec2(0.42, 0.3);
uniform float uv_scale_text_b = 0.6;
uniform vec2 uv_speed_text_b = vec2(0.15, 0.1);
uniform float normal_strength = 1.0;
uniform float uv_sampler_scale = 0.3;
uniform float blend_factor = 0.28;
uniform sampler2D normalmap_a;
uniform sampler2D normalmap_b;
uniform sampler2D uv_sampler;
uniform sampler2DArray caustic_sampler : hint_default_black;
uniform float caustic_distortion_strength: hint_range(0.0, 0.009) = 0.001; // New uniform for tweaking
uniform float num_caustic_layers = 16.0; // <<< IMPORTANT: DOUBLE CHECK THIS against your Texture2DArray's actual slices!
uniform float refraction_strength = 0.05; // How much the background is distorted
uniform float refraction_fresnel_power = 2.0;
uniform vec3 underwater_fog_color : source_color; // New uniform for fog color
uniform float underwater_fog_density = 0.1; // New uniform for fog density
uniform float underwater_fog_start = 0.0; // New uniform: distance from camera where fog starts (can be negative to make it start immediately)
// Fresnel function to calculate the reflection/refraction effect
float fresnel(float amount, vec3 normal, vec3 view) {
return pow((1.0 - clamp(dot(normalize(normal), normalize(view)), 0.0, 1.0)), amount);
}
// Function to calculate edge depth
float edge(float depth) {
depth = 2.0 * depth - 1.0;
return near * far / (far - depth * (near - far));
}
// Function to calculate dynamic amplitude based on position and time
float dynamic_amplitude(vec2 pos, float time) {
return 1.0 + 0.5 * sin(time + length(pos) * 0.1);
}
// Hash function for noise generation
float hash(vec2 p) {
return fract(sin(dot(p * 17.17, vec2(14.91, 67.31))) * 4791.9511);
}
// 2D noise function
float noise(vec2 x) {
vec2 p = floor(x);
vec2 f = fract(x);
f = f * f * (3.0 - 2.0 * f);
vec2 a = vec2(1.0, 0.0);
return mix(mix(hash(p + a.yy), hash(p + a.xy), f.x),
mix(hash(p + a.yx), hash(p + a.xx), f.x), f.y);
}
// Fractional Brownian Motion (fBM) function for generating complex noise
float fbm(vec2 x) {
float height = 0.0;
float amplitude = 0.5;
float frequency = 3.0;
for (int i = 0; i < 6; i++) {
height += noise(x * frequency) * amplitude;
amplitude *= 0.5;
frequency *= 2.0;
}
return height;
}
// Structure to hold wave results: displacement, tangent, binormal, and normal
struct WaveResult {
vec3 displacement;
vec3 tangent;
vec3 binormal;
vec3 normal;
};
// Gerstner wave function to calculate wave displacement and normals
WaveResult gerstner_wave(vec4 params, vec2 pos, float time) {
float steepness = params.z * dynamic_amplitude(pos, time);
float wavelength = params.w;
float k = 2.0 * PI / wavelength;
float c = sqrt(9.81 / k);
vec2 d = normalize(params.xy);
float f = k * (dot(d, pos.xy) - c * time);
float a = steepness / k;
vec3 displacement = vec3(d.x * (a * cos(f)), a * sin(f), d.y * (a * cos(f)));
vec3 tangent = vec3(1.0 - d.x * d.x * steepness * sin(f), steepness * cos(f), -d.x * d.y * steepness * sin(f));
vec3 binormal = vec3(-d.x * d.y * steepness * sin(f), steepness * cos(f), 1.0 - d.y * d.y * steepness * sin(f));
vec3 normal = normalize(cross(tangent, binormal));
return WaveResult(displacement, tangent, binormal, normal);
}
// Function to combine multiple Gerstner waves
WaveResult wave(vec2 pos, float time) {
WaveResult waveResult;
waveResult.displacement = vec3(0.0);
waveResult.tangent = vec3(1.0, 0.0, 0.0);
waveResult.binormal = vec3(0.0, 0.0, 1.0);
waveResult.normal = vec3(0.0, 1.0, 0.0);
WaveResult wr;
wr = gerstner_wave(wave_1, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_2, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_3, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_4, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_5, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_6, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_7, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
wr = gerstner_wave(wave_8, pos, time);
waveResult.displacement += wr.displacement;
waveResult.tangent += wr.tangent;
waveResult.binormal += wr.binormal;
waveResult.normal += wr.normal;
// Add noise to the wave displacement for more natural look
waveResult.displacement.y += fbm(pos.xy * (noise_zoom / 50.0)) * noise_amp;
return waveResult;
}
// Varying variables to pass data from vertex to fragment shader
varying float height;
varying vec3 world_position;
varying mat3 tbn_matrix;
varying mat4 inv_mvp;
// Vertex shader function
void vertex() {
// Calculate time based on the global TIME variable and time_factor
float time = TIME / time_factor;
// Calculate wave displacement and normals
WaveResult waveResult = wave(VERTEX.xz, time);
// Apply wave displacement to the vertex position
VERTEX += waveResult.displacement;
// Store the height of the wave displacement
height = waveResult.displacement.y;
// Transform normals, tangents, and binormals to world space
vec3 n = normalize((MODELVIEW_MATRIX * vec4(waveResult.normal, 0.0)).xyz);
vec3 t = normalize((MODELVIEW_MATRIX * vec4(waveResult.tangent.xyz, 0.0)).xyz);
vec3 b = normalize((MODELVIEW_MATRIX * vec4((cross(waveResult.normal, waveResult.tangent.xyz)), 0.0)).xyz);
// Calculate world position of the vertex
world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
// Create TBN matrix for normal mapping
tbn_matrix = mat3(t, b, n);
// Calculate inverse MVP matrix for screen space transformations
inv_mvp = inverse(PROJECTION_MATRIX * MODELVIEW_MATRIX);
}
// Fragment shader function
void fragment() {
// Calculate UV coordinates based on world position
vec2 uv = world_position.xz;
// Sample UV offset texture
vec2 uv_offset = texture(uv_sampler, uv * uv_sampler_scale).rg;
// Calculate animated UV coordinates for normal maps
vec2 animated_uv_a = (uv + uv_speed_text_a * TIME + uv_offset) * uv_scale_text_a;
vec2 animated_uv_b = (uv + uv_speed_text_b * TIME + uv_offset) * uv_scale_text_b;
// Sample normal maps
vec3 normal_sample_a = texture(normalmap_a, animated_uv_a).rgb;
vec3 normal_sample_b = texture(normalmap_b, animated_uv_b).rgb;
// Normalize normal samples and combine them
normal_sample_a = normalize(normal_sample_a * 2.0 - 1.0);
normal_sample_b = normalize(normal_sample_b * 2.0 - 1.0);
vec3 combined_normal = normalize(mix(normal_sample_a, normal_sample_b, blend_factor));
// Perturb the normal using the TBN matrix
vec3 perturbed_normal = normalize(tbn_matrix * (combined_normal * normal_strength));
// Sample depth texture
float depth_raw = texture(DEPTH_TEXTURE, SCREEN_UV).r;
float depth = PROJECTION_MATRIX[3][2] / (depth_raw + PROJECTION_MATRIX[2][2]);
// Calculate the distance from the camera to the water surface
float camera_depth = INV_VIEW_MATRIX[3].y - world_position.y;
if (camera_depth < 0.0) { // Camera is underwater
// Map the depth to a range where deeper = positive beers_law, closer = negative beers_law
float depth_factor = smoothstep(-10.0, 0.0, camera_depth); // Adjust -10.0 for the depth range
ALPHA -= depth_factor * 0.3;
}
// Calculate depth blend factor using Beer's law
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);
// --- Refraction Distortion Implementation ---
vec2 refraction_uv_offset = perturbed_normal.xy * refraction_strength; // Use XY of normal for 2D screen UV distortion
// Add some noise to the offset for more organic look (optional, can be subtle)
refraction_uv_offset += texture(uv_sampler, SCREEN_UV * 0.1 + TIME * 0.05).rg * 0.01;
// The final UV for sampling the screen texture
vec2 refracted_screen_uv = SCREEN_UV + refraction_uv_offset;
// Blend between refracted and original screen UV based on fresnel (less refraction at grazing angles)
// This makes reflections stronger than refraction at high angles, which is physically correct.
float refraction_fresnel = fresnel(refraction_fresnel_power, NORMAL, VIEW); // Use original NORMAL for camera view
refracted_screen_uv = mix(SCREEN_UV, refracted_screen_uv, 1.0 - refraction_fresnel);
// Sample screen color using the new refracted UVand blend it with depth color
vec3 screen_color = textureLod(SCREEN_TEXTURE, refracted_screen_uv, depth_blend_power * 2.5).rgb;
vec3 depth_color = mix(shallow_water_color.rgb, deep_water_color.rgb, depth_blend_power);
vec3 color = mix(screen_color * depth_color, depth_color * 0.25, depth_blend_power * 0.5);
// Calculate depth difference for edge detection
float z_depth = edge(texture(DEPTH_TEXTURE, SCREEN_UV).x);
float z_pos = edge(FRAGCOORD.z);
float z_dif = z_depth - z_pos;
// Calculate caustic effect
vec4 caustic_screenPos = vec4(SCREEN_UV * 2.0 - 1.0, depth_raw, 1.0);
vec4 caustic_localPos = inv_mvp * caustic_screenPos;
caustic_localPos = vec4(caustic_localPos.xyz / caustic_localPos.w, caustic_localPos.w);
vec2 caustic_Uv = caustic_localPos.xz / vec2(1024.0) + 0.5;
caustic_Uv += perturbed_normal.xz * caustic_distortion_strength;
float caustic_layer_index = floor(mod(TIME * 26.0, num_caustic_layers)); // Use floor for integer index
vec4 caustic_color = texture(caustic_sampler, vec3(caustic_Uv * 660.0, caustic_layer_index));
float caustic_intensity_multiplier = (1.0 - depth_blend_power) * 6.0;
color *= 1.0 + pow(caustic_color.r, 1.50) * caustic_intensity_multiplier;
// Calculate fresnel effect
float fresnel = fresnel(5.0, NORMAL, VIEW);
vec3 surface_color = mix(base_water_color, fresnel_water_color, fresnel);
// Calculate edge foam effect
vec2 edge_uv = world_position.xz * edge_texture_scale + edge_texture_offset + TIME * edge_texture_speed;
float edge_fade = smoothstep(edge_fade_start, edge_fade_end, z_dif);
vec3 depth_color_adj = mix(texture(edge_foam_texture, edge_uv).rgb * edge_foam_intensity, color, edge_fade);
// Apply peak color effect based on height with noise
// --- Peak Foam Effect ---
// Foam should appear on higher peaks
// The height uniform comes from the vertex shader's displacement.y
float foam_threshold_start = peak_height_threshold;
float foam_threshold_end = peak_height_threshold + 0.2; // Adjust for fade range
// Smoothstep creates a gradient for foam appearance based on height
float height_foam_alpha = smoothstep(foam_threshold_start, foam_threshold_end, height);
// Add noise to make foam patchy and less uniform
// Use a faster moving noise for foam animation
float foam_noise = fbm(world_position.xz * 0.5 + TIME * 0.5); // Faster moving noise
height_foam_alpha *= foam_noise * 2.0; // Intensify and make patchier
// Clamp to ensure alpha is between 0 and 1
height_foam_alpha = clamp(height_foam_alpha, 0.0, 1.0);
// Sample foam texture for detail. Add some distortion based on normals for more realism.
// Perturb the foam UV slightly by the normal map for more organic look
vec2 foam_uv_distorted = world_position.xz * foam_scale + TIME * 0.1;
foam_uv_distorted += perturbed_normal.xz * 0.05; // Small distortion
float foam_texture_sample = texture(foam_texture, foam_uv_distorted).r;
// Combine height-based alpha with texture sample and overall intensity
float final_foam_alpha = height_foam_alpha * foam_texture_sample * foam_intensity;
// Apply peak color as a blend
vec3 final_color = mix(surface_color, peak_color * peak_intensity, final_foam_alpha);
// Optionally, make the foam whiter instead of just tinted
final_color = mix(final_color, vec3(1.0), final_foam_alpha);
// --- Underwater Fog/Color Implementation ---
// Check if the camera is underwater
float camera_water_height = INV_VIEW_MATRIX[3].y; // Camera's Y position in world space
float water_surface_height = world_position.y; // Water's Y position at this fragment (displaced)
vec3 final_albedo_color; // Declare a variable to hold the final ALBEDO before assignment
// --- MODIFIED ALPHA & UNDERWATER FOG BLEND ---
if (camera_water_height < water_surface_height) { // Camera is underwater
// Calculate the distance the camera is *below* the water surface
float dist_below_surface = water_surface_height - camera_water_height;
// Define a shallow zone where transparency and fog blend in
float shallow_zone_start = 0.0; // Camera is exactly at surface (or just below)
float shallow_zone_end = 0.5; // Camera is 0.5 units below surface (adjust this value!)
// Calculate an alpha multiplier for the water surface itself based on depth
// Smoothly transition water's alpha from 1.0 (fully opaque) to a lower value (more transparent)
// as the camera goes deeper into the shallow zone.
float surface_alpha_blend = smoothstep(shallow_zone_start, shallow_zone_end, dist_below_surface);
// Apply a base transparency if desired, or fade it out completely
// ALPHA = mix(1.0, 0.7, surface_alpha_blend); // Water stays somewhat opaque, becomes more transparent deeper
ALPHA = mix(1.0, 0.2, surface_alpha_blend); // Water becomes quite transparent when fully submerged in shallow zone
// If you want it to gradually become more transparent based on actual depth, like your old line:
// float underwater_alpha_factor = smoothstep(water_surface_height - 10.0, water_surface_height, camera_water_height);
// ALPHA = mix(ALPHA, 1.0 - (underwater_alpha_factor * 0.3), underwater_alpha_factor); // Combine with previous alpha
// Let's stick with the simple shallow zone fade for now to fix the "holes"
// --- Fog Amount Blending ---
// The previous fog_amount is correct for fading distant objects.
// We now use 'surface_alpha_blend' to mix how much of that fog is applied to what we see.
// When dist_below_surface is small (camera near surface), surface_alpha_blend is low,
// so we see LESS of the fog and more of the clear background.
// As camera goes deeper, surface_alpha_blend increases, so we see MORE fog.
float scene_depth_raw = texture(DEPTH_TEXTURE, SCREEN_UV).r;
vec4 world_pos_from_depth_clip = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, scene_depth_raw, 1.0);
vec3 world_pos_from_depth = world_pos_from_depth_clip.xyz / world_pos_from_depth_clip.w;
float dist_to_scene_object = length(world_pos_from_depth - INV_VIEW_MATRIX[3].xyz);
float fog_amount = 1.0 - exp(-(dist_to_scene_object - underwater_fog_start) * underwater_fog_density);
fog_amount = clamp(fog_amount, 0.0, 1.0);
// Adjust the fog blend based on how far below the surface the camera is
// When camera is very close to surface, fog_amount is reduced (more clear)
// As camera goes deeper, fog_amount is fully applied.
float final_fog_blend_factor = mix(0.0, fog_amount, surface_alpha_blend); // Adjust 0.0 to a small value if you want slight fog even right at surface
final_albedo_color = mix(color, underwater_fog_color, final_fog_blend_factor);
// This mix for the water surface still holds:
final_albedo_color = mix(final_albedo_color, final_color, 0.2);
} else { // Camera is above water (standard rendering)
final_albedo_color = final_color + depth_color_adj;
}
// --- END MODIFIED ALPHA & UNDERWATER FOG BLEND ---
// Set the final color, metallic, roughness, and normal
ALBEDO = clamp(final_albedo_color, vec3(0.0), vec3(1.0)); // Assign the final albedo color
METALLIC = metallic;
ROUGHNESS = roughness;
NORMAL = perturbed_normal;
}

View File

@@ -0,0 +1 @@
uid://bxwe0bkai5bn

View File

@@ -0,0 +1,74 @@
[gd_resource type="ShaderMaterial" load_steps=8 format=3 uid="uid://dolvv80m4a8ym"]
[ext_resource type="Shader" uid="uid://bxwe0bkai5bn" path="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/ocean.gdshader" id="1_dic1h"]
[ext_resource type="CompressedTexture2DArray" uid="uid://dcvujep4v7k1b" path="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/caustic.png" id="2_103fq"]
[ext_resource type="Texture2D" uid="uid://5dhudphm5c8o" path="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/foam_albedo.png" id="3_upbnb"]
[ext_resource type="Texture2D" uid="uid://bfa4xeh5thwio" path="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/normal_A.png" id="4_vwqlf"]
[ext_resource type="Texture2D" uid="uid://dpwv0qf6tb7we" path="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/normal_B.png" id="5_6jyj5"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ud4jo"]
noise_type = 3
domain_warp_enabled = true
domain_warp_fractal_type = 0
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_hugwt"]
seamless = true
seamless_blend_skirt = 0.6
as_normal_map = true
noise = SubResource("FastNoiseLite_ud4jo")
[resource]
render_priority = 0
shader = ExtResource("1_dic1h")
shader_parameter/wave_1 = Vector4(0.3, 4, 0.2, 0.6)
shader_parameter/wave_2 = Vector4(-0.26, 0.265, 0.01, 0.47)
shader_parameter/wave_3 = Vector4(-6.65, 5.63, 0.1, 0.38)
shader_parameter/wave_4 = Vector4(-0.42, -1.63, 0.1, 0.28)
shader_parameter/wave_5 = Vector4(1.66, 0.615, 0.15, 1.81)
shader_parameter/wave_6 = Vector4(1.2, 1.14, 0.01, 0.33)
shader_parameter/wave_7 = Vector4(-1.6, 7.3, 0.11, 0.73)
shader_parameter/wave_8 = Vector4(-0.42, -1.63, 0.15, 1.52)
shader_parameter/time_factor = 2.5
shader_parameter/noise_zoom = 2.0
shader_parameter/noise_amp = 1.0
shader_parameter/base_water_color = Color(0.25098, 0.0941176, 0.635294, 1)
shader_parameter/fresnel_water_color = Color(0.160784, 0.631373, 0.717647, 1)
shader_parameter/deep_water_color = Color(0.0470588, 0.0392157, 0.266667, 1)
shader_parameter/shallow_water_color = Color(0.134335, 0.413904, 0.539619, 1)
shader_parameter/beers_law = 0.5
shader_parameter/depth_offset = -1.2
shader_parameter/near = 7.0
shader_parameter/far = 10000.0
shader_parameter/edge_texture_scale = 3.5
shader_parameter/edge_texture_offset = 1.0
shader_parameter/edge_texture_speed = 0.1
shader_parameter/edge_foam_intensity = 2.0
shader_parameter/edge_fade_start = -3.0
shader_parameter/edge_fade_end = 6.6
shader_parameter/edge_foam_texture = ExtResource("3_upbnb")
shader_parameter/peak_height_threshold = 1.0
shader_parameter/peak_color = Vector3(1, 1, 1)
shader_parameter/peak_intensity = 1.0
shader_parameter/foam_texture = ExtResource("3_upbnb")
shader_parameter/foam_intensity = 1.0
shader_parameter/foam_scale = 1.0
shader_parameter/metallic = 0.6
shader_parameter/roughness = 0.045
shader_parameter/uv_scale_text_a = 0.1
shader_parameter/uv_speed_text_a = Vector2(0.42, 0.3)
shader_parameter/uv_scale_text_b = 0.6
shader_parameter/uv_speed_text_b = Vector2(0.15, 0.1)
shader_parameter/normal_strength = 1.0
shader_parameter/uv_sampler_scale = 0.3
shader_parameter/blend_factor = 0.28
shader_parameter/normalmap_a = ExtResource("4_vwqlf")
shader_parameter/normalmap_b = ExtResource("5_6jyj5")
shader_parameter/uv_sampler = SubResource("NoiseTexture2D_hugwt")
shader_parameter/caustic_sampler = ExtResource("2_103fq")
shader_parameter/caustic_distortion_strength = 0.001
shader_parameter/num_caustic_layers = 16.0
shader_parameter/refraction_strength = 0.05
shader_parameter/refraction_fresnel_power = 2.0
shader_parameter/underwater_fog_color = Color(0.184314, 0.929412, 0.164706, 1)
shader_parameter/underwater_fog_density = 0.1
shader_parameter/underwater_fog_start = 0.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 KiB

View File

@@ -0,0 +1,30 @@
[remap]
importer="2d_array_texture"
type="CompressedTexture2DArray"
uid="uid://dcvujep4v7k1b"
path.s3tc="res://.godot/imported/caustic.png-20d1447e252529e719bd2f6f50ad94f7.s3tc.ctexarray"
path.etc2="res://.godot/imported/caustic.png-20d1447e252529e719bd2f6f50ad94f7.etc2.ctexarray"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/caustic.png"
dest_files=["res://.godot/imported/caustic.png-20d1447e252529e719bd2f6f50ad94f7.s3tc.ctexarray", "res://.godot/imported/caustic.png-20d1447e252529e719bd2f6f50ad94f7.etc2.ctexarray"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
slices/horizontal=4
slices/vertical=4

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,42 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://5dhudphm5c8o"
path.s3tc="res://.godot/imported/foam_albedo.png-c07e7d548cc5fd08fcec046c95794295.s3tc.ctex"
path.etc2="res://.godot/imported/foam_albedo.png-c07e7d548cc5fd08fcec046c95794295.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/foam_albedo.png"
dest_files=["res://.godot/imported/foam_albedo.png-c07e7d548cc5fd08fcec046c95794295.s3tc.ctex", "res://.godot/imported/foam_albedo.png-c07e7d548cc5fd08fcec046c95794295.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

View File

@@ -0,0 +1,42 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bfa4xeh5thwio"
path.s3tc="res://.godot/imported/normal_A.png-9f9f97a1168bfef20e1747f569913069.s3tc.ctex"
path.etc2="res://.godot/imported/normal_A.png-9f9f97a1168bfef20e1747f569913069.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/normal_A.png"
dest_files=["res://.godot/imported/normal_A.png-9f9f97a1168bfef20e1747f569913069.s3tc.ctex", "res://.godot/imported/normal_A.png-9f9f97a1168bfef20e1747f569913069.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

@@ -0,0 +1,42 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dpwv0qf6tb7we"
path.s3tc="res://.godot/imported/normal_B.png-befe3a6f8f5ad256b138cffb2ec1eef9.s3tc.ctex"
path.etc2="res://.godot/imported/normal_B.png-befe3a6f8f5ad256b138cffb2ec1eef9.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/normal_B.png"
dest_files=["res://.godot/imported/normal_B.png-befe3a6f8f5ad256b138cffb2ec1eef9.s3tc.ctex", "res://.godot/imported/normal_B.png-befe3a6f8f5ad256b138cffb2ec1eef9.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=false
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 KiB

View File

@@ -0,0 +1,42 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ch1eb1v8e4utn"
path.s3tc="res://.godot/imported/uv_example.png-b9c1281353524aa0eff2401e42e8614c.s3tc.ctex"
path.etc2="res://.godot/imported/uv_example.png-b9c1281353524aa0eff2401e42e8614c.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
[deps]
source_file="res://addons/ninetailsrabbit.terrainy/shaders/water/ocean/textures/uv_example.png"
dest_files=["res://.godot/imported/uv_example.png-b9c1281353524aa0eff2401e42e8614c.s3tc.ctex", "res://.godot/imported/uv_example.png-b9c1281353524aa0eff2401e42e8614c.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0