Shader code
/*
Original shader by mrange (https://www.shadertoy.com/view/csfXzN)
Godot 3.5 port with customizable parameters by PmkExpert
As much as possible of the original has been kept, including comments
MIT License
*/
// License CC0: Sea and moon
// Tinkering with the colors of an old shaders to make it a better fit for windows terminal
shader_type canvas_item;
const float PI = 3.141592654;
//const float TAU = 6.283185308;
//Kept the original names, but they mostly change the waves' speed
uniform float gravity : hint_range(0.0,25.0) = 1.0;
uniform float waterTension : hint_range(0.0,10.0) = 0.01;
//Generally, the shader is dark, so some colors have less effect than others overall
uniform vec4 skyCol1 : hint_color = vec4(0.6, 0.35, 0.3, 1.0);
uniform vec4 skyCol2 : hint_color = vec4(1.0, 0.3, 0.3, 1.0);
uniform vec4 sunCol1 : hint_color = vec4(1.0, 0.5, 0.4, 1.0);
uniform vec4 sunCol2 : hint_color = vec4(1.0, 0.8, 0.8, 1.0);
uniform vec4 seaCol1 : hint_color = vec4(0.1, 0.2, 0.2, 1.0);
uniform vec4 seaCol2 : hint_color = vec4(0.2, 0.9, 0.6, 1.0);
//New uniforms made of values from the code for easier customization
uniform float sunPosX : hint_range(-1.5,1.5) = 0.0; //The celestial body's position
uniform float sunPosY : hint_range(-0.6,0.4) = 0.06; //The celestial body's altitude
uniform float Zoom : hint_range(0.5,20.0) = 2.5; //How much close is the horizon
uniform float sunShine : hint_range(0.1,100.0) = 1.0; //The amount of light emitted
uniform float sunSize : hint_range(0.1,100.0) = 1.0; //Can make it appear better under sea level than sunPos
uniform int seaNoise : hint_range(1,20) = 8; //Makes the sea appear differently
uniform int crestSize : hint_range(1,20) = 4; //How big the waves' crests look
uniform float seaLevel : hint_range(-0.5,0.5) = -0.1; //The horizon's level
//Some other values in the code can be changed for different effects, but their behavior is less predictable
// License: Unknown, author: Unknown, found: don't remember
float tanh_approx(float x) {
// Found this somewhere on the interwebs
// return tanh(x);
float x2 = x*x;
return clamp(x*(27.0 + x2)/(27.0+9.0*x2), -1.0, 1.0);
}
vec2 wave(in float t, in float a, in float w, in float p) {
float x = t;
float y = a*sin(t*w + p);
return vec2(x, y);
}
vec2 dwave(in float t, in float a, in float w, in float p) {
float dx = 1.0;
float dy = a*w*cos(t*w + p);
return vec2(dx, dy);
}
vec2 gravityWave(in float t, in float a, in float k, in float h) {
float w = sqrt(gravity*k*tanh_approx(k*h));
return wave(t, a ,k, w*TIME);
}
vec2 capillaryWave(in float t, in float a, in float k, in float h) {
float w = sqrt((gravity*k + waterTension*k*k*k)*tanh_approx(k*h));
return wave(t, a, k, w*TIME);
}
vec2 gravityWaveD(in float t, in float a, in float k, in float h) {
float w = sqrt(gravity*k*tanh_approx(k*h));
return dwave(t, a, k, w*TIME);
}
vec2 capillaryWaveD(in float t, in float a, in float k, in float h) {
float w = sqrt((gravity*k + waterTension*k*k*k)*tanh_approx(k*h));
return dwave(t, a, k, w*TIME);
}
void mrot(inout vec2 p, in float a) {
float c = cos(a);
float s = sin(a);
p = vec2(c*p.x + s*p.y, -s*p.x + c*p.y);
}
vec4 sea(in vec2 p, in float ia) {
float y = 0.0;
vec3 d = vec3(0.0);
int maxIter = seaNoise;
int midIter = crestSize;
float kk = 1.0/1.3;
float aa = 1.0/(kk*kk);
float k = 1.0*pow(kk, -float(maxIter) + 1.0);
float a = ia*0.25*pow(aa, -float(maxIter) + 1.0);
float h = 25.0;
p *= 0.5;
vec2 waveDir = vec2(0.0, 1.0);
for (int i = midIter; i < maxIter; ++i) {
float t = dot(-waveDir, p) + float(i);
y += capillaryWave(t, a, k, h).y;
vec2 dw = capillaryWaveD(-t, a, k, h);
d += vec3(waveDir.x, dw.y, waveDir.y);
mrot(waveDir, PI/3.0);
k *= kk;
a *= aa;
}
waveDir = vec2(0.0, 1.0);
for (int i = 0; i < midIter; ++i) {
float t = dot(waveDir, p) + float(i);
y += gravityWave(t, a, k, h).y;
vec2 dw = gravityWaveD(t, a, k, h);
vec2 d2 = vec2(0.0, dw.x);
d += vec3(waveDir.x, dw.y, waveDir.y);
mrot(waveDir, -step(2.0, float(i)));
k *= kk;
a *= aa;
}
vec3 t = normalize(d);
vec3 nxz = normalize(vec3(t.z, 0.0, -t.x));
vec3 nor = cross(t, nxz);
return vec4(y, nor);
}
vec3 sunDirection() {
vec3 dir = normalize(vec3(sunPosX, sunPosY, 1));
return dir;
}
vec3 skyColor(in vec3 rd) {
//Added code to change the colors to be modifiable shader params
vec3 skyCol1_ = skyCol1.xyz * 0.5;
vec3 skyCol2_ = skyCol2.xyz * 0.5;
vec3 sunDir = sunDirection();
float sunDot = max(dot(rd, sunDir), 0.0);
vec3 final = vec3(0.0);
final += mix(skyCol1_, skyCol2_, rd.y);
final += 0.5*sunCol1.rgb*pow(sunDot, 90.0 / sunShine);
final += 4.0*sunCol2.rgb*pow(sunDot, 900.0 / sunSize);
return final;
}
vec3 render(in vec3 ro, in vec3 rd) {
//Added code to change the colors to be modifiable shader params
vec3 seaCol1_ = seaCol1.rgb * 0.2;
vec3 seaCol2_ = seaCol2.rgb * 0.5;
vec3 col = vec3(0.0);
float dsea = (0.0 - ro.y)/rd.y;
vec3 sunDir = sunDirection();
vec3 sky = skyColor(rd);
if (dsea > 0.0) {
vec3 p = ro + dsea*rd;
vec4 s = sea(p.xz, 1.0);
float h = s.x;
vec3 nor = s.yzw;
nor = mix(nor, vec3(0.0, 1.0, 0.0), smoothstep(0.0, 200.0, dsea));
float fre = clamp(1.0 - dot(-nor,rd), 0.0, 1.0);
fre = fre*fre*fre;
float dif = mix(0.25, 1.0, max(dot(nor,sunDir), 0.0));
vec3 refl = skyColor(reflect(rd, nor));
vec3 refr = seaCol1_ + dif*sunCol1.rgb*seaCol2_*0.1;
col = mix(refr, 0.9*refl, fre);
float atten = max(1.0 - dot(vec2(dsea),vec2(dsea)) * 0.001, 0.0);
col += seaCol2_*(p.y - h) * 2.0 * atten;
col = mix(col, sky, 1.0 - exp(-0.01*dsea));
} else {
col = sky;
}
return col;
}
void fragment() {
vec2 q = FRAGCOORD.xy/(1.0 / SCREEN_PIXEL_SIZE).xy;
vec2 p = -1. + 2. * q;
p.x *= (1.0 / SCREEN_PIXEL_SIZE).x/(1.0 / SCREEN_PIXEL_SIZE).y;
vec3 ro = vec3(0.0, 10.0, 0.0);
vec3 ww = normalize(vec3(0.0, seaLevel, 1.0));
vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww));
vec3 vv = normalize(cross(ww,uu));
vec3 rd = normalize(p.x*uu + p.y*vv + Zoom*ww);
vec3 col = render(ro, rd);
COLOR.rgb = vec3(col);
COLOR.a = texture(TEXTURE, UV).a;
}
Tags
Moon shader