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:
parent
bd5b09b0ac
commit
4ac3620f5b
7 changed files with 151 additions and 64 deletions
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
74
Shaders/hazes.frag
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue