credit
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// painterly_water.gdshader — Godot 4.x
|
||||
// Flat, gouache-style water for a straight river + cascade.
|
||||
//
|
||||
// RIVER preset: uv_scale = vec2(2.0, 6.0), flow_speed = 0.10, wobble = 0.05
|
||||
// FALL preset: uv_scale = vec2(3.0, 1.0), flow_speed = 0.55, wobble = 0.02,
|
||||
// edge_foam_top = 0.25, edge_foam_bottom = 0.35, foam_amount = 0.75
|
||||
// POOL preset: uv_scale = vec2(3.0, 3.0), flow_speed = 0.03, wobble = 0.08
|
||||
|
||||
shader_type spatial;
|
||||
render_mode blend_mix, cull_disabled, diffuse_lambert, specular_disabled, shadows_disabled;
|
||||
|
||||
// --- palette: keep it to 3 tones + foam, like mixing real paint ---
|
||||
uniform vec3 color_deep : source_color = vec3(0.07, 0.26, 0.40);
|
||||
uniform vec3 color_mid : source_color = vec3(0.16, 0.50, 0.58);
|
||||
uniform vec3 color_light : source_color = vec3(0.48, 0.79, 0.78);
|
||||
uniform vec3 color_foam : source_color = vec3(0.95, 0.97, 0.94);
|
||||
|
||||
uniform sampler2D noise_a : repeat_enable, filter_linear;
|
||||
uniform sampler2D noise_b : repeat_enable, filter_linear;
|
||||
uniform sampler2D canvas : repeat_enable, filter_linear;
|
||||
|
||||
uniform vec2 uv_scale = vec2(2.0, 6.0);
|
||||
uniform vec2 flow_dir = vec2(0.0, 1.0); // +Y = "downstream" along the plane's V axis
|
||||
uniform float flow_speed = 0.10;
|
||||
|
||||
uniform float wobble : hint_range(0.0, 0.25) = 0.05; // brush wander
|
||||
uniform float bands : hint_range(2.0, 8.0) = 4.0; // fewer = more poster-like
|
||||
uniform float foam_amount: hint_range(0.0, 1.0) = 0.55;
|
||||
|
||||
// foam strips along the top / bottom edge of the mesh (for the lip and the splash base)
|
||||
uniform float edge_foam_top : hint_range(0.0, 0.6) = 0.0;
|
||||
uniform float edge_foam_bottom : hint_range(0.0, 0.6) = 0.0;
|
||||
|
||||
uniform float canvas_scale = 4.0;
|
||||
uniform float canvas_strength : hint_range(0.0, 1.0) = 0.25;
|
||||
|
||||
void fragment() {
|
||||
vec2 uv = UV * uv_scale;
|
||||
vec2 flow = flow_dir * TIME * flow_speed;
|
||||
|
||||
// slow low-frequency warp — this is what sells the "hand-painted" wobble
|
||||
vec2 warp = (texture(noise_b, uv * 0.3 - flow * 0.25).rg - 0.5) * wobble * 2.0;
|
||||
|
||||
// two layers at different speeds so the motion never looks like a sliding texture
|
||||
float n1 = texture(noise_a, uv + warp - flow).r;
|
||||
float n2 = texture(noise_a, uv * 1.9 + warp.yx - flow * 1.7 + vec2(0.37)).r;
|
||||
float v = n1 * 0.65 + n2 * 0.35;
|
||||
|
||||
// posterize into flat steps — the single most important line here
|
||||
float q = floor(v * bands) / max(bands - 1.0, 1.0);
|
||||
|
||||
// edge foam strips
|
||||
float top = 1.0 - smoothstep(0.0, max(edge_foam_top, 0.001), UV.y);
|
||||
float bottom = smoothstep(1.0 - max(edge_foam_bottom, 0.001), 1.0, UV.y);
|
||||
float edge = clamp(top + bottom, 0.0, 1.0) * step(0.35, v); // let noise break it up
|
||||
|
||||
vec3 col = mix(color_deep, color_mid, smoothstep(0.00, 0.50, q));
|
||||
col = mix(col, color_light, smoothstep(0.50, 0.85, q));
|
||||
col = mix(col, color_foam, step(1.0 - foam_amount * 0.4, q));
|
||||
col = mix(col, color_foam, edge);
|
||||
|
||||
// canvas grain in screen space so the paper stays put while the water moves
|
||||
float grain = texture(canvas, SCREEN_UV * canvas_scale).r;
|
||||
col = mix(col, col * (0.75 + grain * 0.5), canvas_strength);
|
||||
|
||||
ALBEDO = col;
|
||||
ROUGHNESS = 1.0;
|
||||
SPECULAR = 0.0;
|
||||
METALLIC = 0.0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://crudfhhxokfvp
|
||||
@@ -0,0 +1,11 @@
|
||||
shader_type spatial;
|
||||
|
||||
uniform sampler2DArray skins : source_color, filter_linear_mipmap, repeat_enable;
|
||||
instance uniform int skin_index = 0;
|
||||
|
||||
void fragment() {
|
||||
vec4 tex_color = texture(skins, vec3(UV, float(skin_index)));
|
||||
ALBEDO = tex_color.rgb;
|
||||
// optional if alpha
|
||||
// ALPHA = tex_color.a;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://cnuead630a8a6
|
||||
@@ -1,185 +0,0 @@
|
||||
shader_type spatial;
|
||||
render_mode depth_draw_always, cull_disabled;
|
||||
|
||||
group_uniforms water;
|
||||
uniform vec3 water_color : source_color;
|
||||
uniform sampler2D water_noise_1;
|
||||
uniform sampler2D water_noise_2;
|
||||
|
||||
group_uniforms vertex_waves;
|
||||
uniform bool use_vertex_waves = false;
|
||||
uniform float wave_height : hint_range(0.0, 2.0, 0.1) = 0.2;
|
||||
uniform float wave_speed : hint_range(0.0, 1.0, 0.01) = 0.05;
|
||||
uniform float wave_scale : hint_range(1.0, 50.0, 1.0) = 10.0;
|
||||
|
||||
group_uniforms rendering;
|
||||
uniform bool double_sided = true;
|
||||
uniform vec4 surface_bottom : source_color = vec4(0.29, 0.53, 0.67, 0.65);
|
||||
|
||||
group_uniforms depth;
|
||||
uniform sampler2D depth_texture : hint_depth_texture;
|
||||
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap, repeat_disable;
|
||||
uniform float depth_distance : hint_range(0.0, 10.0, 0.1) = 0.5;
|
||||
uniform float water_color_ratio : hint_range(0.0, 1.0, 0.1) = 0.5;
|
||||
uniform float beers_law : hint_range(0.0, 20.0, 0.1) = 3.0;
|
||||
|
||||
group_uniforms surface;
|
||||
uniform float normal_scale : hint_range(0.0, 1.0, 0.1) = 0.5;
|
||||
uniform float roughness_scale : hint_range(0.0, 1.0, 0.1) = 0.2;
|
||||
|
||||
group_uniforms river_flow;
|
||||
uniform bool use_river_flow = false;
|
||||
uniform float flow_speed : hint_range(0.0, 10.0, 0.1) = 1.0;
|
||||
uniform float flow_direction_multiplier : hint_range(-1.0, 1.0, 0.1) = 1.0;
|
||||
uniform vec2 uv1_scale = vec2(50.0, 1.0);
|
||||
uniform vec2 uv1_offset = vec2(0.0, 0.0);
|
||||
uniform bool debug_tangent = false;
|
||||
|
||||
group_uniforms foam;
|
||||
uniform bool use_foam = false;
|
||||
uniform bool debug_foam = false;
|
||||
uniform sampler2D foam_texture : repeat_enable;
|
||||
uniform float foam_uv_scale : hint_range(0.001, 1.0, 0.001) = 0.01;
|
||||
uniform float foam_scale : hint_range(1.0, 100.0, 1.0) = 25.0;
|
||||
uniform float foam_speed : hint_range(0.0, 2.0, 0.1) = 0.4;
|
||||
uniform float foam_falloff_distance : hint_range(0.0, 2.0, 0.1) = 0.4;
|
||||
uniform float foam_edge_distance : hint_range(0.0, 1.0, 0.1) = 0.2;
|
||||
uniform float foam_edge_bias : hint_range(0.0, 1.0, 0.1) = 0.1;
|
||||
uniform vec3 foam_color : source_color = vec3(0.8, 0.8, 0.8);
|
||||
|
||||
group_uniforms camera;
|
||||
uniform float camera_near = 0.05;
|
||||
uniform float camera_far = 200.0;
|
||||
|
||||
varying vec4 world_uv;
|
||||
varying vec2 flow_direction;
|
||||
varying flat vec2 TANGENT_DEBUG;
|
||||
varying vec3 world_pos;
|
||||
|
||||
float edge(float near, float far, float depth){
|
||||
depth = 1.0 - 2.0 * depth;
|
||||
return near * far / (far + depth * (near - far));
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
world_uv = MODEL_MATRIX * vec4(VERTEX, 1.0);
|
||||
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
|
||||
if (use_vertex_waves) {
|
||||
vec2 wave_uv = world_pos.xz / wave_scale;
|
||||
wave_uv.x += TIME * wave_speed;
|
||||
wave_uv.y += TIME * wave_speed * 0.5;
|
||||
wave_uv = mod(wave_uv, 1.0);
|
||||
|
||||
float noise1 = texture(water_noise_1, wave_uv).r;
|
||||
float noise2 = texture(water_noise_2, wave_uv * 0.5 + vec2(TIME * wave_speed * 0.3, 0.0)).r;
|
||||
noise2 = mod(noise2, 1.0);
|
||||
|
||||
float wave_offset = (noise1 + noise2) * 0.5 - 0.5;
|
||||
VERTEX.y += wave_offset * wave_height;
|
||||
}
|
||||
|
||||
if (use_river_flow) {
|
||||
flow_direction = vec2(1.0, 0.0);
|
||||
if (debug_tangent) {
|
||||
TANGENT_DEBUG = normalize(TANGENT.xz);
|
||||
} else {
|
||||
TANGENT_DEBUG = vec2(0.0);
|
||||
}
|
||||
} else {
|
||||
flow_direction = vec2(0.0, 1.0);
|
||||
TANGENT_DEBUG = vec2(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
if (!double_sided && !FRONT_FACING) {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec2 _uv;
|
||||
|
||||
if (debug_tangent && use_river_flow) {
|
||||
vec2 tangent_dir = TANGENT_DEBUG;
|
||||
ALBEDO = vec3(tangent_dir.x * 0.5 + 0.5, 0.0, tangent_dir.y * 0.5 + 0.5);
|
||||
ALPHA = 1.0;
|
||||
} else {
|
||||
|
||||
if (use_river_flow) {
|
||||
vec2 flow_offset = TIME * flow_speed * flow_direction * flow_direction_multiplier / uv1_scale.x;
|
||||
_uv = (UV + flow_offset) * uv1_scale + uv1_offset;
|
||||
} else {
|
||||
_uv = world_uv.xz;
|
||||
}
|
||||
|
||||
vec2 _suv = SCREEN_UV;
|
||||
|
||||
float scaled_time = use_river_flow ? TIME * flow_speed / uv1_scale.x : TIME;
|
||||
float spatial_freq = use_river_flow ? 25.0 / uv1_scale.x : 25.0;
|
||||
float distortion_x = sin(scaled_time + (_uv.x + _uv.y) * spatial_freq) * 0.01;
|
||||
float distortion_y = cos(scaled_time + (_uv.x - _uv.y) * spatial_freq) * 0.01;
|
||||
|
||||
_uv.x += distortion_x;
|
||||
_uv.y += distortion_y;
|
||||
|
||||
_suv.x += distortion_x;
|
||||
_suv.y += distortion_y;
|
||||
|
||||
float depth_r = textureLod(depth_texture, SCREEN_UV, 0.0).r;
|
||||
vec4 world = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth_r, 1.0);
|
||||
world.xyz /= world.w;
|
||||
|
||||
float depth_blend = 1.0 - smoothstep(world.z + depth_distance, world.z, VERTEX.z);
|
||||
depth_blend = exp(depth_blend * -beers_law);
|
||||
depth_blend = clamp(pow(depth_blend, 3.0), 0.0, 1.0);
|
||||
|
||||
vec3 refraction = textureLod(screen_texture, _suv, 0.0).rgb;
|
||||
NORMAL_MAP = mix(texture(water_noise_1, _uv).rgb, texture(water_noise_2, _uv).rgb, (sin(TIME * flow_speed) + 1.0) / 2.0);
|
||||
|
||||
if (FRONT_FACING) {
|
||||
ALBEDO = mix(refraction * depth_blend, water_color, water_color_ratio);
|
||||
NORMAL *= normal_scale;
|
||||
} else {
|
||||
NORMAL = -NORMAL;
|
||||
NORMAL_MAP = mix(vec3(1.0), vec3(0.0), NORMAL_MAP);
|
||||
ALBEDO = mix(refraction, surface_bottom.rgb, surface_bottom.a);
|
||||
NORMAL *= normal_scale;
|
||||
}
|
||||
|
||||
ROUGHNESS = roughness_scale;
|
||||
|
||||
if (use_foam) {
|
||||
float z_depth = edge(camera_near, camera_far, textureLod(depth_texture, SCREEN_UV, 0.0).r);
|
||||
float z_pos = edge(camera_near, camera_far, FRAGCOORD.z);
|
||||
float waterDepth = z_depth - z_pos;
|
||||
waterDepth = max(waterDepth, 0.0);
|
||||
|
||||
float edgePatternScroll = TIME * foam_speed;
|
||||
|
||||
vec2 world_uv_foam = world_pos.xz * foam_uv_scale;
|
||||
vec2 scaledUV = world_uv_foam * foam_scale;
|
||||
|
||||
float falloff = 1.0 - (waterDepth / foam_falloff_distance) + foam_edge_bias;
|
||||
float channelA = texture(foam_texture, scaledUV - vec2(edgePatternScroll, cos(scaledUV.x))).r;
|
||||
float channelB = texture(foam_texture, scaledUV * 0.5 + vec2(sin(scaledUV.y), edgePatternScroll)).b;
|
||||
|
||||
float mask = (channelA + channelB) * 0.95;
|
||||
mask = pow(mask, 2.0);
|
||||
mask = clamp(mask, 0.0, 1.0);
|
||||
|
||||
if(waterDepth < foam_falloff_distance * foam_edge_distance) {
|
||||
float leading = waterDepth / (foam_falloff_distance * foam_edge_distance);
|
||||
ALPHA *= leading;
|
||||
mask *= leading;
|
||||
}
|
||||
|
||||
vec3 edge = foam_color * falloff;
|
||||
|
||||
if (debug_foam) {
|
||||
ALBEDO = vec3(falloff, mask, 0.0);
|
||||
} else {
|
||||
ALBEDO += clamp(edge - vec3(mask), 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
uid://cfqksp7q7rneg
|
||||
Reference in New Issue
Block a user