WS30: Separate out haze calculations
Previously haze calculations were performed in the main body of the ws30 shaders (inherited from the ALS terrain shaders). This change creates a common applyHaze function to consistently apply haze. This is not ws30 specific, and could be used to replace the haze calculations of all ALS shaders for improved consistency.
This commit is contained in:
parent
d8110f0b38
commit
4564b30eac
7 changed files with 299 additions and 620 deletions
|
@ -167,6 +167,11 @@
|
|||
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
|
||||
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>quality_level</name>
|
||||
<type>int</type>
|
||||
<value><use>quality_level</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>grain_strength</name>
|
||||
<type>float</type>
|
||||
|
|
|
@ -297,6 +297,11 @@
|
|||
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
|
||||
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>quality_level</name>
|
||||
<type>int</type>
|
||||
<value><use>quality_level</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>visibility</name>
|
||||
<type>float</type>
|
||||
|
@ -1192,6 +1197,16 @@
|
|||
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
|
||||
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>tquality_level</name>
|
||||
<type>int</type>
|
||||
<value><use>tquality_level</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>cloud_self_shading</name>
|
||||
<type>float</type>
|
||||
<value><use>cloud_self_shading</use></value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>visibility</name>
|
||||
<type>float</type>
|
||||
|
|
|
@ -2,102 +2,260 @@
|
|||
#version 120
|
||||
|
||||
uniform float air_pollution;
|
||||
uniform int quality_level;
|
||||
uniform float fogstructure;
|
||||
uniform float cloud_self_shading;
|
||||
uniform float scattering;
|
||||
uniform float terminator;
|
||||
uniform float terrain_alt;
|
||||
uniform float overcast;
|
||||
uniform float eye_alt;
|
||||
|
||||
// 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 terminator_width = 200000.0;
|
||||
const float EarthRadius = 5800000.0;
|
||||
|
||||
varying vec3 relPos;
|
||||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
varying vec3 worldPos;
|
||||
|
||||
float Noise2D(in vec2 coord, in float wavelength);
|
||||
vec3 filter_combined (in vec3 color) ;
|
||||
float Noise3D(in vec3 coord, in float wavelength);
|
||||
|
||||
const float AtmosphericScaleHeight = 8500.0;
|
||||
|
||||
// Development tools:
|
||||
// Reduce haze to almost zero, while preserving lighting. Useful for observing distant tiles.
|
||||
// Keeps the calculation overhead. This can be used for profiling.
|
||||
// Possible values: 0:Normal, 1:Reduced haze.
|
||||
const int reduce_haze_without_removing_calculation_overhead = 0;
|
||||
|
||||
// standard ALS fog function with exp(-d/D) fading and cutoff at low altitude and exp(-d^2/D^2) at high altitude
|
||||
float fog_func (in float targ, in float alt)
|
||||
{
|
||||
float fade_mix;
|
||||
|
||||
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
|
||||
|
||||
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));
|
||||
}
|
||||
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
|
||||
// create the illusion of improved visibility range
|
||||
|
||||
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);
|
||||
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));
|
||||
}
|
||||
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.2 * sqrt(air_pollution));
|
||||
|
||||
fade_length = fade_length / alt_factor(eye_alt, vertex_alt);
|
||||
|
||||
return 1.0-exp(-dist/max(15000.0,fade_length));
|
||||
float fade_length = avisibility * (2.5 - 2.2 * sqrt(air_pollution));
|
||||
fade_length = fade_length / alt_factor(eye_alt, vertex_alt);
|
||||
return 1.0-exp(-dist/max(15000.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;
|
||||
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;
|
||||
}
|
||||
|
||||
// the generalized logistic function used to compute lightcurves
|
||||
|
||||
float light_curve (in float x, in float a, in float b, in float c, in float d, in float e)
|
||||
{
|
||||
x = x - 0.5;
|
||||
|
||||
// use the asymptotics to shorten computations
|
||||
if (x > 30.0) {return e;}
|
||||
if (x < -15.0) {return 0.0;}
|
||||
|
||||
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
|
||||
x = x - 0.5;
|
||||
// use the asymptotics to shorten computations
|
||||
if (x > 30.0) { return e; }
|
||||
if (x < -15.0) { return 0.0; }
|
||||
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
|
||||
}
|
||||
|
||||
// the haze color function
|
||||
|
||||
vec3 get_hazeColor(in float lightArg)
|
||||
{
|
||||
vec3 hazeColor;
|
||||
hazeColor.r = light_curve(lightArg, 8.305e-06, 0.161, 4.827-3.0 *air_pollution, 3.04e-05, 1.0);
|
||||
hazeColor.g = light_curve(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
|
||||
hazeColor.b = light_curve(lightArg, 1.330e-05, 0.264, 1.527+ 2.0*air_pollution, 1.08e-05, 1.0);
|
||||
|
||||
return hazeColor;
|
||||
vec3 hazeColor;
|
||||
hazeColor.r = light_curve(lightArg, 8.305e-06, 0.161, 4.827-3.0 *air_pollution, 3.04e-05, 1.0);
|
||||
hazeColor.g = light_curve(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
|
||||
hazeColor.b = light_curve(lightArg, 1.330e-05, 0.264, 1.527+ 2.0*air_pollution, 1.08e-05, 1.0);
|
||||
return hazeColor;
|
||||
}
|
||||
|
||||
// Apply the ALS haze model to a given fragment
|
||||
vec4 applyHaze(inout vec4 fragColor,
|
||||
inout vec3 hazeColor,
|
||||
in vec3 secondary_light,
|
||||
in float ct,
|
||||
in float hazeLayerAltitude,
|
||||
in float visibility,
|
||||
in float avisibility,
|
||||
in float dist,
|
||||
in float lightArg,
|
||||
in float mie_angle)
|
||||
{
|
||||
float mvisibility = min(visibility,avisibility);
|
||||
|
||||
if (dist > 0.04 * mvisibility)
|
||||
{
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
float intensity;
|
||||
float eShade;
|
||||
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
float yprime_alt = light_diffuse_comp.a;
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
vec3 lightDir = gl_LightSource[0].position.xyz;
|
||||
vec3 n = normal;
|
||||
n = normalize(n);
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
if (delta_z > 0.0) { // we're inside the layer
|
||||
if (ct < 0.0) { // we look down
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,mvisibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
} else {
|
||||
// we may look through upper layer edge
|
||||
H = dist * ct;
|
||||
|
||||
if (H > delta_z) {
|
||||
distance_in_layer = dist/H * delta_z;
|
||||
} else {
|
||||
distance_in_layer = dist;
|
||||
}
|
||||
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
} else { // we see the layer from above, delta_z < 0.0
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) { // we don't see into the layer at all, aloft visibility is the only fading
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
} else {
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
if ((quality_level > 4) && (abs(delta_z) < 400.0)) {
|
||||
float blur_thickness = 50.0;
|
||||
float cphi = dot(vec3(0.0, 1.0, 0.0), relPos)/dist;
|
||||
float ctlayer = delta_z/dist-0.01 + 0.02 * Noise2D(vec2(cphi,1.0),0.1) -0.01;
|
||||
float ctblur = 0.035 ;
|
||||
float blur_dist;
|
||||
|
||||
blur_dist = dist * (1.0-smoothstep(0.0,300.0,-delta_z)) * smoothstep(-400.0,-200.0, -delta_z);
|
||||
blur_dist = blur_dist * smoothstep(ctlayer-4.0*ctblur, ctlayer-ctblur, ct) * (1.0-smoothstep(ctlayer+0.5*ctblur, ctlayer+ctblur, ct));
|
||||
distance_in_layer = max(distance_in_layer, blur_dist);
|
||||
}
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
float eqColorFactor;
|
||||
|
||||
if (quality_level > 3) {
|
||||
float noise_1500m = Noise3D(worldPos.xyz, 1500.0);
|
||||
float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * mvisibility + 1.0 * mvisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
|
||||
} else {
|
||||
transmission_arg = transmission_arg + (distance_in_layer/mvisibility);
|
||||
}
|
||||
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/mvisibility - (1.0 - effective_scattering);
|
||||
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;
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
// Mie-like factor
|
||||
if (lightArg < 10.0) {
|
||||
intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
intensity = length(hazeColor);
|
||||
|
||||
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
|
||||
{
|
||||
// high altitude desaturation of the haze color
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, eye_alt)));
|
||||
|
||||
// blue hue of haze
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
float shadow = mix( min(1.0 + dot(n,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
}
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor.rgb *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
{
|
||||
transmission = 1.0 - (transmission/1000000.0);
|
||||
}
|
||||
|
||||
// finally, mix fog in
|
||||
if (quality_level > 4) {
|
||||
float backscatter = 0.5* min(1.0,10000.0/(mvisibility*mvisibility));
|
||||
fragColor.rgb = mix(hazeColor+secondary_light * backscatter , fragColor.rgb,transmission);
|
||||
} else {
|
||||
fragColor.rgb = mix(clamp(hazeColor,0.0,1.0) , clamp(fragColor.rgb,0.0,1.0),transmission);
|
||||
}
|
||||
} // end if (dist > 0.04 * mvisibility)
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
return fragColor;
|
||||
}
|
|
@ -197,6 +197,18 @@ void get_material(in int landclass,
|
|||
out vec2 st
|
||||
);
|
||||
|
||||
// Apply the ALS haze model to a specific fragment
|
||||
vec4 applyHaze(inout vec4 fragColor,
|
||||
inout vec3 hazeColor,
|
||||
in vec3 secondary_light,
|
||||
in float ct,
|
||||
in float hazeLayerAltitude,
|
||||
in float visibility,
|
||||
in float avisibility,
|
||||
in float dist,
|
||||
in float lightArg,
|
||||
in float mie_angle);
|
||||
|
||||
|
||||
|
||||
// End Test-phase code
|
||||
|
@ -555,185 +567,12 @@ if ((dist < 5000.0)&& (quality_level > 3) && (wetness>0.0))
|
|||
// is closer to what the OpenGL fixed function pipeline does.
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
|
||||
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, texel.rgb);
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
|
||||
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
|
||||
if (delta_z > 0.0) // we're inside the layer
|
||||
{
|
||||
if (ct < 0.0) // we look down
|
||||
{
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
else // we may look through upper layer edge
|
||||
{
|
||||
H = dist * ct;
|
||||
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
|
||||
else {distance_in_layer = dist;}
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
|
||||
float eqColorFactor;
|
||||
|
||||
|
||||
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
if (quality_level > 3)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/visibility);
|
||||
}
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quality_level > 3)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
|
||||
}
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 - effective_scattering);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
|
||||
// Mie-like factor
|
||||
|
||||
if (lightArg < 10.0)
|
||||
{
|
||||
intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
intensity = length(hazeColor);
|
||||
|
||||
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
|
||||
{
|
||||
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
|
||||
// blue hue of haze
|
||||
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
|
||||
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
float shadow = mix( min(1.0 + dot(n,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
{
|
||||
transmission = 1.0 - (transmission/1000000.0);
|
||||
}
|
||||
|
||||
fragColor.rgb = mix(clamp(hazeColor,0.0,1.0) , clamp(fragColor.rgb,0.0,1.0),transmission);
|
||||
|
||||
}
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
|
||||
gl_FragColor = applyHaze(fragColor, hazeColor, vec3(0.0), ct, hazeLayerAltitude, visibility, avisibility, dist, lightArg, mie_angle);
|
||||
|
||||
|
||||
// Testing phase controls:
|
||||
|
|
|
@ -10,12 +10,6 @@
|
|||
// TEST PHASE TOGGLES AND CONTROLS
|
||||
//
|
||||
|
||||
// Development tools:
|
||||
// Reduce haze to almost zero, while preserving lighting. Useful for observing distant tiles.
|
||||
// Keeps the calculation overhead. This can be used for profiling.
|
||||
// Possible values: 0:Normal, 1:Reduced haze.
|
||||
const int reduce_haze_without_removing_calculation_overhead = 0;
|
||||
|
||||
// Remove haze and lighting and shows just the texture.
|
||||
// Useful for checking texture rendering and scenery.
|
||||
// The compiler will likely optimise out the haze and lighting calculations.
|
||||
|
@ -36,19 +30,6 @@
|
|||
// End of test phase controls
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// written by Thorsten Renk, Oct 2011, based on default.frag
|
||||
// Ambient term comes in gl_Color.rgb.
|
||||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
|
@ -60,19 +41,13 @@ varying vec2 rawPos;
|
|||
//vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
|
||||
varying vec3 ecViewdir;
|
||||
varying vec2 grad_dir;
|
||||
//varying vec2 orthoTexCoord;
|
||||
varying vec4 ecPosition;
|
||||
|
||||
varying float steepness;
|
||||
|
||||
uniform sampler2D landclass;
|
||||
uniform sampler2DArray textureArray;
|
||||
uniform sampler2D perlin;
|
||||
|
||||
|
||||
varying float steepness;
|
||||
|
||||
|
||||
|
||||
uniform float visibility;
|
||||
uniform float avisibility;
|
||||
uniform float scattering;
|
||||
|
@ -130,15 +105,8 @@ uniform vec4 fg_materialParams2[128];
|
|||
uniform mat4 fg_zUpTransform;
|
||||
uniform vec3 fg_modelOffset;
|
||||
|
||||
const float EarthRadius = 5800000.0;
|
||||
const float terminator_width = 200000.0;
|
||||
|
||||
// Testing phase: Why are these in global scope in WS2 shaders?
|
||||
//float alt;
|
||||
float eShade;
|
||||
float yprime_alt;
|
||||
float mie_angle;
|
||||
|
||||
float shadow_func (in float x, in float y, in float noise, in float dist);
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dot_density);
|
||||
float Noise2D(in vec2 coord, in float wavelength);
|
||||
|
@ -277,6 +245,17 @@ void get_material(in int landclass,
|
|||
out vec2 st
|
||||
);
|
||||
|
||||
// Apply the ALS haze model to a specific fragment
|
||||
vec4 applyHaze(inout vec4 fragColor,
|
||||
inout vec3 hazeColor,
|
||||
in vec3 secondary_light,
|
||||
in float ct,
|
||||
in float hazeLayerAltitude,
|
||||
in float visibility,
|
||||
in float avisibility,
|
||||
in float dist,
|
||||
in float lightArg,
|
||||
in float mie_angle);
|
||||
|
||||
// End Test-phase code
|
||||
////////////////////////
|
||||
|
@ -286,13 +265,12 @@ void main()
|
|||
{
|
||||
float alt;
|
||||
|
||||
yprime_alt = light_diffuse_comp.a;
|
||||
float yprime_alt = light_diffuse_comp.a;
|
||||
//diffuse_term.a = 1.0;
|
||||
mie_angle = gl_Color.a;
|
||||
float mie_angle = gl_Color.a;
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
|
||||
// distance to fragment
|
||||
|
||||
float dist = length(relPos);
|
||||
// angle of view vector with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
|
@ -678,8 +656,6 @@ void main()
|
|||
|
||||
if (mix_flag == 1)
|
||||
{
|
||||
|
||||
|
||||
nSum = 0.167 * (noise_4000m + 2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
|
||||
nSum = mix(nSum, 0.5, max(0.0, 2.0 * (transition_model - 0.5)));
|
||||
nSum = nSum + 0.4 * (1.0 -smoothstep(0.9,0.95, abs(steepness)+ 0.05 * (noise_50m - 0.5))) * min(1.0, 2.0 * transition_model);
|
||||
|
@ -701,8 +677,7 @@ void main()
|
|||
texel = mix(texel, detail_texel,mix_factor);
|
||||
}
|
||||
|
||||
// rock for very steep gradients
|
||||
|
||||
// rock for very steep gradients
|
||||
if (gradient_texel.a > 0.0)
|
||||
{
|
||||
texel = mix(texel, gradient_texel, 1.0 - smoothstep(0.75,0.8,abs(steepness)+ 0.00002* msl_altitude + 0.05 * (noise_50m - 0.5)));
|
||||
|
@ -711,7 +686,6 @@ void main()
|
|||
|
||||
|
||||
// strata noise
|
||||
|
||||
float stratnoise_50m;
|
||||
float stratnoise_10m;
|
||||
|
||||
|
@ -726,20 +700,16 @@ void main()
|
|||
}
|
||||
|
||||
// the dot vegetation texture overlay
|
||||
|
||||
texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * (dotnoise_10m + dotnoise_15m) * detail_fade(1.0 * (dot_size * (1.0 +0.1*dot_size)), view_angle,dist));
|
||||
texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * dotnoise_2m * detail_fade(0.1 * dot_size, view_angle,dist));
|
||||
|
||||
// then the grain texture overlay
|
||||
|
||||
|
||||
texel.rgb = mix(texel.rgb, grain_texel.rgb, grain_strength * grain_texel.a * (1.0 - mix_factor) * (1.0-smoothstep(2000.0,5000.0, dist)));
|
||||
|
||||
// for really hires, add procedural noise overlay
|
||||
texel.rgb = texel.rgb * (1.0 + 0.4 * (noise_01m-0.5) * detail_fade(0.1, view_angle, dist)) ;
|
||||
|
||||
// autumn colors
|
||||
|
||||
// autumn colors
|
||||
float autumn_factor = season * 2.0 * (1.0 - local_autumn_factor) ;
|
||||
|
||||
|
||||
|
@ -767,7 +737,6 @@ void main()
|
|||
// mix dust
|
||||
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor *dust_resistance + 3.0 * dust_cover_factor * dust_resistance *(((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
|
||||
|
||||
|
||||
// mix snow
|
||||
float snow_mix_factor = 0.0;
|
||||
|
||||
|
@ -778,17 +747,12 @@ void main()
|
|||
texel = mix(texel, snow_texel, snow_mix_factor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// get distribution of water when terrain is wet
|
||||
|
||||
float combined_wetness = min(1.0, wetness + intrinsic_wetness);
|
||||
float water_threshold1;
|
||||
float water_threshold2;
|
||||
float water_factor =0.0;
|
||||
|
||||
|
||||
if ((dist < 5000.0) && (combined_wetness>0.0))
|
||||
{
|
||||
water_threshold1 = 1.0-0.5* combined_wetness;
|
||||
|
@ -797,11 +761,8 @@ void main()
|
|||
}
|
||||
|
||||
// darken wet terrain
|
||||
|
||||
texel.rgb = texel.rgb * (1.0 - 0.6 * combined_wetness);
|
||||
|
||||
|
||||
|
||||
// light computations
|
||||
vec4 light_specular = gl_LightSource[0].specular;
|
||||
|
||||
|
@ -851,32 +812,26 @@ void main()
|
|||
|
||||
vec3 secondary_light = vec3 (0.0,0.0,0.0);
|
||||
|
||||
if (use_searchlight == 1)
|
||||
{
|
||||
if (use_searchlight == 1) {
|
||||
secondary_light += searchlight();
|
||||
}
|
||||
if (use_landing_light == 1)
|
||||
{
|
||||
|
||||
if (use_landing_light == 1) {
|
||||
secondary_light += landing_light(landing_light1_offset, landing_light3_offset);
|
||||
}
|
||||
if (use_alt_landing_light == 1)
|
||||
{
|
||||
|
||||
if (use_alt_landing_light == 1) {
|
||||
secondary_light += landing_light(landing_light2_offset, landing_light3_offset);
|
||||
}
|
||||
color.rgb +=secondary_light * light_distance_fading(dist);
|
||||
|
||||
|
||||
color.rgb += secondary_light * light_distance_fading(dist);
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
|
||||
|
||||
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
|
@ -884,184 +839,18 @@ void main()
|
|||
|
||||
// Rayleigh color shift due to in-scattering
|
||||
|
||||
float rShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt + 420000.0);
|
||||
//float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade;
|
||||
float lightIntensity = length(hazeColor * effective_scattering) * 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);
|
||||
float rShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt + 420000.0);
|
||||
//float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade;
|
||||
float lightIntensity = length(hazeColor * effective_scattering) * 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);
|
||||
|
||||
|
||||
// here comes the terrain haze model
|
||||
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
|
||||
float mvisibility = min(visibility,avisibility);
|
||||
|
||||
if (dist > 0.04 * mvisibility)
|
||||
{
|
||||
alt = eye_alt;
|
||||
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
if (delta_z > 0.0) // we're inside the layer
|
||||
{
|
||||
if (ct < 0.0) // we look down
|
||||
{
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,mvisibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
else // we may look through upper layer edge
|
||||
{
|
||||
H = dist * ct;
|
||||
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
|
||||
else {distance_in_layer = dist;}
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
// blur of the haze layer edge
|
||||
|
||||
float blur_thickness = 50.0;
|
||||
float cphi = dot(vec3(0.0, 1.0, 0.0), relPos)/dist;
|
||||
float ctlayer = delta_z/dist-0.01 + 0.02 * Noise2D(vec2(cphi,1.0),0.1) -0.01;
|
||||
float ctblur = 0.035 ;
|
||||
|
||||
float blur_dist;
|
||||
|
||||
if (abs(delta_z) < 400.0)
|
||||
{
|
||||
blur_dist = dist * (1.0-smoothstep(0.0,300.0,-delta_z)) * smoothstep(-400.0,-200.0, -delta_z);
|
||||
blur_dist = blur_dist * smoothstep(ctlayer-4.0*ctblur, ctlayer-ctblur, ct) * (1.0-smoothstep(ctlayer+0.5*ctblur, ctlayer+ctblur, ct));
|
||||
distance_in_layer = max(distance_in_layer, blur_dist);
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
|
||||
float eqColorFactor;
|
||||
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering);
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 - effective_scattering);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
// Mie-like factor
|
||||
|
||||
if (lightArg < 10.0)
|
||||
{
|
||||
intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
intensity = length(hazeColor);
|
||||
|
||||
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
|
||||
{
|
||||
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
|
||||
// blue hue of haze
|
||||
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
|
||||
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
float shadow = mix( min(1.0 + dot(n,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
}
|
||||
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
|
||||
hazeColor.rgb *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
// finally, mix fog in
|
||||
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
{
|
||||
transmission = 1.0 - (transmission/1000000.0);
|
||||
}
|
||||
|
||||
|
||||
fragColor.rgb = mix(hazeColor+secondary_light * fog_backscatter(mvisibility) , fragColor.rgb,transmission);
|
||||
|
||||
} // end if (dist > 0.04 * mvisibility)
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
|
||||
|
||||
gl_FragColor = applyHaze(fragColor, hazeColor, secondary_light, ct, hazeLayerAltitude, visibility, avisibility, dist, lightArg, mie_angle);
|
||||
|
||||
// Testing phase controls:
|
||||
if (remove_haze_and_lighting == 1)
|
||||
{
|
||||
gl_FragColor = texel;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -184,6 +184,18 @@ void get_material(in int landclass,
|
|||
out vec2 st
|
||||
);
|
||||
|
||||
// Apply the ALS haze model to a specific fragment
|
||||
vec4 applyHaze(inout vec4 fragColor,
|
||||
inout vec3 hazeColor,
|
||||
in vec3 secondary_light,
|
||||
in float ct,
|
||||
in float hazeLayerAltitude,
|
||||
in float visibility,
|
||||
in float avisibility,
|
||||
in float dist,
|
||||
in float lightArg,
|
||||
in float mie_angle);
|
||||
|
||||
// End Test-phase code
|
||||
////////////////////////
|
||||
|
||||
|
@ -299,155 +311,14 @@ void main()
|
|||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
|
||||
|
||||
// here comes the terrain haze model
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
float dist = length(relPos);
|
||||
|
||||
float mvisibility = min(visibility,avisibility);
|
||||
|
||||
if (dist > 0.04 * mvisibility)
|
||||
{
|
||||
|
||||
alt = eye_alt;
|
||||
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
// angle with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
if (delta_z > 0.0) // we're inside the layer
|
||||
{
|
||||
if (ct < 0.0) // we look down
|
||||
{
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,mvisibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
else // we may look through upper layer edge
|
||||
{
|
||||
H = dist * ct;
|
||||
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
|
||||
else {distance_in_layer = dist;}
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
|
||||
float eqColorFactor;
|
||||
|
||||
|
||||
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/visibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -effective_scattering);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -effective_scattering);
|
||||
}
|
||||
|
||||
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;}
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
// Mie-like factor
|
||||
if (lightArg < 10.0)
|
||||
{intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
|
||||
// blue hue of haze
|
||||
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
|
||||
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
//intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
|
||||
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
// determine the right mix of transmission and haze
|
||||
|
||||
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
{
|
||||
transmission = 1.0 - (transmission/1000000.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
fragColor.rgb = mix(hazeColor, fragColor.rgb,transmission);
|
||||
}
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
|
||||
gl_FragColor = applyHaze(fragColor, hazeColor, vec3(0.0), ct, hazeLayerAltitude, visibility, avisibility, dist, lightArg, mie_angle);
|
||||
|
||||
|
||||
// Testing phase controls:
|
||||
|
|
|
@ -232,8 +232,10 @@ else // the faster, full-day version without lightfields
|
|||
vec4 constant_term = gl_LightModel.ambient + light_ambient;
|
||||
// Another hack for supporting two-sided lighting without using
|
||||
// gl_FrontFacing in the fragment shader.
|
||||
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
|
||||
gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
|
||||
gl_FrontColor.rgb = constant_term.rgb;
|
||||
gl_BackColor.rgb = constant_term.rgb;
|
||||
gl_FrontColor.a = mie_angle;
|
||||
gl_BackColor.a = mie_angle;
|
||||
|
||||
setupShadows(ecPosition);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue