212 lines
6.9 KiB
Plaintext
212 lines
6.9 KiB
Plaintext
// Copyright (c) 2023-2025 Cory Petkovsek and Contributors
|
|
// Copyright (c) 2021 J. Cuellar
|
|
|
|
shader_type spatial;
|
|
render_mode blend_mix, cull_disabled, unshaded;
|
|
|
|
uniform vec2 _color_correction_params;
|
|
|
|
uniform float _fog_density = .0001;
|
|
uniform float _fog_rayleigh_depth = .115;
|
|
uniform float _fog_mie_depth = 0.;
|
|
uniform float _fog_falloff = 3.;
|
|
uniform float _fog_start = 0.;
|
|
uniform float _fog_end = 1000.;
|
|
uniform vec3 _sun_direction = vec3(.25, -.25, .25);
|
|
uniform vec3 _moon_direction = vec3(.45, -.25, .45);
|
|
|
|
uniform float _atm_darkness = .5;
|
|
uniform float _atm_sun_intensity = 30.;
|
|
uniform vec4 _atm_day_tint: source_color = vec4(.78, .85, .98, 1.);
|
|
uniform vec4 _atm_horizon_light_tint: source_color = vec4(.98, .73, .49, 1.);
|
|
uniform vec4 _atm_night_tint: source_color = vec4(.16, .2, .25, 1.);
|
|
uniform vec3 _atm_level_params = vec3(1., 0., 0.);
|
|
uniform float _atm_thickness = .7;
|
|
|
|
uniform vec3 _atm_beta_ray;
|
|
uniform vec3 _atm_beta_mie;
|
|
|
|
uniform vec3 _atm_sun_partial_mie_phase;
|
|
uniform vec4 _atm_sun_mie_tint: source_color = vec4(1.);
|
|
uniform float _atm_sun_mie_intensity = 1.;
|
|
|
|
uniform vec3 _atm_moon_partial_mie_phase;
|
|
uniform vec4 _atm_moon_mie_tint: source_color = vec4(.13, .18, .29, 1.);
|
|
uniform float _atm_moon_mie_intensity = .7;
|
|
|
|
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;
|
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
|
|
|
// Inc
|
|
//------------------------------------------------------------------------------
|
|
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);
|
|
}
|
|
|
|
// pow3
|
|
vec3 contrastLevel(vec3 vec, float level){
|
|
return mix(vec, vec * vec * vec, level);
|
|
}
|
|
|
|
vec3 tonemapPhoto(vec3 color, float exposure, float level){
|
|
color.rgb *= exposure;
|
|
return mix(color.rgb, 1.0 - exp(-color.rgb), level);
|
|
}
|
|
|
|
vec2 equirectUV(vec3 norm){
|
|
vec2 ret;
|
|
ret.x = (atan(norm.x, norm.z) + kPI) * kINV_TAU;
|
|
ret.y = acos(norm.y) * kINV_PI;
|
|
return ret;
|
|
}
|
|
|
|
// Atmosphere Inc
|
|
//------------------------------------------------------------------------------
|
|
const float RAYLEIGH_ZENITH_LENGTH = 8.4e3;
|
|
const float MIE_ZENITH_LENGTH = 1.25e3;
|
|
|
|
float rayleighPhase(float mu){
|
|
return k3PI16 * (1.0 + mu * mu);
|
|
}
|
|
|
|
float miePhase(float mu, vec3 partial){
|
|
return kPI4 * (partial.x) * (pow(partial.y - partial.z * mu, -1.5));
|
|
}
|
|
|
|
// Simplifield for more performance
|
|
void simpleOpticalDepth(float y, out float sr, out float sm){
|
|
y = max(0.03, y + 0.03) + _atm_level_params.y;
|
|
y = 1.0 / (y * _atm_level_params.x);
|
|
sr = y * RAYLEIGH_ZENITH_LENGTH;
|
|
sm = y * MIE_ZENITH_LENGTH;
|
|
}
|
|
|
|
// Paper based
|
|
void opticalDepth(float y, out float sr, out float sm){
|
|
y = max(0.0, y);
|
|
y = saturate(y * _atm_level_params.x);
|
|
|
|
float zenith = acos(y);
|
|
zenith = cos(zenith) + 0.15 * pow(93.885 - ((zenith * 180.0) / kPI), -1.253);
|
|
zenith = 1.0 / (zenith + _atm_level_params.y);
|
|
|
|
sr = zenith * RAYLEIGH_ZENITH_LENGTH;
|
|
sm = zenith * MIE_ZENITH_LENGTH;
|
|
}
|
|
|
|
vec3 atmosphericScattering(float sr, float sm, vec2 mu, vec3 mult, float depth){
|
|
vec3 betaMie = _atm_beta_mie;
|
|
vec3 betaRay = _atm_beta_ray * _atm_thickness;
|
|
|
|
vec3 extcFactor = saturateRGB(exp(-(betaRay * sr + betaMie * sm)));
|
|
|
|
float extcFF = mix(saturate(_atm_thickness * 0.5), 1.0, mult.x);
|
|
vec3 finalExtcFactor = mix(1.0 - extcFactor, (1.0 - extcFactor) * extcFactor, extcFF);
|
|
|
|
float rayleighPhase = rayleighPhase(mu.x);
|
|
vec3 BRT = betaRay * rayleighPhase * saturate(depth * _fog_rayleigh_depth);
|
|
vec3 BMT = betaMie * miePhase(mu.x, _atm_sun_partial_mie_phase);
|
|
BMT *= _atm_sun_mie_intensity * _atm_sun_mie_tint.rgb * saturate(depth * _fog_mie_depth);
|
|
|
|
vec3 BRMT = (BRT + BMT) / (betaRay + betaMie);
|
|
vec3 scatter = _atm_sun_intensity * (BRMT * finalExtcFactor) * _atm_day_tint.rgb * mult.y;
|
|
scatter = mix(scatter, scatter * (1.0 - extcFactor), _atm_darkness);
|
|
|
|
vec3 lcol = mix(_atm_day_tint.rgb, _atm_horizon_light_tint.rgb, mult.x);
|
|
vec3 nscatter = (1.0 - extcFactor) * _atm_night_tint.rgb * saturate(depth * _fog_rayleigh_depth);
|
|
nscatter += miePhase(mu.y, _atm_moon_partial_mie_phase) *
|
|
_atm_moon_mie_tint.rgb * _atm_moon_mie_intensity * 0.005 * saturate(depth * _fog_mie_depth);
|
|
|
|
return (scatter * lcol) + nscatter;
|
|
}
|
|
|
|
// Fog
|
|
//------------------------------------------------------------------------------
|
|
float fogExp(float depth, float density){
|
|
return 1.0 - saturate(exp2(-depth * density));
|
|
}
|
|
|
|
float fogFalloff(float y, float zeroLevel, float falloff){
|
|
return saturate(exp(-(y + zeroLevel) * falloff));
|
|
}
|
|
|
|
float fogDistance(float depth){
|
|
float d = depth;
|
|
d = (_fog_end - d) / (_fog_end - _fog_start);
|
|
return saturate(1.0 - d);
|
|
}
|
|
|
|
void computeCoords(vec2 uv, float depth, mat4 camMat, mat4 invProjMat,
|
|
out vec3 viewDir, out vec3 worldPos){
|
|
|
|
vec3 ndc = vec3(uv * 2.0 - 1.0, depth);
|
|
|
|
// ViewDir
|
|
vec4 view = invProjMat * vec4(ndc, 1.0);
|
|
viewDir = view.xyz / view.w;
|
|
|
|
// worldPos
|
|
view = camMat * view;
|
|
view.xyz /= view.w;
|
|
view.xyz -= (camMat * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
|
worldPos = view.xyz;
|
|
}
|
|
|
|
// Varyings
|
|
//------------------------------------------------------------------------------
|
|
varying mat4 camera_matrix;
|
|
varying vec4 angle_mult;
|
|
varying flat int angle;
|
|
|
|
void vertex(){
|
|
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
|
|
angle = 0; //ignore; without this the line below errors in 4.3-stable
|
|
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);
|
|
camera_matrix = INV_VIEW_MATRIX;
|
|
}
|
|
|
|
void fragment(){
|
|
float depthRaw = texture(DEPTH_TEXTURE, SCREEN_UV).r;
|
|
|
|
vec3 view; vec3 worldPos;
|
|
computeCoords(SCREEN_UV, depthRaw, camera_matrix, INV_PROJECTION_MATRIX, view, worldPos);
|
|
worldPos = normalize(worldPos);
|
|
|
|
float linearDepth = -view.z;
|
|
float fogFactor = fogExp(linearDepth, _fog_density);
|
|
fogFactor *= fogFalloff(worldPos.y, 0.0, _fog_falloff);
|
|
fogFactor *= fogDistance(linearDepth);
|
|
|
|
vec2 mu = vec2(dot(_sun_direction, worldPos), dot(_moon_direction, worldPos));
|
|
float sr; float sm; simpleOpticalDepth(worldPos.y + _atm_level_params.z, sr, sm);
|
|
vec3 scatter = atmosphericScattering(sr, sm, mu.xy, angle_mult.xyz, linearDepth);
|
|
|
|
vec3 tint = scatter;
|
|
vec4 fogColor = vec4(tint.rgb, fogFactor);
|
|
fogColor = vec4((fogColor.rgb), saturate(fogColor.a));
|
|
fogColor.rgb = tonemapPhoto(fogColor.rgb, _color_correction_params.y, _color_correction_params.x);
|
|
|
|
ALBEDO = fogColor.rgb;
|
|
ALPHA = fogColor.a;
|
|
//ALPHA = (depthRaw) < 0.999999999999 ? fogColor.a: 0.0; // Exclude sky.
|
|
} |