X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=builtin_data%2F_sky.glsl;fp=builtin_data%2F_sky.glsl;h=45ca330dd80afd89f7845f07d353fc8f5fe2d4e5;hb=06d83c11e10208478487dea864ddd7822630c391;hp=0000000000000000000000000000000000000000;hpb=e98956208676c77e74462f17932ac530077a0540;p=libs%2Fgl.git diff --git a/builtin_data/_sky.glsl b/builtin_data/_sky.glsl new file mode 100644 index 00000000..45ca330d --- /dev/null +++ b/builtin_data/_sky.glsl @@ -0,0 +1,138 @@ +struct AtmosphericEvents +{ + vec3 rayleigh_scatter; + vec3 mie_scatter; + vec3 mie_absorb; + vec3 ozone_absorb; +}; + +uniform Atmosphere +{ + AtmosphericEvents events; + float rayleigh_density_decay; + float mie_density_decay; + float ozone_band_center; + float ozone_band_extent; + float planet_radius; + float atmosphere_thickness; + vec3 ground_albedo; + int n_steps; +}; + +uniform View +{ + float view_height; + vec4 light_color; + vec3 light_dir; +}; + +struct OpticalPathInfo +{ + vec3 optical_depth; + vec3 luminance; +}; + +const float pi = 3.1415926535; +const float mie_asymmetry = 0.8; + +uniform sampler2D transmittance_lookup; + +vec3 rayleigh_density(vec3 base, float height) +{ + return base*exp(height/rayleigh_density_decay); +} + +float rayleigh_phase(float cos_theta) +{ + return 3.0*(1.0+cos_theta*cos_theta)/(16.0*pi); +} + +vec3 mie_density(vec3 base, float height) +{ + return base*exp(height/mie_density_decay); +} + +float mie_phase(float cos_theta) +{ + float g = mie_asymmetry; + float num = (1.0-g*g)*(1.0+cos_theta*cos_theta); + float denom = (2.0+g*g)*pow(1.0+g*g-2.0*g*cos_theta, 1.5); + return 3.0/(8.0*pi)*num/denom; +} + +vec3 ozone_density(vec3 base, float height) +{ + return base*max(1.0-abs(height-ozone_band_center)/ozone_band_extent, 0.0); +} + +AtmosphericEvents calculate_events(float height) +{ + AtmosphericEvents ev; + ev.rayleigh_scatter = rayleigh_density(events.rayleigh_scatter, height); + ev.mie_scatter = mie_density(events.mie_scatter, height); + ev.mie_absorb = mie_density(events.mie_absorb, height); + ev.ozone_absorb = ozone_density(events.ozone_absorb, height); + return ev; +} + +vec3 total_extinction(AtmosphericEvents ev) +{ + return ev.rayleigh_scatter+ev.mie_scatter+ev.mie_absorb+ev.ozone_absorb; +} + +float ray_sphere_intersect(vec3 ray_start, vec3 ray_dir, vec3 sphere_center, float sphere_radius) +{ + float t = dot(sphere_center-ray_start, ray_dir); + vec3 nearest = ray_start+t*ray_dir-sphere_center; + float d_sq = dot(nearest, nearest); + float r_sq = sphere_radius*sphere_radius; + if(d_sq>r_sq) + return -1.0; + + float offset = sqrt(r_sq-d_sq); + if(offset-t) + return t+offset; + else + return -1.0; +} + +#pragma MSP stage(fragment) +OpticalPathInfo raymarch_path(float start_height, vec3 look_dir) +{ + float cos_theta = dot(look_dir, light_dir); + float p_rayleigh = rayleigh_phase(cos_theta); + float p_mie = mie_phase(cos_theta); + + vec3 planet_center = vec3(0.0, 0.0, -planet_radius); + vec3 pos = vec3(0.0, 0.0, start_height); + vec3 path_luminance = vec3(0.0); + vec3 path_extinction = vec3(0.0); + + float ground_t = ray_sphere_intersect(pos, look_dir, planet_center, planet_radius); + float space_t = ray_sphere_intersect(pos, look_dir, planet_center, planet_radius+atmosphere_thickness); + float ray_length = (ground_t>0.0 ? ground_t : space_t); + float step_size = ray_length/n_steps; + + for(int i=0; i<=n_steps; ++i) + { + vec3 from_center = pos-planet_center; + float height = length(from_center); + float light_z = dot(from_center/height, light_dir); + height -= planet_radius; + + AtmosphericEvents ev = calculate_events(height); + vec3 transmittance = exp(-path_extinction); + vec3 in_transmittance = texture(transmittance_lookup, vec2(sqrt(height/atmosphere_thickness), light_z)).rgb; + vec3 in_luminance = (ev.rayleigh_scatter*p_rayleigh+ev.mie_scatter*p_mie)*step_size; + if(i==n_steps && ground_t>0.0) + in_luminance += ground_albedo*light_z/pi; + path_luminance += transmittance*in_transmittance*in_luminance; + + path_extinction += total_extinction(ev)*step_size; + pos += look_dir*step_size; + } + + return OpticalPathInfo(path_extinction, path_luminance); +}