199 lines
5.5 KiB
Plaintext
199 lines
5.5 KiB
Plaintext
// Copyright (c) 2023-2025 Cory Petkovsek and Contributors
|
|
// Copyright (c) 2021 J. Cuellar
|
|
// This shader is based on DanilS clouds shader with MIT License
|
|
// See https://github.com/danilw/godot-utils-and-other/tree/master/Dynamic%20sky%20and%20reflection
|
|
|
|
shader_type spatial;
|
|
render_mode unshaded, blend_mix, depth_draw_never, cull_front, skip_vertex_transform;
|
|
|
|
uniform vec3 _sun_direction;
|
|
uniform vec3 _moon_direction;
|
|
uniform float _clouds_coverage;
|
|
uniform float _clouds_thickness;
|
|
uniform float _clouds_absorption;
|
|
uniform float _clouds_noise_freq;
|
|
uniform float _clouds_sky_tint_fade;
|
|
uniform float _clouds_intensity;
|
|
uniform float _clouds_size;
|
|
uniform float _clouds_speed;
|
|
uniform vec3 _clouds_direction;
|
|
uniform sampler2D _clouds_texture;
|
|
|
|
uniform vec4 _clouds_day_color: source_color;
|
|
uniform vec4 _clouds_horizon_light_color: source_color;
|
|
uniform vec4 _clouds_night_color: source_color;
|
|
|
|
const int kCLOUDS_STEP = 10;
|
|
|
|
uniform vec3 _clouds_partial_mie_phase;
|
|
uniform float _clouds_mie_intensity;
|
|
uniform vec4 _atm_sun_mie_tint;
|
|
uniform vec4 _atm_moon_mie_tint: source_color;
|
|
|
|
const float kPI = 3.1415927f;
|
|
const float kINV_PI = 0.3183098f;
|
|
const float kHALF_PI = 1.5707963f;
|
|
const float kINV_HALF_PI = 0.6366198f;
|
|
const float kQRT_PI = 0.7853982f;
|
|
const float kINV_QRT_PI = 1.2732395f;
|
|
const float kPI4 = 12.5663706f;
|
|
const float kINV_PI4 = 0.0795775f;
|
|
const float k3PI16 = 0.1193662f;
|
|
const float kTAU = 6.2831853f;
|
|
const float kINV_TAU = 0.1591549f;
|
|
const float kE = 2.7182818f;
|
|
|
|
float saturate(float value){
|
|
return clamp(value, 0.0, 1.0);
|
|
}
|
|
|
|
vec3 saturateRGB(vec3 value){
|
|
return clamp(value.rgb, 0.0, 1.0);
|
|
}
|
|
|
|
float pow3(float real){
|
|
return real * real * real;
|
|
}
|
|
|
|
float noiseClouds(vec3 p){
|
|
vec3 pos = vec3(p * 0.01);
|
|
pos.z *= 256.0;
|
|
vec2 offset = vec2(0.317, 0.123);
|
|
vec4 uv= vec4(0.0);
|
|
uv.xy = pos.xy + offset * floor(pos.z);
|
|
uv.zw = uv.xy + offset;
|
|
float x1 = textureLod(_clouds_texture, uv.xy, 0.0).r;
|
|
float x2 = textureLod(_clouds_texture, uv.zw, 0.0).r;
|
|
return mix(x1, x2, fract(pos.z));
|
|
}
|
|
|
|
float cloudsFBM(vec3 p, float l){
|
|
float ret;
|
|
ret = 0.51749673 * noiseClouds(p);
|
|
p *= l;
|
|
ret += 0.25584929 * noiseClouds(p);
|
|
p *= l;
|
|
ret += 0.12527603 * noiseClouds(p);
|
|
p *= l;
|
|
ret += 0.06255931 * noiseClouds(p);
|
|
return ret;
|
|
}
|
|
|
|
float noiseCloudsFBM(vec3 p, float freq){
|
|
return cloudsFBM(p, freq);
|
|
}
|
|
|
|
float remap(float value, float fromMin, float fromMax, float toMin, float toMax){
|
|
return toMin + (value - fromMin) * (toMax - toMin) / (fromMax - fromMin);
|
|
}
|
|
|
|
float cloudsDensity(vec3 p, vec3 offset, float t){
|
|
vec3 pos = p * 0.0212242 - offset;
|
|
float dens = noiseCloudsFBM(pos, _clouds_noise_freq);
|
|
dens += dens;
|
|
|
|
float cov = 1.0-_clouds_coverage;
|
|
cov = smoothstep(0.00, (cov * 3.5) + t, dens);
|
|
dens *= cov;
|
|
dens = remap(dens, 1.0-cov, 1.0, 0.0, 1.0);
|
|
|
|
return saturate(dens);
|
|
}
|
|
|
|
bool IntersectSphere(float r, vec3 origin, vec3 dir, out float t, out vec3 nrm)
|
|
{
|
|
origin += vec3(0.0, 450.0, 0.0);
|
|
float a = dot(dir, dir);
|
|
float b = 2.0 * dot(origin, dir);
|
|
float c = dot(origin, origin) - r * r;
|
|
float d = b * b - 4.0 * a * c;
|
|
if(d < 0.0) return false;
|
|
|
|
d = sqrt(d);
|
|
a *= 2.0;
|
|
float t1 = 0.5 * (-b + d);
|
|
float t2 = 0.5 * (-b - d);
|
|
|
|
if(t1<0.0) t1 = t2;
|
|
if(t2 < 0.0) t2 = t1;
|
|
t1 = min(t1, t2);
|
|
|
|
if(t1 < 0.0) return false;
|
|
nrm = origin + t1 * dir;
|
|
t = t1;
|
|
|
|
return true;
|
|
}
|
|
|
|
float miePhase(float mu, vec3 partial){
|
|
return kPI4 * (partial.x) * (pow(partial.y - partial.z * mu, -1.5));
|
|
}
|
|
|
|
vec4 renderClouds2(vec3 ro, vec3 rd, float tm, float am){
|
|
vec4 ret = vec4(0, 0, 0, 0);
|
|
vec3 wind = _clouds_direction * (tm * _clouds_speed);
|
|
float a = 0.0;
|
|
|
|
// n and tt doesnt need to be initialized since it would be set by IntersectSphere
|
|
vec3 n; float tt;
|
|
if(IntersectSphere(500, ro, rd, tt, n))
|
|
{
|
|
float marchStep = float(kCLOUDS_STEP) * _clouds_thickness;
|
|
vec3 dirStep = rd / rd.y * marchStep;
|
|
vec3 pos = n * _clouds_size;
|
|
|
|
vec2 mu = vec2(dot(_sun_direction, rd), dot(_moon_direction, rd));
|
|
vec3 mph = ((miePhase(mu.x, _clouds_partial_mie_phase) * _atm_sun_mie_tint.rgb) +
|
|
miePhase(mu.y, _clouds_partial_mie_phase) * am);
|
|
|
|
vec4 t = vec4(1.0);
|
|
t.rgb += (mph.rgb * _clouds_mie_intensity);
|
|
|
|
for(int i = 0; i < kCLOUDS_STEP; i++)
|
|
{
|
|
float h = float(i) * 0.1; // / float(kCLOUDS_STEP);
|
|
|
|
float density = cloudsDensity(pos, wind, h);
|
|
float sh = saturate(exp(-_clouds_absorption * density * marchStep));
|
|
t *= sh;
|
|
ret += (t * (exp(h) * 0.571428571) * density * marchStep);
|
|
a += (1.0 - sh) * (1.0 - a);
|
|
pos += dirStep;
|
|
}
|
|
return vec4(ret.rgb * _clouds_intensity, a);
|
|
}
|
|
return vec4(ret.rgb * _clouds_intensity, a);
|
|
}
|
|
|
|
|
|
varying vec4 world_pos;
|
|
varying vec4 moon_coords;
|
|
varying vec3 deep_space_coords;
|
|
varying vec4 angle_mult;
|
|
|
|
void vertex(){
|
|
vec4 vert = vec4(VERTEX, 0.0);
|
|
POSITION = PROJECTION_MATRIX * MODELVIEW_MATRIX * vert;
|
|
POSITION.z = 0.0000001;
|
|
|
|
world_pos = (MODEL_MATRIX * vert);
|
|
angle_mult.x = saturate(1.0 - _sun_direction.y);
|
|
angle_mult.y = saturate(_sun_direction.y + 0.45);
|
|
angle_mult.z = saturate(-_sun_direction.y + 0.30);
|
|
angle_mult.w = saturate(-_sun_direction.y + 0.60);
|
|
}
|
|
|
|
void fragment(){
|
|
vec3 ray = normalize(world_pos).xyz;
|
|
float horizonBlend = saturate((ray.y+0.01) * 50.0);
|
|
|
|
vec4 clouds = renderClouds2(vec3(0.0, 0.0, 0.0), ray, TIME, angle_mult.z);
|
|
clouds.a = saturate(clouds.a);
|
|
clouds.rgb *= mix(mix(_clouds_day_color.rgb, _clouds_horizon_light_color.rgb, angle_mult.x),
|
|
_clouds_night_color.rgb, angle_mult.w);
|
|
clouds.a = mix(0.0, clouds.a, horizonBlend);
|
|
|
|
ALBEDO = clouds.rgb;
|
|
ALPHA = pow3(clouds.a);
|
|
}
|