This commit is contained in:
Gerard Gascón 2025-04-24 17:23:34 +02:00
commit b99855351d
434 changed files with 50357 additions and 0 deletions

BIN
scripts/shaders/Perlin_noise_example.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cfux36pq3rp1p"
path.s3tc="res://.godot/imported/Perlin_noise_example.png-1d87d1cb590d7ea007c419d3f3ff388b.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://scripts/shaders/Perlin_noise_example.png"
dest_files=["res://.godot/imported/Perlin_noise_example.png-1d87d1cb590d7ea007c419d3f3ff388b.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
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/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

View file

@ -0,0 +1,46 @@
shader_type spatial;
render_mode unshaded;
uniform sampler2D dissolve_texture : hint_default_transparent;
uniform float threshold : hint_range(0,1);
uniform vec3 color : source_color;
uniform float alpha_add = 1;
uniform float speed : hint_range(0, 0.01) = 0.005;
float fresnel(vec3 Normal, vec3 ViewDir, float Power){
return pow((1.0 - clamp(dot(normalize(Normal), normalize(ViewDir)), 0, 1)), Power);
}
float _fresnel(vec2 uv, float Power){
return pow((clamp(sin(PI * uv.x) * sin(PI * uv.y), 0, 1)), Power);
}
vec2 loop(vec2 vec){
vec2 res = vec;
vec2 floors = floor(res);
res.x -= floor(res.x);
res.y -= floor(res.y);
if(int(floors.x) % 2 == 0){
res.x = 1.0 - res.x;
}
if(int(floors.y) % 2 == 0){
res.y = 1.0 - res.y;
}
return res;
}
void fragment(){
vec4 noise_texture = texture(dissolve_texture, loop(UV + vec2(TIME, TIME) * speed));
noise_texture *= texture(dissolve_texture, loop(UV + vec2(-TIME, -TIME) * speed)) / 0.5;
noise_texture *= texture(dissolve_texture, loop(UV + vec2(TIME, -TIME) * speed)) / 0.5;
noise_texture *= texture(dissolve_texture, loop(UV + vec2(-TIME, TIME) * speed)) / 0.5;
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(-TIME, TIME) * speed * 0.3)) / 0.5;
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(TIME, -TIME) * speed * 0.5)) / 0.5;
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(TIME, TIME) * speed * 0.8)) / 0.5;
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(-TIME, -TIME) * speed)) / 0.5;
ALPHA = clamp(noise_texture.x - threshold, 0, 1);
ALPHA *= _fresnel(UV, 3) * alpha_add;
ALPHA = clamp(ALPHA, 0, 1);
ALBEDO = color;
}

View file

@ -0,0 +1,231 @@
/*
Shader from Godot Shaders - the free shader library.
godotshaders.com/shader/VHS-and-CRT-monitor-effect
This shader is under CC0 license. Feel free to use, improve and
change this shader according to your needs and consider sharing
the modified result to godotshaders.com.
*/
shader_type canvas_item;
//*** IMPORTANT! ***/
// - If you are using this shader to affect the node it is applied to set 'overlay' to false (unchecked in the instepctor).
// - If you are using this shader as an overlay, and want the shader to affect the nodes below in the Scene hierarchy,
// set 'overlay' to true (checked in the inspector).
// On Mac there is potentially a bug causing this to not work properly. If that is the case and you want to use the shader as an overlay
// change all "overlay ? SCREEN_TEXTURE : TEXTURE" to only "SCREEN_TEXTURE" on lines 129-140, and "vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV);"
// to "vec2 uv = warp(SCREEN_UV);" on line 98.
uniform bool overlay = false;
uniform float scanlines_opacity : hint_range(0.0, 1.0) = 0.4;
uniform float scanlines_width : hint_range(0.0, 0.5) = 0.25;
uniform float grille_opacity : hint_range(0.0, 1.0) = 0.3;
uniform vec2 resolution = vec2(640.0, 480.0); // Set the number of rows and columns the texture will be divided in. Scanlines and grille will make a square based on these values
uniform bool pixelate = true; // Fill each square ("pixel") with a sampled color, creating a pixel look and a more accurate representation of how a CRT monitor would work.
uniform bool roll = true;
uniform float roll_speed = 8.0; // Positive values are down, negative are up
uniform float roll_size : hint_range(0.0, 100.0) = 15.0;
uniform float roll_variation : hint_range(0.1, 5.0) = 1.8; // This valie is not an exact science. You have to play around with the value to find a look you like. How this works is explained in the code below.
uniform float distort_intensity : hint_range(0.0, 0.2) = 0.05; // The distortion created by the rolling effect.
uniform float noise_opacity : hint_range(0.0, 1.0) = 0.4;
uniform float noise_speed = 5.0; // There is a movement in the noise pattern that can be hard to see first. This sets the speed of that movement.
uniform float static_noise_intensity : hint_range(0.0, 1.0) = 0.06;
uniform float aberration : hint_range(-1.0, 1.0) = 0.03; // Chromatic aberration, a distortion on each color channel.
uniform float brightness = 1.4; // When adding scanline gaps and grille the image can get very dark. Brightness tries to compensate for that.
uniform bool discolor = true; // Add a discolor effect simulating a VHS
uniform float warp_amount :hint_range(0.0, 5.0) = 1.0; // Warp the texture edges simulating the curved glass of a CRT monitor or old TV.
uniform bool clip_warp = false;
uniform float vignette_intensity = 0.4; // Size of the vignette, how far towards the middle it should go.
uniform float vignette_opacity : hint_range(0.0, 1.0) = 0.5;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
// Used by the noise functin to generate a pseudo random value between 0.0 and 1.0
vec2 random(vec2 uv){
uv = vec2( dot(uv, vec2(127.1,311.7) ),
dot(uv, vec2(269.5,183.3) ) );
return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
}
// Generate a Perlin noise used by the distortion effects
float noise(vec2 uv) {
vec2 uv_index = floor(uv);
vec2 uv_fract = fract(uv);
vec2 blur = smoothstep(0.0, 1.0, uv_fract);
return mix( mix( dot( random(uv_index + vec2(0.0,0.0) ), uv_fract - vec2(0.0,0.0) ),
dot( random(uv_index + vec2(1.0,0.0) ), uv_fract - vec2(1.0,0.0) ), blur.x),
mix( dot( random(uv_index + vec2(0.0,1.0) ), uv_fract - vec2(0.0,1.0) ),
dot( random(uv_index + vec2(1.0,1.0) ), uv_fract - vec2(1.0,1.0) ), blur.x), blur.y) * 0.5 + 0.5;
}
// Takes in the UV and warps the edges, creating the spherized effect
vec2 warp(vec2 uv){
vec2 delta = uv - 0.5;
float delta2 = dot(delta.xy, delta.xy);
float delta4 = delta2 * delta2;
float delta_offset = delta4 * warp_amount;
return uv + delta * delta_offset;
}
// Adds a black border to hide stretched pixel created by the warp effect
float border (vec2 uv){
float radius = min(warp_amount, 0.08);
radius = max(min(min(abs(radius * 2.0), abs(1.0)), abs(1.0)), 1e-5);
vec2 abs_uv = abs(uv * 2.0 - 1.0) - vec2(1.0, 1.0) + radius;
float dist = length(max(vec2(0.0), abs_uv)) / radius;
float square = smoothstep(0.96, 1.0, dist);
return clamp(1.0 - square, 0.0, 1.0);
}
// Adds a vignette shadow to the edges of the image
float vignette(vec2 uv){
uv *= 1.0 - uv.xy;
float vignette = uv.x * uv.y * 15.0;
return pow(vignette, vignette_intensity * vignette_opacity);
}
void fragment()
{
vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV); // Warp the uv. uv will be used in most cases instead of UV to keep the warping
vec2 text_uv = uv;
vec2 roll_uv = vec2(0.0);
float time = roll ? TIME : 0.0;
// Pixelate the texture based on the given resolution.
if (pixelate)
{
text_uv = ceil(uv * resolution) / resolution;
}
// Create the rolling effect. We need roll_line a bit later to make the noise effect.
// That is why this runs if roll is true OR noise_opacity is over 0.
float roll_line = 0.0;
if (roll || noise_opacity > 0.0)
{
// Create the areas/lines where the texture will be distorted.
roll_line = smoothstep(0.3, 0.9, sin(uv.y * roll_size - (time * roll_speed) ) );
// Create more lines of a different size and apply to the first set of lines. This creates a bit of variation.
roll_line *= roll_line * smoothstep(0.3, 0.9, sin(uv.y * roll_size * roll_variation - (time * roll_speed * roll_variation) ) );
// Distort the UV where where the lines are
roll_uv = vec2(( roll_line * distort_intensity * (1.-UV.x)), 0.0);
}
vec4 text;
if (roll)
{
// If roll is true distort the texture with roll_uv. The texture is split up into RGB to
// make some chromatic aberration. We apply the aberration to the red and green channels accorging to the aberration parameter
// and intensify it a bit in the roll distortion.
text.r = texture(SCREEN_TEXTURE, text_uv + roll_uv * 0.8 + vec2(aberration, 0.0) * .1).r;
text.g = texture(SCREEN_TEXTURE, text_uv + roll_uv * 1.2 - vec2(aberration, 0.0) * .1 ).g;
text.b = texture(SCREEN_TEXTURE, text_uv + roll_uv).b;
text.a = 1.0;
}
else
{
// If roll is false only apply the aberration without any distorion. The aberration values are very small so the .1 is only
// to make the slider in the Inspector less sensitive.
text.r = texture(SCREEN_TEXTURE, text_uv + vec2(aberration, 0.0) * .1).r;
text.g = texture(SCREEN_TEXTURE, text_uv - vec2(aberration, 0.0) * .1).g;
text.b = texture(SCREEN_TEXTURE, text_uv).b;
text.a = 1.0;
}
float r = text.r;
float g = text.g;
float b = text.b;
uv = warp(UV);
// CRT monitors don't have pixels but groups of red, green and blue dots or lines, called grille. We isolate the texture's color channels
// and divide it up in 3 offsetted lines to show the red, green and blue colors next to each other, with a small black gap between.
if (grille_opacity > 0.0){
float g_r = smoothstep(0.85, 0.95, abs(sin(uv.x * (resolution.x * 3.14159265))));
r = mix(r, r * g_r, grille_opacity);
float g_g = smoothstep(0.85, 0.95, abs(sin(1.05 + uv.x * (resolution.x * 3.14159265))));
g = mix(g, g * g_g, grille_opacity);
float b_b = smoothstep(0.85, 0.95, abs(sin(2.1 + uv.x * (resolution.x * 3.14159265))));
b = mix(b, b * b_b, grille_opacity);
}
// Apply the grille to the texture's color channels and apply Brightness. Since the grille and the scanlines (below) make the image very dark you
// can compensate by increasing the brightness.
text.r = clamp(r * brightness, 0.0, 1.0);
text.g = clamp(g * brightness, 0.0, 1.0);
text.b = clamp(b * brightness, 0.0, 1.0);
// Scanlines are the horizontal lines that make up the image on a CRT monitor.
// Here we are actual setting the black gap between each line, which I guess is not the right definition of the word, but you get the idea
float scanlines = 0.5;
if (scanlines_opacity > 0.0)
{
// Same technique as above, create lines with sine and applying it to the texture. Smoothstep to allow setting the line size.
scanlines = smoothstep(scanlines_width, scanlines_width + 0.5, abs(sin(uv.y * (resolution.y * 3.14159265))));
text.rgb = mix(text.rgb, text.rgb * vec3(scanlines), scanlines_opacity);
}
// Apply the banded noise.
if (noise_opacity > 0.0)
{
// Generate a noise pattern that is very stretched horizontally, and animate it with noise_speed
float noise = smoothstep(0.4, 0.5, noise(uv * vec2(2.0, 200.0) + vec2(10.0, (TIME * (noise_speed))) ) );
// We use roll_line (set above) to define how big the noise should be vertically (multiplying cuts off all black parts).
// We also add in some basic noise with random() to break up the noise pattern above. The noise is sized according to
// the resolution value set in the inspector. If you don't like this look you can
// change "ceil(uv * resolution) / resolution" to only "uv" to make it less pixelated. Or multiply resolution with som value
// greater than 1.0 to make them smaller.
roll_line *= noise * scanlines * clamp(random((ceil(uv * resolution) / resolution) + vec2(TIME * 0.8, 0.0)).x + 0.8, 0.0, 1.0);
// Add it to the texture based on noise_opacity
text.rgb = clamp(mix(text.rgb, text.rgb + roll_line, noise_opacity), vec3(0.0), vec3(1.0));
}
// Apply static noise by generating it over the whole screen in the same way as above
if (static_noise_intensity > 0.0)
{
text.rgb += clamp(random((ceil(uv * resolution) / resolution) + fract(TIME)).x, 0.0, 1.0) * static_noise_intensity;
}
// Apply a black border to hide imperfections caused by the warping.
// Also apply the vignette
text.rgb *= border(uv);
text.rgb *= vignette(uv);
// Hides the black border and make that area transparent. Good if you want to add the the texture on top an image of a TV or monitor.
if (clip_warp)
{
text.a = border(uv);
}
// Apply discoloration to get a VHS look (lower saturation and higher contrast)
// You can play with the values below or expose them in the Inspector.
float saturation = 0.5;
float contrast = 1.2;
if (discolor)
{
// Saturation
vec3 greyscale = vec3(text.r + text.g + text.b) / 3.;
text.rgb = mix(text.rgb, greyscale, saturation);
// Contrast
float midpoint = pow(0.5, 2.2);
text.rgb = (text.rgb - vec3(midpoint)) * contrast + midpoint;
}
COLOR = text;
}

View file

@ -0,0 +1,11 @@
shader_type canvas_item;
uniform sampler2D dissolve_texture : hint_default_transparent;
uniform float dissolve_value : hint_range(0,1);
void fragment(){
vec4 main_texture = texture(TEXTURE, UV);
vec4 noise_texture = texture(dissolve_texture, UV);
main_texture.a *= floor(dissolve_value + min(1, noise_texture.x));
COLOR = main_texture;
}

View file

@ -0,0 +1,45 @@
shader_type canvas_item;
uniform int num_colors: hint_range(2,32) = 8;
uniform sampler2D PALETTE_TEXTURE: hint_default_black;
uniform sampler2D PALETTE_TEXTURE_LOW: hint_default_black;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
uniform int u_dither_size = 4;
vec3 palette_limiter (in vec3 albedo, in vec2 uv){
float estimation_cutoff = 0.001;
vec3 closest_color;
float min_dist = 2.0;
float n = float(num_colors);
bool palette_low = (int(uv.y)) % 2 == 0;
for (int i=0; i<num_colors; i++ ){
float index = 1.000/(2.000*n)+float(i)/n;
vec3 index_color = texture(PALETTE_TEXTURE, vec2(index,0.5)).rgb;
float dist = length(index_color - albedo);
if (dist < min_dist) {
min_dist = dist;
if(palette_low){
closest_color = texture(PALETTE_TEXTURE_LOW, vec2(index,0.5)).rgb;
}else{
closest_color = index_color;
}
if (min_dist < estimation_cutoff){
return closest_color;
}
}
}
return closest_color;
}
void fragment() {
vec2 screen_size = vec2(textureSize(SCREEN_TEXTURE, 0)) / float(u_dither_size);
vec2 uv_cord = floor(UV * screen_size);
vec2 screen_sample_uv = uv_cord / screen_size;
vec3 current_color = texture(SCREEN_TEXTURE, screen_sample_uv).rgb;
COLOR.rgb = palette_limiter(current_color, uv_cord);
}

View file

@ -0,0 +1,199 @@
// Wind Waker style water - NekotoArts
// Adapted from https://www.shadertoy.com/view/3tKBDz
// After which I added in some fractal Brownian motion
// as well as vertex displacement
shader_type spatial;
render_mode unshaded;
uniform vec4 WATER_COL : source_color = vec4(0.04, 0.38, 0.88, 1.0);
uniform vec4 WATER2_COL : source_color = vec4(0.04, 0.35, 0.78, 1.0);
uniform vec4 FOAM_COL : source_color = vec4(0.8125, 0.9609, 0.9648, 1.0);
uniform float distortion_speed = 2.0;
uniform vec2 tile = vec2(5.0, 5.0);
uniform float height = 2.0;
uniform vec2 wave_size = vec2(2.0, 2.0);
uniform float wave_speed = 1.5;
const float M_2PI = 6.283185307;
const float M_6PI = 18.84955592;
float random(vec2 uv) {
return fract(sin(dot(uv.xy,
vec2(12.9898,78.233))) *
43758.5453123);
}
float noise(vec2 uv) {
vec2 uv_index = floor(uv);
vec2 uv_fract = fract(uv);
// Four corners in 2D of a tile
float a = random(uv_index);
float b = random(uv_index + vec2(1.0, 0.0));
float c = random(uv_index + vec2(0.0, 1.0));
float d = random(uv_index + vec2(1.0, 1.0));
vec2 blur = smoothstep(0.0, 1.0, uv_fract);
return mix(a, b, blur.x) +
(c - a) * blur.y * (1.0 - blur.x) +
(d - b) * blur.x * blur.y;
}
float fbm(vec2 uv) {
int octaves = 6;
float amplitude = 0.5;
float frequency = 3.0;
float value = 0.0;
for(int i = 0; i < octaves; i++) {
value += amplitude * noise(frequency * uv);
amplitude *= 0.5;
frequency *= 2.0;
}
return value;
}
float circ(vec2 pos, vec2 c, float s)
{
c = abs(pos - c);
c = min(c, 1.0 - c);
return smoothstep(0.0, 0.002, sqrt(s) - sqrt(dot(c, c))) * -1.0;
}
// Foam pattern for the water constructed out of a series of circles
float waterlayer(vec2 uv)
{
uv = mod(uv, 1.0); // Clamp to [0..1]
float ret = 1.0;
ret += circ(uv, vec2(0.37378, 0.277169), 0.0268181);
ret += circ(uv, vec2(0.0317477, 0.540372), 0.0193742);
ret += circ(uv, vec2(0.430044, 0.882218), 0.0232337);
ret += circ(uv, vec2(0.641033, 0.695106), 0.0117864);
ret += circ(uv, vec2(0.0146398, 0.0791346), 0.0299458);
ret += circ(uv, vec2(0.43871, 0.394445), 0.0289087);
ret += circ(uv, vec2(0.909446, 0.878141), 0.028466);
ret += circ(uv, vec2(0.310149, 0.686637), 0.0128496);
ret += circ(uv, vec2(0.928617, 0.195986), 0.0152041);
ret += circ(uv, vec2(0.0438506, 0.868153), 0.0268601);
ret += circ(uv, vec2(0.308619, 0.194937), 0.00806102);
ret += circ(uv, vec2(0.349922, 0.449714), 0.00928667);
ret += circ(uv, vec2(0.0449556, 0.953415), 0.023126);
ret += circ(uv, vec2(0.117761, 0.503309), 0.0151272);
ret += circ(uv, vec2(0.563517, 0.244991), 0.0292322);
ret += circ(uv, vec2(0.566936, 0.954457), 0.00981141);
ret += circ(uv, vec2(0.0489944, 0.200931), 0.0178746);
ret += circ(uv, vec2(0.569297, 0.624893), 0.0132408);
ret += circ(uv, vec2(0.298347, 0.710972), 0.0114426);
ret += circ(uv, vec2(0.878141, 0.771279), 0.00322719);
ret += circ(uv, vec2(0.150995, 0.376221), 0.00216157);
ret += circ(uv, vec2(0.119673, 0.541984), 0.0124621);
ret += circ(uv, vec2(0.629598, 0.295629), 0.0198736);
ret += circ(uv, vec2(0.334357, 0.266278), 0.0187145);
ret += circ(uv, vec2(0.918044, 0.968163), 0.0182928);
ret += circ(uv, vec2(0.965445, 0.505026), 0.006348);
ret += circ(uv, vec2(0.514847, 0.865444), 0.00623523);
ret += circ(uv, vec2(0.710575, 0.0415131), 0.00322689);
ret += circ(uv, vec2(0.71403, 0.576945), 0.0215641);
ret += circ(uv, vec2(0.748873, 0.413325), 0.0110795);
ret += circ(uv, vec2(0.0623365, 0.896713), 0.0236203);
ret += circ(uv, vec2(0.980482, 0.473849), 0.00573439);
ret += circ(uv, vec2(0.647463, 0.654349), 0.0188713);
ret += circ(uv, vec2(0.651406, 0.981297), 0.00710875);
ret += circ(uv, vec2(0.428928, 0.382426), 0.0298806);
ret += circ(uv, vec2(0.811545, 0.62568), 0.00265539);
ret += circ(uv, vec2(0.400787, 0.74162), 0.00486609);
ret += circ(uv, vec2(0.331283, 0.418536), 0.00598028);
ret += circ(uv, vec2(0.894762, 0.0657997), 0.00760375);
ret += circ(uv, vec2(0.525104, 0.572233), 0.0141796);
ret += circ(uv, vec2(0.431526, 0.911372), 0.0213234);
ret += circ(uv, vec2(0.658212, 0.910553), 0.000741023);
ret += circ(uv, vec2(0.514523, 0.243263), 0.0270685);
ret += circ(uv, vec2(0.0249494, 0.252872), 0.00876653);
ret += circ(uv, vec2(0.502214, 0.47269), 0.0234534);
ret += circ(uv, vec2(0.693271, 0.431469), 0.0246533);
ret += circ(uv, vec2(0.415, 0.884418), 0.0271696);
ret += circ(uv, vec2(0.149073, 0.41204), 0.00497198);
ret += circ(uv, vec2(0.533816, 0.897634), 0.00650833);
ret += circ(uv, vec2(0.0409132, 0.83406), 0.0191398);
ret += circ(uv, vec2(0.638585, 0.646019), 0.0206129);
ret += circ(uv, vec2(0.660342, 0.966541), 0.0053511);
ret += circ(uv, vec2(0.513783, 0.142233), 0.00471653);
ret += circ(uv, vec2(0.124305, 0.644263), 0.00116724);
ret += circ(uv, vec2(0.99871, 0.583864), 0.0107329);
ret += circ(uv, vec2(0.894879, 0.233289), 0.00667092);
ret += circ(uv, vec2(0.246286, 0.682766), 0.00411623);
ret += circ(uv, vec2(0.0761895, 0.16327), 0.0145935);
ret += circ(uv, vec2(0.949386, 0.802936), 0.0100873);
ret += circ(uv, vec2(0.480122, 0.196554), 0.0110185);
ret += circ(uv, vec2(0.896854, 0.803707), 0.013969);
ret += circ(uv, vec2(0.292865, 0.762973), 0.00566413);
ret += circ(uv, vec2(0.0995585, 0.117457), 0.00869407);
ret += circ(uv, vec2(0.377713, 0.00335442), 0.0063147);
ret += circ(uv, vec2(0.506365, 0.531118), 0.0144016);
ret += circ(uv, vec2(0.408806, 0.894771), 0.0243923);
ret += circ(uv, vec2(0.143579, 0.85138), 0.00418529);
ret += circ(uv, vec2(0.0902811, 0.181775), 0.0108896);
ret += circ(uv, vec2(0.780695, 0.394644), 0.00475475);
ret += circ(uv, vec2(0.298036, 0.625531), 0.00325285);
ret += circ(uv, vec2(0.218423, 0.714537), 0.00157212);
ret += circ(uv, vec2(0.658836, 0.159556), 0.00225897);
ret += circ(uv, vec2(0.987324, 0.146545), 0.0288391);
ret += circ(uv, vec2(0.222646, 0.251694), 0.00092276);
ret += circ(uv, vec2(0.159826, 0.528063), 0.00605293);
return max(ret, 0.0);
}
// Procedural texture generation for the water
vec3 water(vec2 uv, vec3 cdir, float iTime)
{
uv *= vec2(0.25);
uv += fbm(uv) * 0.2;
// Parallax height distortion with two directional waves at
// slightly different angles.
vec2 a = 0.025 * cdir.xz / cdir.y; // Parallax offset
float h = sin(uv.x + iTime); // Height at UV
uv += a * h;
h = sin(0.841471 * uv.x - 0.540302 * uv.y + iTime);
uv += a * h;
// Texture distortion
float d1 = mod(uv.x + uv.y, M_2PI);
float d2 = mod((uv.x + uv.y + 0.25) * 1.3, M_6PI);
d1 = iTime * 0.07 + d1;
d2 = iTime * 0.5 + d2;
vec2 dist = vec2(
sin(d1) * 0.15 + sin(d2) * 0.05,
cos(d1) * 0.15 + cos(d2) * 0.05
);
vec3 ret = mix(WATER_COL.rgb, WATER2_COL.rgb, waterlayer(uv + dist.xy));
ret = mix(ret, FOAM_COL.rgb, waterlayer(vec2(1.0) - uv - dist.yx));
return ret;
}
void vertex(){
float time = TIME * wave_speed;
vec2 uv = UV * wave_size;
float d1 = mod(uv.x + uv.y, M_2PI);
float d2 = mod((uv.x + uv.y + 0.25) * 1.3, M_6PI);
d1 = time * 0.07 + d1;
d2 = time * 0.5 + d2;
vec2 dist = vec2(
sin(d1) * 0.15 + sin(d2) * 0.05,
cos(d1) * 0.15 + cos(d2) * 0.05
);
VERTEX.y += dist.y * height;
}
void fragment()
{
vec2 uv = UV;
ALBEDO = vec3(water(uv * tile, vec3(0,1,0), TIME * distortion_speed));
}