ile-de-test/assets/shaders/khanat_sky.gdshader
2023-10-05 20:02:23 +02:00

155 lines
7.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// NOTE: Shader automatically converted from Godot Engine 4.0.alpha5's PhysicalSkyMaterial.
// And then augmented with a few tweaks
shader_type sky;
uniform float rayleigh : hint_range(0, 64) = 2.0;
uniform vec4 rayleigh_color : source_color = vec4(0.3, 0.405, 0.6, 1.0);
uniform float mie : hint_range(0, 1) = 0.005;
uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;
uniform vec4 mie_color : source_color = vec4(0.69, 0.729, 0.812, 1.0);
uniform float turbidity : hint_range(0, 1000) = 10.0;
uniform float sun_disk_scale : hint_range(0, 360) = 1.0;
uniform vec4 ground_color : source_color = vec4(0.1, 0.07, 0.034, 1.0);
uniform float exposure : hint_range(0, 128) = 0.1;
uniform float dither_strength : hint_range(0, 10) = 1.0;
uniform sampler2D night_sky : source_color;
uniform sampler2D samayun : source_color;
uniform float samayun_arc = 45 ;
uniform vec3 samayun_position = vec3( 0.0, 0.5, 0.0 );
uniform sampler2D zabr : source_color;
uniform float zabr_arc = 15 ;
uniform vec3 zabr_position = vec3( 0.0, 0.7, 0.0 );
uniform sampler2D stigi : source_color;
uniform float stigi_arc = 8 ;
uniform vec3 stigi_position = vec3( 0.0, 0.8, 0.0 );
const vec3 UP = vec3( 0.0, 1.0, 0.0 );
// Sun constants
const float SUN_ENERGY = 1000.0;
// Optical length at zenith for molecules.
const float rayleigh_zenith_size = 8.4e3;
const float mie_zenith_size = 1.25e3;
float henyey_greenstein(float cos_theta, float g) {
const float k = 0.0795774715459;
return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
}
// From: https://www.shadertoy.com/view/4sfGzS credit to iq
float hash(vec3 p) {
p = fract( p * 0.3183099 + 0.1 );
p *= 17.0;
return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
}
// Function to create projection plane for texture at a specific position
vec2 place_object(vec3 position, vec3 eyedir){
//We define a local plane tangent to the skydome at the given position
//We work with everything normalized
vec3 n1 = normalize(cross(position,vec3(0.0,1.0,0.0))) ;
vec3 n2 = normalize(cross(position,n1)) ;
//We project EYEDIR on this plane with an approximate correction for projection
float x = dot(eyedir,n1) * 0.9 ;
float y = dot(eyedir,n2) * 0.9 ;
return vec2(x, y);
}
void sky() {
if (LIGHT0_ENABLED) {
float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;
float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);
// Rayleigh coefficients.
float rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );
vec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;
// mie coefficients from Preetham
vec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;
// Optical length.
float zenith = acos(max(0.0, dot(UP, EYEDIR)));
float optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));
float rayleigh_scatter = rayleigh_zenith_size * optical_mass;
float mie_scatter = mie_zenith_size * optical_mass;
// Light extinction based on thickness of atmosphere.
vec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));
// In scattering.
float cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));
float rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));
vec3 betaRTheta = rayleigh_beta * rayleigh_phase;
float mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);
vec3 betaMTheta = mie_beta * mie_phase;
vec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));
// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js
Lin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));
// Hack in the ground color.
Lin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));
// Solar disk and out-scattering.
float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);
float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);
float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
vec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;
L0 += texture(night_sky, SKY_COORDS).xyz * extinction;
vec3 color = (Lin + L0) * 0.04;
COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
COLOR *= exposure;
// Make optional, eliminates banding.
COLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.016 * dither_strength;
} else {
// There is no sun, so display night_sky and nothing else.
COLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;
COLOR *= exposure;
}
// Calculate respective scales of celestial objects
float samayun_scale = radians(samayun_arc) ;
float zabr_scale = radians(zabr_arc) ;
float stigi_scale = radians(stigi_arc) ;
// Calculate respective plane with UV to place celestial object textures
vec2 samayun_uv = place_object(samayun_position, EYEDIR) ;
vec2 zabr_uv = place_object(zabr_position, EYEDIR) ;
vec2 stigi_uv = place_object(stigi_position, EYEDIR) ;
// Adding the celestial objects from the nearest to the farest
// Adding stigi
if (length(EYEDIR - normalize(stigi_position)) < stigi_scale / 2.0){ // we are in the area of the sky where stigi is placed
COLOR += texture(stigi, stigi_uv / stigi_scale + vec2(0.5)).rgb * texture(stigi, stigi_uv / stigi_scale + vec2(0.5)).a;
}
// Adding samayun
if (length(EYEDIR - normalize(samayun_position)) < samayun_scale / 2.0) { // we are in the area of the sky where samayun is placed
if (length(EYEDIR - normalize(stigi_position)) < stigi_scale / 2.0){ // if stigi is in front of samayun, dont draw where stigi alpha is > 0
COLOR += texture(samayun, samayun_uv / samayun_scale + vec2(0.5)).rgb * max((texture(samayun, samayun_uv / samayun_scale + vec2(0.5)).a - texture(stigi, stigi_uv / stigi_scale + vec2(0.5)).a), 0.0) ;
} else {
COLOR += texture(samayun, samayun_uv / samayun_scale + vec2(0.5)).rgb * texture(samayun, samayun_uv / samayun_scale + vec2(0.5)).a;
}
}
// Adding zabr
if (length(EYEDIR - normalize(zabr_position)) < zabr_scale / 2.0) { // we are in the area of the sky where zabr is placed
if (length(EYEDIR - normalize(samayun_position)) < samayun_scale / 2.0){ // if samayun is in front of zabr, dont draw where samayun alpha is > 0
COLOR += texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).rgb * max((texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).a - texture(samayun, samayun_uv / samayun_scale + vec2(0.5)).a), 0.0) ;
} else {
if (length(EYEDIR - normalize(stigi_position)) < stigi_scale / 2.0){ // if stigi is in front of zabr, dont draw where its alpha is > 0
COLOR += texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).rgb * max((texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).a - texture(stigi, stigi_uv / stigi_scale + vec2(0.5)).a), 0.0) ;
} else {
COLOR += texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).rgb * texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).a;
}
}
}
}