// 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 : hint_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 : hint_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 : hint_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 : hint_black_albedo; uniform sampler2D samayun : hint_albedo; uniform float samayun_arc = 45 ; uniform vec3 samayun_position = vec3( 0.0, 0.5, 0.0 ); uniform sampler2D zabr : hint_albedo; uniform float zabr_arc = 15 ; uniform vec3 zabr_position = vec3( 0.0, 0.7, 0.0 ); uniform sampler2D stigi : hint_albedo; 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, don’t 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, don’t 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, don’t draw where its alpha is > 0 COLOR += texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).rgb * (texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).a - texture(stigi, stigi_uv / stigi_scale + vec2(0.5)).a); } else { COLOR += texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).rgb * texture(zabr, zabr_uv / zabr_scale + vec2(0.5)).a; } } } }