diff --git a/Effects/skydome.eff b/Effects/skydome.eff
index 5d1267ea0..f1d2fb625 100644
--- a/Effects/skydome.eff
+++ b/Effects/skydome.eff
@@ -4,16 +4,17 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -56,52 +57,57 @@
density
float
-
+
overcast
float
-
+
saturation
float
-
+
scattering
float
-
+
visibility
float
-
+
hazeLayerAltitude
float
-
+
terminator
float
-
+
avisibility
float
-
+
terrain_alt
float
-
+
cloud_self_shading
float
+
+ horizon_roughness
+ float
+
+
diff --git a/Shaders/skydome.frag b/Shaders/skydome.frag
index a229890bd..5e7178548 100644
--- a/Shaders/skydome.frag
+++ b/Shaders/skydome.frag
@@ -2,27 +2,28 @@
// Atmospheric scattering shader for flightgear
// Written by Lauri Peltonen (Zan)
-// Implementation of O'Neil's algorithm
+// Implementation of O'Neil's algorithm
// Ground haze layer added by Thorsten Renk
varying vec3 rayleigh;
varying vec3 mie;
-varying vec3 eye;
-varying vec3 hazeColor;
-varying float ct;
-//varying float cosphi;
-varying float delta_z;
-varying float alt;
+varying vec3 eye;
+varying vec3 hazeColor;
+varying float ct;
+varying float cphi;
+varying float delta_z;
+varying float alt;
varying float earthShade;
-
-uniform float overcast;
-uniform float saturation;
-uniform float visibility;
-uniform float avisibility;
-uniform float scattering;
-uniform float cloud_self_shading;
-
-const float EarthRadius = 5800000.0;
+
+uniform float overcast;
+uniform float saturation;
+uniform float visibility;
+uniform float avisibility;
+uniform float scattering;
+uniform float cloud_self_shading;
+uniform float horizon_roughness;
+
+const float EarthRadius = 5800000.0;
float miePhase(in float cosTheta, in float g)
{
@@ -41,172 +42,215 @@ float rayleighPhase(in float cosTheta)
return 1.5 * (2.0 + 0.5*cosTheta*cosTheta);
}
+float rand2D(in vec2 co){
+ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+}
+
+float simple_interpolate(in float a, in float b, in float x)
+{
+return a + smoothstep(0.0,1.0,x) * (b-a);
+}
+
+float interpolatedNoise2D(in float x, in float y)
+{
+ float integer_x = x - fract(x);
+ float fractional_x = x - integer_x;
+
+ float integer_y = y - fract(y);
+ float fractional_y = y - integer_y;
+
+ float v1 = rand2D(vec2(integer_x, integer_y));
+ float v2 = rand2D(vec2(integer_x+1.0, integer_y));
+ float v3 = rand2D(vec2(integer_x, integer_y+1.0));
+ float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
+
+ float i1 = simple_interpolate(v1 , v2 , fractional_x);
+ float i2 = simple_interpolate(v3 , v4 , fractional_x);
+
+ return simple_interpolate(i1 , i2 , fractional_y);
+}
+float Noise2D(in vec2 coord, in float wavelength)
+{
+return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
+
+}
void main()
-{
-
+{
+
vec3 shadedFogColor = vec3(0.65, 0.67, 0.78);
float cosTheta = dot(normalize(eye), gl_LightSource[0].position.xyz);
-
- // position of the horizon line
-
- float lAltitude = alt + delta_z;
- float radiusEye = EarthRadius + alt;
- float radiusLayer = EarthRadius + lAltitude;
- float cthorizon;
- float ctterrain;
-
- if (radiusEye > radiusLayer) cthorizon = -sqrt(radiusEye * radiusEye - radiusLayer * radiusLayer)/radiusEye;
- else cthorizon = sqrt(radiusLayer * radiusLayer - radiusEye * radiusEye)/radiusLayer;
-
- ctterrain = -sqrt(radiusEye * radiusEye - EarthRadius * EarthRadius)/radiusEye;
+
+ // position of the horizon line
+
+ float lAltitude = alt + delta_z;
+ float radiusEye = EarthRadius + alt;
+ float radiusLayer = EarthRadius + lAltitude;
+ float cthorizon;
+ float ctterrain;
+
+ if (radiusEye > radiusLayer) cthorizon = -sqrt(radiusEye * radiusEye - radiusLayer * radiusLayer)/radiusEye;
+ else cthorizon = sqrt(radiusLayer * radiusLayer - radiusEye * radiusEye)/radiusLayer;
+
+ ctterrain = -sqrt(radiusEye * radiusEye - EarthRadius * EarthRadius)/radiusEye;
vec3 color = rayleigh * rayleighPhase(cosTheta);
color += mie * miePhase(cosTheta, -0.8);
-
- vec3 black = vec3(0.0,0.0,0.0);
-
-
- float ovc = overcast;
-
-
-
- float sat = 1.0 - ((1.0 - saturation) * 2.0);
- if (sat < 0.3) sat = 0.3;
-
-
- // float wscale = 1.732;
-
-// an overexposure filter, the log() seems to be pretty expensive though
-
-// if (color.x > 0.8) color.x = 0.8 + 0.8* log(color.x/0.8);
-// if (color.y > 0.8) color.y = 0.8 + 0.8* log(color.y/0.8);
-// if (color.z > 0.8) color.z = 0.8 + 0.8* log(color.z/0.8);
-
-
-// a different exposure filter
-//color.x = 1.0 - exp(-1.3 * color.x);
-//color.y = 1.0 - exp(-1.3 * color.y);
-//color.z = 1.0 - exp(-1.3 * color.z);
-
-if (color.r > 0.58) color.r = 1.0 - exp(-1.5 * color.r);
-if (color.g > 0.58) color.g = 1.0 - exp(-1.5 * color.g);
-if (color.b > 0.58) color.b = 1.0 - exp(-1.5 * color.b);
-
-// reduce the whiteout near the horizon generated by the single scattering approximation
-
-//if (ct > cthorizon) color = mix(color, black ,smoothstep(0.2+cthorizon, -0.2+cthorizon, ct));
-//else color = mix (color, black, smoothstep(0.2+cthorizon,-0.2+cthorizon, cthorizon));
-
-
-
-
-// fog computations for a ground haze layer, extending from zero to lAltitude
-
-
-
-float transmission;
-float vAltitude;
-float delta_zv;
-
-float costheta = ct;
-
-float vis = min(visibility, avisibility);
-
-// hack - in an effect volume the visibility only may be reduced, so we take care here
-//if (avisibility < visibility){vis = avisibility;}
-
- if (delta_z > 0.0) // we're inside the layer
- {
- if (costheta>0.0 + ctterrain) // looking up, view ray intersecting upper layer edge
- {
- transmission = exp(-min((delta_z/max(costheta,0.1)),25000.0)/vis);
- //transmission = 1.0;
- vAltitude = min(vis * costheta, delta_z);
- delta_zv = delta_z - vAltitude;
- }
-
- else // looking down, view range intersecting terrain (which may not be drawn)
- {
- transmission = exp(alt/vis/costheta);
- vAltitude = min(-vis * costheta, alt);
- delta_zv = delta_z + vAltitude;
- }
- }
- else // we see the layer from above
- {
- if (costheta < 0.0 + cthorizon)
- {
- transmission = exp(-min(lAltitude/abs(costheta),25000.0)/vis);
- transmission = transmission * exp(-alt/avisibility/abs(costheta));
- transmission = 1.0 - (1.0 - transmission) * smoothstep(0+cthorizon, -0.02+cthorizon, costheta);
- vAltitude = min(lAltitude, -vis * costheta);
- delta_zv = vAltitude;
- }
- else
- {
- transmission = 1.0;
- delta_zv = 0.0;
- }
- }
-
-// combined intensity reduction by cloud shading and fog self-shading, corrected for Weber-Fechner perception law
-
-//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(avisibility, 1.5 * avisibility, -alt/costheta);
-
-float eqColorFactor = 1.0 - 0.1 * delta_zv/vis - (1.0 - min(scattering,cloud_self_shading));
-
-
-// there's always residual intensity, we should never be driven to zero
-if (eqColorFactor < 0.2) eqColorFactor = 0.2;
-
-
-// postprocessing of haze color
-vec3 hColor = hazeColor;
-
-
-// high altitude desaturation
-float intensity = length(hColor);
-hColor = intensity * normalize (mix(hColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
-
-// blue hue
-hColor.x = 0.83 * hColor.x;
-hColor.y = 0.9 * hColor.y;
-
-
-
-// further blueshift when in shadow, either cloud shadow, or self-shadow or Earth shadow, dependent on indirect
-// light
-
-float fade_out = max(0.65 - 0.3 *overcast, 0.45);
-intensity = length(hColor);
-vec3 oColor = hColor;
-oColor = intensity * normalize(mix(oColor, shadedFogColor, (smoothstep(0.1,1.0,ovc))));
-color = ovc * mix(color, oColor * earthShade ,smoothstep(-0.1+ctterrain, 0.0+ctterrain, ct)) + (1-ovc) * color;
-hColor = intensity * normalize(mix(hColor, 1.5 * shadedFogColor, 1.0 -smoothstep(0.25, fade_out,earthShade) ));
-hColor = intensity * normalize(mix(hColor, shadedFogColor, (1.0 - smoothstep(0.5,0.9,eqColorFactor))));
-//hColor = intensity * normalize(mix(hColor, shadedFogColor, (1.0 - smoothstep(0.5,0.9,cloud_self_shading)) ));
-hColor = hColor * earthShade;
-
-// accounting for overcast and saturation
-
-
-
-color = sat * color + (1.0 - sat) * mix(color, black, smoothstep(0.4+cthorizon,0.2+cthorizon,ct));
-
-
-// the terrain below the horizon gets drawn in one optical thickness
-vec3 terrainHazeColor = eqColorFactor * hColor;
-color = mix(color, terrainHazeColor ,smoothstep(0.01 + ctterrain, 0.0+ctterrain, ct));
-
-// mix fog the skydome with the right amount of haze
-
-color = transmission * color + (1.0-transmission) * eqColorFactor * hColor;
-
+
+ vec3 black = vec3(0.0,0.0,0.0);
+
+
+ float ovc = overcast;
+
+
+
+ float sat = 1.0 - ((1.0 - saturation) * 2.0);
+ if (sat < 0.3) sat = 0.3;
+
+
+ // float wscale = 1.732;
+
+// an overexposure filter, the log() seems to be pretty expensive though
+
+// if (color.x > 0.8) color.x = 0.8 + 0.8* log(color.x/0.8);
+// if (color.y > 0.8) color.y = 0.8 + 0.8* log(color.y/0.8);
+// if (color.z > 0.8) color.z = 0.8 + 0.8* log(color.z/0.8);
+
+
+// a different exposure filter
+//color.x = 1.0 - exp(-1.3 * color.x);
+//color.y = 1.0 - exp(-1.3 * color.y);
+//color.z = 1.0 - exp(-1.3 * color.z);
+
+if (color.r > 0.58) color.r = 1.0 - exp(-1.5 * color.r);
+if (color.g > 0.58) color.g = 1.0 - exp(-1.5 * color.g);
+if (color.b > 0.58) color.b = 1.0 - exp(-1.5 * color.b);
+
+// reduce the whiteout near the horizon generated by the single scattering approximation
+
+//if (ct > cthorizon) color = mix(color, black ,smoothstep(0.2+cthorizon, -0.2+cthorizon, ct));
+//else color = mix (color, black, smoothstep(0.2+cthorizon,-0.2+cthorizon, cthorizon));
+
+
+
+
+// fog computations for a ground haze layer, extending from zero to lAltitude
+
+
+
+float transmission;
+float vAltitude;
+float delta_zv;
+
+float costheta = ct;
+
+float vis = min(visibility, avisibility);
+
+// hack - in an effect volume the visibility only may be reduced, so we take care here
+//if (avisibility < visibility){vis = avisibility;}
+
+ if (delta_z > 0.0) // we're inside the layer
+ {
+ if (costheta>0.0 + ctterrain) // looking up, view ray intersecting upper layer edge
+ {
+ transmission = exp(-min((delta_z/max(costheta,0.1)),25000.0)/vis);
+ //transmission = 1.0;
+ vAltitude = min(vis * costheta, delta_z);
+ delta_zv = delta_z - vAltitude;
+ }
+
+ else // looking down, view range intersecting terrain (which may not be drawn)
+ {
+ transmission = exp(alt/vis/costheta);
+ vAltitude = min(-vis * costheta, alt);
+ delta_zv = delta_z + vAltitude;
+ }
+ }
+ else // we see the layer from above
+ {
+ if (costheta < 0.0 + cthorizon)
+ {
+ transmission = exp(-min(lAltitude/abs(costheta),25000.0)/vis);
+ transmission = transmission * exp(-alt/avisibility/abs(costheta));
+ transmission = 1.0 - (1.0 - transmission) * smoothstep(0+cthorizon, -0.02+cthorizon, costheta);
+ vAltitude = min(lAltitude, -vis * costheta);
+ delta_zv = vAltitude;
+ }
+ else
+ {
+ transmission = 1.0;
+ delta_zv = 0.0;
+ }
+ }
+
+// combined intensity reduction by cloud shading and fog self-shading, corrected for Weber-Fechner perception law
+
+//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(avisibility, 1.5 * avisibility, -alt/costheta);
+
+float eqColorFactor = 1.0 - 0.1 * delta_zv/vis - (1.0 - min(scattering,cloud_self_shading));
+
+
+// there's always residual intensity, we should never be driven to zero
+if (eqColorFactor < 0.2) eqColorFactor = 0.2;
+
+
+// postprocessing of haze color
+vec3 hColor = hazeColor;
+
+
+// high altitude desaturation
+float intensity = length(hColor);
+hColor = intensity * normalize (mix(hColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
+
+// blue hue
+hColor.x = 0.83 * hColor.x;
+hColor.y = 0.9 * hColor.y;
+
+
+
+// further blueshift when in shadow, either cloud shadow, or self-shadow or Earth shadow, dependent on indirect
+// light
+
+float fade_out = max(0.65 - 0.3 *overcast, 0.45);
+intensity = length(hColor);
+vec3 oColor = hColor;
+oColor = intensity * normalize(mix(oColor, shadedFogColor, (smoothstep(0.1,1.0,ovc))));
+color = ovc * mix(color, oColor * earthShade ,smoothstep(-0.1+ctterrain, 0.0+ctterrain, ct)) + (1-ovc) * color;
+hColor = intensity * normalize(mix(hColor, 1.5 * shadedFogColor, 1.0 -smoothstep(0.25, fade_out,earthShade) ));
+hColor = intensity * normalize(mix(hColor, shadedFogColor, (1.0 - smoothstep(0.5,0.9,eqColorFactor))));
+//hColor = intensity * normalize(mix(hColor, shadedFogColor, (1.0 - smoothstep(0.5,0.9,cloud_self_shading)) ));
+hColor = hColor * earthShade;
+
+// accounting for overcast and saturation
+
+
+
+color = sat * color + (1.0 - sat) * mix(color, black, smoothstep(0.4+cthorizon,0.2+cthorizon,ct));
+
+
+// the terrain below the horizon gets drawn in one optical thickness
+vec3 terrainHazeColor = eqColorFactor * hColor;
+
+// determine a visibility-dependent angle for how smoothly the haze blends over the skydome
+
+float hazeBlendAngle = max(0.01,1000.0/avisibility + 0.3 * (1.0 - smoothstep(5000.0, 30000.0, avisibility)));
+float altFactor = smoothstep(-300.0, 0.0, delta_z);
+float altFactor2 = 0.2 + 0.8 * smoothstep(-3000.0, 0.0, delta_z);
+hazeBlendAngle = hazeBlendAngle + 0.1 * altFactor;
+hazeBlendAngle = hazeBlendAngle + (1.0-horizon_roughness) * altFactor2 * 0.1 * Noise2D(vec2(0.0,cphi), 0.3);
+
+
+color = mix(color, terrainHazeColor ,smoothstep(hazeBlendAngle + ctterrain, 0.0+ctterrain, ct));
+
+
+// mix fog the skydome with the right amount of haze
+
+color = transmission * color + (1.0-transmission) * eqColorFactor * hColor;
+
gl_FragColor = vec4(color, 1.0);
- gl_FragDepth = 0.1;
+ gl_FragDepth = 0.1;
}
diff --git a/Shaders/skydome.vert b/Shaders/skydome.vert
index 43673a5c8..5d083844c 100644
--- a/Shaders/skydome.vert
+++ b/Shaders/skydome.vert
@@ -6,29 +6,29 @@
uniform mat4 osg_ViewMatrix;
-uniform mat4 osg_ViewMatrixInverse;
-uniform float hazeLayerAltitude;
-uniform float terminator;
-uniform float avisibility;
+uniform mat4 osg_ViewMatrixInverse;
+uniform float hazeLayerAltitude;
+uniform float terminator;
+uniform float avisibility;
uniform float visibility;
-uniform float terrain_alt;
+uniform float terrain_alt;
varying vec3 rayleigh;
varying vec3 mie;
-varying vec3 eye;
-varying vec3 hazeColor;
-varying float ct;
-//varying float cosphi;
-varying float delta_z;
-varying float alt;
-varying float earthShade;
+varying vec3 eye;
+varying vec3 hazeColor;
+varying float ct;
+varying float cphi;
+varying float delta_z;
+varying float alt;
+varying float earthShade;
// Dome parameters from FG and screen
const float domeSize = 80000.0;
const float realDomeSize = 100000.0;
const float groundRadius = 0.984503332 * domeSize;
const float altitudeScale = domeSize - groundRadius;
-const float EarthRadius = 5800000.0;
+const float EarthRadius = 5800000.0;
// Dome parameters when calculating scattering
// Assuming dome size is 5.0
@@ -43,25 +43,25 @@ const float fSamples = float(nSamples);
uniform float rK = 0.0003; //0.00015;
uniform float mK = 0.003; //0.0025;
uniform float density = 0.5; //1.0
-//vec3 rayleighK = rK * vec3(5.602, 7.222, 19.644);
+//vec3 rayleighK = rK * vec3(5.602, 7.222, 19.644);
vec3 rayleighK = rK * vec3(4.5, 8.62, 17.3);
vec3 mieK = vec3(mK);
vec3 sunIntensity = 10.0*vec3(120.0, 125.0, 130.0);
-
-// light_func is a generalized logistic function fit to the light intensity as a function
-// of scaled terminator position obtained from Flightgear core
-
-float light_func (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));
-}
-
+
+// light_func is a generalized logistic function fit to the light intensity as a function
+// of scaled terminator position obtained from Flightgear core
+
+float light_func (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));
+}
+
// Find intersections of ray to skydome
// ray must be normalized
@@ -76,8 +76,8 @@ float intersection (in float cheight, in vec3 ray, in float rad2)
// Return the scale function at height = 0 for different thetas
float outscatterscale(in float costheta)
-{
-
+{
+
float x = 1.0 - costheta;
@@ -115,11 +115,11 @@ void main()
// Make it so that 0.0 is ground level and 1.0 is 100km (space) level
float altitude = distance(groundPoint, vec4(0.0, 0.0, 0.0, 1.0));
float scaledAltitude = altitude / realDomeSize;
-
- // the local horizon angle
- float radiusEye = EarthRadius + altitude;
- float ctterrain = -sqrt(radiusEye * radiusEye - EarthRadius * EarthRadius)/radiusEye;
-
+
+ // the local horizon angle
+ float radiusEye = EarthRadius + altitude;
+ float ctterrain = -sqrt(radiusEye * radiusEye - EarthRadius * EarthRadius)/radiusEye;
+
// Camera's position, z is up!
float cameraRealAltitude = groundLevel + heightScale*scaledAltitude;
@@ -133,7 +133,7 @@ void main()
// We are in space, calculate correct positiondelta!
relativePosition -= space * normalize(relativePosition);
}
-
+
vec3 positionDelta = relativePosition / fSamples;
float deltaLength = length(positionDelta); // Should multiply by something?
@@ -147,20 +147,20 @@ void main()
// If sample is above camera, reverse ray direction
if(positionDelta.z < 0.0) cameraCosTheta = -positionDelta.z / deltaLength;
else cameraCosTheta = positionDelta.z / deltaLength;
-
-
- float cameraCosTheta1 = -positionDelta.z / deltaLength;
-
+
+
+ float cameraCosTheta1 = -positionDelta.z / deltaLength;
+
// Total attenuation from camera to skydome
float totalCameraScatter = outscatter(cameraCosTheta, scaledAltitude);
// Do numerical integration of scattering function from skydome to camera
- vec3 color = vec3(0.0);
-
- // no scattering integrations where terrain is later drawn
- if (cameraCosTheta1 > (ctterrain-0.05))
+ vec3 color = vec3(0.0);
+
+ // no scattering integrations where terrain is later drawn
+ if (cameraCosTheta1 > (ctterrain-0.05))
{
for(int i = 0; i < nSamples; i++)
{
@@ -179,7 +179,7 @@ void main()
// Again, reverse the direction if vertex is over the camera
float cameraScatter;
if(relativePosition.z < 0.0) { // Vertex is over the camera
- cameraCosTheta = -dot(normalize(positionDelta), normalize(sample));
+ cameraCosTheta = -dot(normalize(positionDelta), normalize(sample));
cameraScatter = totalCameraScatter - outscatter(cameraCosTheta, sampleAltitude);
} else { // Vertex is below camera
@@ -196,13 +196,13 @@ void main()
sample += positionDelta;
}
}
- color *= sunIntensity;
+ color *= sunIntensity;
ct = cameraCosTheta1;
rayleigh = rayleighK * color;
mie = mieK * color;
eye = gl_NormalMatrix * positionDelta;
-
-
+
+
// We need to move the camera so that the dome appears to be centered around earth
// to make the dome render correctly!
float moveDown = -altitude; // Center dome on camera
@@ -210,82 +210,65 @@ void main()
moveDown += scaledAltitude * altitudeScale; // And move correctly according to altitude
// Vertex transformed correctly so that at 100km we are at space border
- vec4 finalVertex = realVertex - vec4(0.0, 0.0, 1.0, 0.0) * moveDown;
-
- // prepare some stuff for a ground haze layer
-
- delta_z = hazeLayerAltitude - altitude;
- alt = altitude;
-
-
- // establish coordinates relative to sun position
- vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
- vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
- vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0) );
-
-
- vec3 relVector = normalize(finalVertex.xyz - ep.xyz);
-
- // and compute the twilight shading
-
-
- // yprime is the coordinate from/towards terminator
- float yprime;
-
- if (alt > hazeLayerAltitude) // we're looking from above and can see far
- {
- if (ct < 0.0)
- {
- yprime = -dot(relVector,lightHorizon) * altitude/-ct;//(ct-0.001);
- yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
- }
- else // the only haze we see looking up is overcast, assume its altitude
- {
- yprime = -dot(relVector,lightHorizon) * avisibility;
- yprime = yprime -sqrt(2.0 * EarthRadius * 10000.0);
- }
- }
- else
- {yprime = -dot(relVector,lightHorizon) * avisibility;
- yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
- }
-
- if (terminator > 1000000.0){yprime = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);}
-
- //float edgeAlt = max(hazeLayerAltitude - (alt-terrain_alt)/avisibility * visibility, terrain_alt);
-
- //yprime = yprime -sqrt(2.0 * EarthRadius * edgeAlt);
-
- float terminator_width = 200000.0;
- earthShade = 0.9 * smoothstep((terminator_width+ terminator), (-terminator_width + terminator), yprime) + 0.1;
-
-
-//hazeColor = vec3 (gl_LightSource[0].diffuse.x, gl_LightSource[0].diffuse.y, gl_LightSource[0].diffuse.z);
-
- //hazeColor.x = hazeColor.x * 0.83;
- //hazeColor.y = hazeColor.y * 0.9;
-
- float lightArg = (terminator-yprime)/100000.0;
- vec4 light_diffuse;
- light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
- light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
- light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
- light_diffuse.a = 0.0;
- hazeColor = light_diffuse.xyz;
-
- float intensity = length(hazeColor.xyz);
- float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator -sqrt(2.0 * EarthRadius * terrain_alt));
- float mie_angle = (0.5 * dot(normalize(relVector), normalize(lightFull)) ) + 0.5;
- 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 - would be best here this causes a box-like bug for some reason
-// so it moved to the fragment shader where it has no issues
-
-//float intensity = length(hazeColor.xyz);
-//hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.8* smoothstep(5000.0, 50000.0, alt)));
-
-
+ vec4 finalVertex = realVertex - vec4(0.0, 0.0, 1.0, 0.0) * moveDown;
+
+ // prepare some stuff for a ground haze layer
+
+ delta_z = hazeLayerAltitude - altitude;
+ alt = altitude;
+
+
+ // establish coordinates relative to sun position
+ vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
+ vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
+ vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0) );
+
+
+ vec3 relVector = normalize(finalVertex.xyz - ep.xyz);
+
+ // and compute the twilight shading
+
+
+ // yprime is the coordinate from/towards terminator
+ float yprime;
+
+ if (alt > hazeLayerAltitude) // we're looking from above and can see far
+ {
+ if (ct < 0.0)
+ {
+ yprime = -dot(relVector,lightHorizon) * altitude/-ct;//(ct-0.001);
+ yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
+ }
+ else // the only haze we see looking up is overcast, assume its altitude
+ {
+ yprime = -dot(relVector,lightHorizon) * avisibility;
+ yprime = yprime -sqrt(2.0 * EarthRadius * 10000.0);
+ }
+ }
+ else
+ {yprime = -dot(relVector,lightHorizon) * avisibility;
+ yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
+ }
+
+ if (terminator > 1000000.0){yprime = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);}
+
+ float terminator_width = 200000.0;
+ earthShade = 0.9 * smoothstep((terminator_width+ terminator), (-terminator_width + terminator), yprime) + 0.1;
+
+ float lightArg = (terminator-yprime)/100000.0;
+ vec4 light_diffuse;
+ light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
+ light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
+ light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
+ light_diffuse.a = 0.0;
+ hazeColor = light_diffuse.xyz;
+
+ float intensity = length(hazeColor.xyz);
+ float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator -sqrt(2.0 * EarthRadius * terrain_alt));
+ cphi = dot(normalize(relVector), normalize(lightHorizon));
+ float mie_angle = (0.5 * dot(normalize(relVector), normalize(lightFull)) ) + 0.5;
+ 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)) );
+
// Transform
gl_Position = gl_ModelViewProjectionMatrix * finalVertex;