1
0
Fork 0

Rayleigh scattering for light reflected from the terrain, leading to blue hazy distance effects and redshift of reflected sunlight, work in progress, only terrain and water done

This commit is contained in:
Thorsten Renk 2014-10-03 13:49:38 +03:00
parent bd5b09b0ac
commit 4ac3620f5b
7 changed files with 151 additions and 64 deletions

View file

@ -112,6 +112,7 @@
<cloud_self_shading><use>/environment/cloud-self-shading</use></cloud_self_shading>
<moonlight><use>/environment/moonlight</use></moonlight>
<season><use>/environment/season</use></season>
<air_pollution><use>/environment/air-pollution-norm</use></air_pollution>
<wind_effects><use>/sim/rendering/shaders/wind-effects</use></wind_effects>
<windE><use>/environment/sea/surface/wind-from-east-fps</use></windE>
<windN><use>/environment/sea/surface/wind-from-north-fps</use></windN>
@ -293,6 +294,7 @@
<fragment-shader>Shaders/terrain-haze-ultra.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
</program>
<uniform>
<name>grain_strength</name>
@ -429,6 +431,11 @@
<type>float</type>
<value><use>season</use></value>
</uniform>
<uniform>
<name>air_pollution</name>
<type>float</type>
<value><use>air_pollution</use></value>
</uniform>
<uniform>
<name>cloudpos1_x</name>
<type>float</type>

View file

@ -362,6 +362,7 @@
<vertex-shader>Shaders/water_lightfield.vert</vertex-shader>
<fragment-shader>Shaders/water_lightfield.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
</program>
<!--<uniform>
<name>water_reflection</name>
@ -532,7 +533,17 @@
<type>float</type>
<value><use>cloud_self_shading</use></value>
</uniform>
<uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value><use>fogstructure</use></value>
</uniform>
<uniform>
<name>air_pollution</name>
<type>float</type>
<value><use>air_pollution</use></value>
</uniform>
<uniform>
<name>cloudpos1_x</name>
<type>float</type>
<value><use>cloudpos1_x</use></value>

View file

@ -131,6 +131,7 @@
<moonlight><use>/environment/moonlight</use></moonlight>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>
<air_pollution><use>/environment/air-pollution-norm</use></air_pollution>
<ice_cover><use>/environment/sea/surface/ice-cover</use></ice_cover>
<quality_level><use>/sim/rendering/shaders/landmass</use></quality_level>
<!-- sea colors -->
@ -373,6 +374,7 @@
<vertex-shader>Shaders/water_lightfield.vert</vertex-shader>
<fragment-shader>Shaders/water_lightfield.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
</program>
<!--<uniform>
<name>water_reflection</name>
@ -558,6 +560,11 @@
<type>float</type>
<value><use>fogstructure</use></value>
</uniform>
<uniform>
<name>air_pollution</name>
<type>float</type>
<value><use>air_pollution</use></value>
</uniform>
<uniform>
<name>ice_cover</name>
<type>float</type>

74
Shaders/hazes.frag Normal file
View file

@ -0,0 +1,74 @@
// -*-C++-*-
// standard ALS fog function with exp(-d/D) fading and cutoff at low altitude and exp(-d^2/D^2) at high altitude
const float AtmosphericScaleHeight = 8500.0;
float fog_func (in float targ, in float alt)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (alt < 50000.0)
{
fade_mix = (alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else
{
return exp(- targ * targ - pow(targ,4.0));
}
}
// altitude correction for exponential drop in atmosphere density
float alt_factor(in float eye_alt, in float vertex_alt)
{
float h0 = AtmosphericScaleHeight;
float h1 = min(eye_alt,vertex_alt);
float h2 = max(eye_alt,vertex_alt);
if ((h2-h1) < 200.0) // use a Taylor-expanded version
{
return 0.5 * (exp(-h2/h0) + exp(-h1/h0));
}
else
{
return h0/(h2-h1) * (exp(-h1/h0) - exp(-h2/h0));
}
}
// Rayleigh in-scatter function
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt)
{
float fade_length = avisibility * (2.5 - 2.0 * air_pollution);
fade_length = fade_length / alt_factor(eye_alt, vertex_alt);
return 1.0-exp(-dist/max(35000.0,fade_length));
}
// Rayleigh out-scattering color shift
vec3 rayleigh_out_shift(in vec3 color, in float outscatter)
{
color.r = color.r * (1.0 - 0.4 * outscatter);
color.g = color.g * (1.0 - 0.8 * outscatter);
color.b = color.b * (1.0 - 1.6 * outscatter);
return color;
}

View file

@ -42,6 +42,7 @@ uniform float fogstructure;
uniform float snow_thickness_factor;
uniform float cloud_self_shading;
uniform float season;
uniform float air_pollution;
uniform float grain_strength;
uniform float intrinsic_wetness;
uniform float transition_model;
@ -62,7 +63,7 @@ uniform int rock_strata;
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float alt;
//float alt;
float eShade;
float yprime_alt;
float mie_angle;
@ -73,8 +74,10 @@ float Noise2D(in vec2 coord, in float wavelength);
float Noise3D(in vec3 coord, in float wavelength);
float SlopeLines2D(in vec2 coord, in vec2 gradDir, in float wavelength, in float steepness);
float Strata3D(in vec3 coord, in float wavelength, in float variation);
float fog_func (in float targ, in float alt);
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt);
float alt_factor(in float eye_alt, in float vertex_alt);
vec3 rayleigh_out_shift(in vec3 color, in float outscatter);
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
@ -98,39 +101,11 @@ return 1.0 - smoothstep(0.5 * fade_dist, fade_dist, dist);
}
// this determines how light is attenuated in the distance
// physically this should be exp(-arg) but for technical reasons we use a sharper cutoff
// for distance > visibility
float fog_func (in float targ)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (alt < 50000.0)
{
fade_mix = (alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else
{
return exp(- targ * targ - pow(targ,4.0));
}
}
void main()
{
float alt;
yprime_alt = diffuse_term.a;
//diffuse_term.a = 1.0;
@ -298,7 +273,7 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
stprime = stprime * distortion_factor * 15.0;
stprime = stprime + normalize(relPos).xy * 0.022 * (noise_10m + 0.5 * noise_5m +0.25 * noise_2m - 0.875 );
detail_texel = texture2D(detail_texture, stprime);
detail_texel = texture2D(detail_texture, stprime);
if (detail_texel.a <0.1) {flag = 0;}
@ -486,14 +461,17 @@ if ((dist < 5000.0)&& (quality_level > 3) && (combined_wetness>0.0))
fragColor = color * texel + specular;
// here comes the terrain haze model
// Rayleigh color shift due to out-scattering
float rayleigh_length = 0.5 * avisibility * (2.5 - 1.9 * air_pollution)/alt_factor(eye_alt, eye_alt+relPos.z);
float outscatter = 1.0-exp(-dist/rayleigh_length);
fragColor.rgb = rayleigh_out_shift(fragColor.rgb,outscatter);
// here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt;
if (dist > 0.04 * min(visibility,avisibility))
//if ((gl_FragCoord.y > ylimit) || (gl_FragCoord.x < zlimit1) || (gl_FragCoord.x > zlimit2))
//if (dist > 40.0)
{
alt = eye_alt;
@ -604,7 +582,7 @@ else
transmission = fog_func(transmission_arg);
transmission = fog_func(transmission_arg, alt);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
@ -661,6 +639,15 @@ if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColo
}
// blue Rayleigh scattering with distance
float rShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt-340000.0) + 0.1;
float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade;
vec3 rayleighColor = vec3 (0.17, 0.52, 0.87) * lightIntensity;
float rayleighStrength = rayleigh_in_func(dist, air_pollution, avisibility/max(lightIntensity,0.05), eye_alt, eye_alt + relPos.z);
fragColor.rgb = mix(fragColor.rgb, rayleighColor,rayleighStrength);
// finally, mix fog in
fragColor.rgb = mix(eqColorFactor * hazeColor * eShade , fragColor.rgb,transmission);
@ -672,6 +659,15 @@ gl_FragColor = fragColor;
}
else // if dist < threshold no fogging at all
{
// blue Rayleigh scattering with distance
float rShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt-340000.0) + 0.1;
float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade;
vec3 rayleighColor = vec3 (0.17, 0.52, 0.87) * lightIntensity;
float rayleighStrength = rayleigh_in_func(dist, air_pollution, avisibility/max(lightIntensity,0.05), eye_alt, eye_alt + relPos.z);
fragColor.rgb = mix(fragColor.rgb, rayleighColor,rayleighStrength);
gl_FragColor = fragColor;
}

View file

@ -271,6 +271,8 @@ float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smooth
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
// default lighting based on texture and material using the light we have just computed
diffuse_term = diffuse_color* light_diffuse;

View file

@ -59,6 +59,7 @@ uniform float ice_cover;
uniform float sea_r;
uniform float sea_g;
uniform float sea_b;
uniform float air_pollution;
uniform int quality_level;
uniform int ocean_flag;
@ -75,6 +76,10 @@ const float EarthRadius = 5800000.0;
//vec3 fog_Func(vec3 color, int type);
float shadow_func (in float x, in float y, in float noise, in float dist);
float fog_func (in float targ, in float alt);
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt);
float alt_factor(in float eye_alt, in float vertex_alt);
vec3 rayleigh_out_shift(in vec3 color, in float outscatter);
//////////////////////
/////// functions /////////
@ -261,32 +266,8 @@ return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
// physically this should be exp(-arg) but for technical reasons we use a sharper cutoff
// for distance > visibility
float fog_func (in float targ)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ; // need to sync with the distance to which terrain is drawn
if (eye_alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (eye_alt < 50000.0)
{
fade_mix = (eye_alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else
{
return exp(- targ * targ - pow(targ,4.0));
}
}
void main(void)
{
@ -594,6 +575,11 @@ void main(void)
finalColor *= ambient_light;
// Rayleigh color shift due to out-scattering
float rayleigh_length = 0.4 * avisibility * (2.5 - 1.9 * air_pollution)/alt_factor(eye_alt, eye_alt+relPos.z);
float outscatter = 1.0-exp(-dist/rayleigh_length);
finalColor.rgb = rayleigh_out_shift(finalColor.rgb,outscatter);
// here comes the terrain haze model
@ -707,7 +693,7 @@ else
}
transmission = fog_func(transmission_arg);
transmission = fog_func(transmission_arg, eye_alt);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
@ -755,7 +741,11 @@ if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColo
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
}
float rShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt-340000.0) + 0.1;
float lightIntensity = length(gl_Color.rgb)/1.73 * rShade;
vec3 rayleighColor = vec3 (0.17, 0.52, 0.87) * lightIntensity;
float rayleighStrength = rayleigh_in_func(dist, air_pollution, avisibility/max(lightIntensity,0.05), eye_alt, eye_alt + relPos.z);
finalColor.rgb = mix(finalColor.rgb, rayleighColor, rayleighStrength);
finalColor.rgb = mix(eqColorFactor * hazeColor * eShade, finalColor.rgb,transmission);