162 lines
5.8 KiB
Plaintext
162 lines
5.8 KiB
Plaintext
// Copyright (c) 2023-2025 Cory Petkovsek and Contributors
|
|
// Copyright (c) 2021 J. Cuellar
|
|
|
|
shader_type spatial;
|
|
render_mode blend_mix, cull_front, unshaded, fog_disabled;
|
|
|
|
|
|
uniform vec2 color_correction;
|
|
|
|
uniform float sea_level: hint_range(-2048,2048,.01) = 0.0;
|
|
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;
|
|
|
|
varying vec4 v_angle_mult;
|
|
|
|
#include "Common.gdshaderinc"
|
|
|
|
// Atmosphere
|
|
vec3 calc_atmospheric_scatter(float sr, float sm, vec2 mu, vec3 mult, float depth) {
|
|
vec3 beta_mie = atm_beta_mie;
|
|
vec3 beta_ray = atm_beta_ray * atm_thickness;
|
|
|
|
vec3 extc_factor = clamp_rgb_to_unit(exp(-(beta_ray * sr + beta_mie * sm)));
|
|
|
|
float extc_ff = mix(clamp_to_unit(atm_thickness * 0.5), 1.0, mult.x);
|
|
vec3 final_extc_factor = mix(1.0 - extc_factor, (1.0 - extc_factor) * extc_factor, extc_ff);
|
|
|
|
float rayleigh_phase = calc_rayleigh_phase(mu.x);
|
|
vec3 BRT = beta_ray * rayleigh_phase * clamp_to_unit(depth * fog_rayleigh_depth);
|
|
vec3 BMT = beta_mie * calc_mie_phase(mu.x, atm_sun_partial_mie_phase);
|
|
BMT *= atm_sun_mie_intensity * atm_sun_mie_tint.rgb * clamp_to_unit(depth * fog_mie_depth);
|
|
|
|
vec3 BRMT = (BRT + BMT) / (beta_ray + beta_mie);
|
|
vec3 scatter = atm_sun_intensity * (BRMT * final_extc_factor) * atm_day_tint.rgb * mult.y;
|
|
scatter = mix(scatter, scatter * (1.0 - extc_factor), atm_darkness);
|
|
|
|
vec3 lcol = mix(atm_day_tint.rgb, atm_horizon_light_tint.rgb, mult.x);
|
|
vec3 nscatter = (1.0 - extc_factor) * atm_night_tint.rgb * clamp_to_unit(depth * fog_rayleigh_depth);
|
|
nscatter += calc_mie_phase(mu.y, atm_moon_partial_mie_phase) *
|
|
atm_moon_mie_tint.rgb * atm_moon_mie_intensity * 0.005 * clamp_to_unit(depth * fog_mie_depth);
|
|
|
|
return (scatter * lcol) + nscatter;
|
|
}
|
|
|
|
// Fog
|
|
float calc_fog_exp(float depth, float density) {
|
|
return 1.0 - clamp_to_unit(exp2(-depth * density));
|
|
}
|
|
|
|
float calc_fog_falloff(float y, float zeroLevel, float falloff) {
|
|
return clamp_to_unit(exp(-(y + zeroLevel) * falloff));
|
|
}
|
|
|
|
float calc_fog_distance(float depth) {
|
|
float d = depth;
|
|
d = (fog_end - d) / (fog_end - fog_start);
|
|
return clamp_to_unit(1.0 - d);
|
|
}
|
|
|
|
|
|
// Main
|
|
|
|
void vertex() {
|
|
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
|
|
v_angle_mult = vec4(
|
|
clamp_to_unit(1.0 - sun_direction.y),
|
|
clamp_to_unit(sun_direction.y + 0.45),
|
|
clamp_to_unit(-sun_direction.y + 0.30),
|
|
clamp_to_unit(-sun_direction.y + 0.60));
|
|
}
|
|
|
|
void fragment() {
|
|
// Calculate world pixel position from depth
|
|
float depth_raw = texture(DEPTH_TEXTURE, SCREEN_UV).r;
|
|
#ifndef CURRENT_RENDERER
|
|
// For 4.3 or earlier, will break if far plane is less than 1m.
|
|
depth_raw = PROJECTION_MATRIX[3][2] > PROJECTION_MATRIX[2][2] ? depth_raw : depth_raw * 2.0 - 1.0;
|
|
#else
|
|
#if CURRENT_RENDERER == RENDERER_COMPATIBILITY
|
|
depth_raw = depth_raw * 2.0 - 1.0;
|
|
#endif
|
|
#endif
|
|
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth_raw);
|
|
vec4 clip_pos = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
|
|
vec3 view_pos = clip_pos.xyz / clip_pos.w;
|
|
vec4 world_pos_hom = INV_VIEW_MATRIX * vec4(view_pos, 1.0);
|
|
vec3 world_position = world_pos_hom.xyz / world_pos_hom.w;
|
|
|
|
// Ray from camera to world intersection point
|
|
vec3 intersection_ray = world_position - CAMERA_POSITION_WORLD;
|
|
// Unit ray direction
|
|
vec3 ray_direction = normalize(intersection_ray);
|
|
//float linear_depth = -view_pos.z; // Approximate ray distance
|
|
//float ray_distance = length(intersection_ray); // Exact ray distance
|
|
|
|
// Cap ray if there's a sea_level plane intersection
|
|
float original_distance = length(intersection_ray);
|
|
// Y difference from camera to sea_level
|
|
float dy = sea_level - CAMERA_POSITION_WORLD.y;
|
|
// Distance along ray to sea_level plane
|
|
float plane_distance = dy / (ray_direction.y + 1e-6 * sign(ray_direction.y)); // avoid divide by zero
|
|
float plane_hit = float(ray_direction.y < 0.) *
|
|
float(plane_distance > 0.) *
|
|
float(plane_distance < original_distance);
|
|
|
|
// Use final distance or t_plane distance Final distance: mix original vs plane distance
|
|
float ray_distance = mix(original_distance, plane_distance, plane_hit);
|
|
|
|
// Capped world position
|
|
//world_position = CAMERA_POSITION_WORLD + ray_distance * ray_direction;
|
|
|
|
float fog_factor = calc_fog_exp(ray_distance, fog_density);
|
|
fog_factor *= calc_fog_falloff(ray_direction.y, 0.0, fog_falloff);
|
|
fog_factor *= calc_fog_distance(ray_distance);
|
|
|
|
vec2 mu = vec2(
|
|
dot(sun_direction, ray_direction),
|
|
dot(moon_direction, ray_direction)
|
|
);
|
|
float sr, sm;
|
|
calc_simple_optical_depth(ray_direction.y + atm_level_params.z, sr, sm, atm_level_params.xy);
|
|
vec3 scatter = calc_atmospheric_scatter(sr, sm, mu, v_angle_mult.xyz, ray_distance);
|
|
|
|
vec4 fog_color = vec4(scatter, fog_factor);
|
|
fog_color.a = clamp(fog_color.a, 0.0, 1.0);
|
|
fog_color.rgb = apply_photo_tonemap(fog_color.rgb, color_correction.y, color_correction.x);
|
|
|
|
ALBEDO = fog_color.rgb;
|
|
ALPHA = fog_color.a;
|
|
|
|
// View depth map
|
|
//ALPHA = 1.;
|
|
//ALBEDO = vec3(ray_distance*.0001);
|
|
}
|