diff --git a/Effects/bowwave.eff b/Effects/bowwave.eff index 9facbc888..2c2148a06 100644 --- a/Effects/bowwave.eff +++ b/Effects/bowwave.eff @@ -109,14 +109,443 @@ /rendering/scene/scattering + + /environment/surface/scattering + /environment/terminator-relative-position-m + + /environment/mean-terrain-elevation-m + + + /rendering/scene/overcast + + + /sim/rendering/eye-altitude-m + + + /environment/cloud-self-shading + + + /environment/moonlight + /sim/rendering/shaders/skydome + + /sim/rendering/shaders/landmass + + + + /environment/sea/color_r + + + /environment/sea/color_g + + + /environment/sea/color_b + + + + + + /sim/rendering/shaders/skydome + /sim/rendering/shaders/quality-level + /sim/rendering/shaders/water + + 2.0 + /sim/rendering/shaders/water + + + + 2.0 + + + + GL_ARB_shader_objects + GL_ARB_shading_language_100 + GL_ARB_vertex_shader + GL_ARB_fragment_shader + + + + + + true + + + material/active + + + material/ambient + + + material/diffuse + + + material/specular + + + material/emissive + + + material/shininess + + + material/color-mode + + + + + blend/active + + + blend/source + + + blend/destination + + + + shade-model + + + cull-face + + + rendering-hint + + + 0 + + texture[0]/image + + + texture[0]/filter + + + texture[0]/wrap-s + + + texture[0]/wrap-t + + + texture[0]/internal-format + + + + 1 + noise + + + 2 + + texture[2]/image + + + texture[2]/filter + + + texture[2]/wrap-s + + + texture[2]/wrap-t + + + texture[2]/internal-format + + + + 3 + + texture[3]/image + + + texture[3]/filter + + + texture[3]/wrap-s + + + texture[3]/wrap-t + + + texture[3]/internal-format + + + + 4 + + texture[4]/image + + + texture[4]/filter + + + texture[4]/wrap-s + + + texture[4]/wrap-t + + + texture[4]/internal-format + + + + 5 + + texture[5]/image + + + texture[5]/filter + + + texture[5]/wrap-s + + + texture[5]/wrap-t + + + texture[5]/internal-format + + + + 6 + + texture[6]/image + + + texture[6]/filter + + + texture[6]/wrap-s + + + texture[6]/wrap-t + + + texture[6]/internal-format + + + + 7 + + texture[7]/image + + + texture[7]/filter + + + texture[7]/wrap-s + + + texture[7]/wrap-t + + + texture[7]/internal-format + + + + + + Shaders/wake_lightfield.vert + + Shaders/bowwave_lightfield.frag + + + water_reflection + sampler-2d + 0 + + + water_normalmap + sampler-2d + 2 + + + water_dudvmap + sampler-2d + 3 + + + water_reflection_grey + sampler-2d + 4 + + + sea_foam + sampler-2d + 5 + + + alpha_tex + sampler-2d + 6 + + + bowwave_nmap + sampler-2d + 7 + + + saturation + float + + + saturation + + + + Status + int + + status + + + + + Overcast + float + + overcast + + + + WindE + float + + windE + + + + WindN + float + + windN + + + + spd + float + speed-kt + + + hdg + float + + heading-deg + + + + Noise + sampler-3d + 1 + + + + + visibility + float + + visibility + + + + avisibility + float + + avisibility + + + + hazeLayerAltitude + float + + lthickness + + + + scattering + float + + scattering + + + + ground_scattering + float + + ground_scattering + + + + terminator + float + + terminator + + + + terrain_alt + float + + terrain_alt + + + + overcast + float + + overcast + + + + eye_alt + float + + eye_alt + + + + cloud_self_shading + float + cloud_self_shading + + + + + sea_r + float + + sea_r + + + + sea_g + float + + sea_g + + + + sea_b + float + + sea_b + + + + quality_level + int + quality_level + + + + + diff --git a/Shaders/bowwave_lightfield.frag b/Shaders/bowwave_lightfield.frag new file mode 100644 index 000000000..1337a8ec0 --- /dev/null +++ b/Shaders/bowwave_lightfield.frag @@ -0,0 +1,469 @@ +// This shader is mostly an adaptation of the shader found at +// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion +// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10 +// © Michael Horsch - 2005 +// Major update and revisions - 2011-10-07 +// © Emilian Huminiuc and Vivian Meazza +// Optimisation - 2012-5-05 +// © Emilian Huminiuc and Vivian Meazza +// Ported to the Atmospheric Light Scattering Framework +// by Thorsten Renk, Aug. 2013 + +#version 120 +#define fps2kts 0.5925 + +uniform sampler2D water_normalmap; +uniform sampler2D water_reflection; +uniform sampler2D water_dudvmap; +uniform sampler2D water_reflection_grey; +uniform sampler2D sea_foam; +uniform sampler2D alpha_tex; +uniform sampler2D bowwave_nmap; + +uniform float saturation, Overcast, WindE, WindN, spd, hdg; +uniform float CloudCover0, CloudCover1, CloudCover2, CloudCover3, CloudCover4; +uniform int Status; + +uniform float hazeLayerAltitude; +uniform float terminator; +uniform float terrain_alt; +uniform float avisibility; +uniform float visibility; +uniform float overcast; +uniform float scattering; +uniform float ground_scattering; +uniform float cloud_self_shading; +uniform float eye_alt; +uniform float fogstructure; +uniform float ice_cover; +uniform float sea_r; +uniform float sea_g; +uniform float sea_b; + +uniform int quality_level; + + +varying vec4 waterTex1; //moving texcoords +varying vec4 waterTex2; //moving texcoords +varying vec3 viewerdir; +varying vec3 lightdir; +varying vec3 normal; +varying vec3 relPos; +varying float earthShade; +varying float yprime_alt; +varying float mie_angle; +varying float steepness; + +vec3 specular_light; + +const float terminator_width = 200000.0; +const float EarthRadius = 5800000.0; + +////fog "include" ///// +uniform int fogType; + +vec3 fog_Func(vec3 color, int type); +////////////////////// + +/////// functions ///////// + +float normalize_range(float _val) + { + if (_val > 180.0) + return _val - 360.0; + else + return _val; + } + + +void relWind(out float rel_wind_speed_kts, out float rel_wind_from_rad) + { + //calculate the carrier speed north and east in kts + float speed_north_kts = cos(radians(hdg)) * spd ; + float speed_east_kts = sin(radians(hdg)) * spd ; + + //calculate the relative wind speed north and east in kts + float rel_wind_speed_from_east_kts = WindE*fps2kts + speed_east_kts; + float rel_wind_speed_from_north_kts = WindN*fps2kts + speed_north_kts; + + //combine relative speeds north and east to get relative windspeed in kts + rel_wind_speed_kts = sqrt(rel_wind_speed_from_east_kts*rel_wind_speed_from_east_kts + + rel_wind_speed_from_north_kts*rel_wind_speed_from_north_kts); + + //calculate the relative wind direction + float rel_wind_from_deg = degrees(atan(rel_wind_speed_from_east_kts, rel_wind_speed_from_north_kts)); + // rel_wind_from_rad = atan(rel_wind_speed_from_east_kts, rel_wind_speed_from_north_kts); + float rel_wind = rel_wind_from_deg - hdg; + rel_wind = normalize_range(rel_wind); + rel_wind_from_rad = radians(rel_wind); + } + +void rotationmatrix(in float angle, out mat4 rotmat) + { + rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0, + sin( angle ), cos( angle ), 0.0, 0.0, + 0.0 , 0.0 , 1.0, 0.0, + 0.0 , 0.0 , 0.0, 1.0 ); + } + + +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)); +} + +// 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; // 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) + { + const vec4 sca = vec4(0.005, 0.005, 0.005, 0.005); + const vec4 sca2 = vec4(0.02, 0.02, 0.02, 0.02); + const vec4 tscale = vec4(0.25, 0.25, 0.25, 0.25); + + mat4 RotationMatrix; + + float relWindspd=0; + float relWinddir=0; + + float dist = length(relPos); + vec3 shadedFogColor = vec3(0.65, 0.67, 0.78); + float effective_scattering = min(scattering, cloud_self_shading); + + // compute relative wind speed and direction + relWind (relWindspd, relWinddir); + + rotationmatrix(relWinddir, RotationMatrix); + + // compute direction to viewer + vec3 E = normalize(viewerdir); + + // compute direction to light source + vec3 L = normalize(lightdir); + + // half vector + vec3 H = normalize(L + E); + + const float water_shininess = 240.0; + // approximate cloud cover + float cover = 0.0; + //bool Status = true; + + float windEffect = relWindspd; //wind speed in kt + // float windEffect = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.6; //wind speed in kt + float windScale = 15.0/(5.0 + windEffect); //wave scale + float waveRoughness = 0.05 + smoothstep(0.0, 50.0, windEffect); //wave roughness filter + + + if (Status == 1){ + cover = min(min(min(min(CloudCover0, CloudCover1),CloudCover2),CloudCover3),CloudCover4); + } else { + // hack to allow for Overcast not to be set by Local Weather + + if (Overcast == 0){ + cover = 5; + } else { + cover = Overcast * 5; + } + + } + + //vec4 viewt = normalize(waterTex4); + vec4 viewt = vec4(-E, 0.0) * 0.6; + + vec4 disdis = texture2D(water_dudvmap, vec2(waterTex2 * tscale)* windScale * 2.0) * 2.0 - 1.0; + vec4 dist1 = texture2D(water_dudvmap, vec2(waterTex1 + disdis*sca2)* windScale * 2.0) * 2.0 - 1.0; + vec4 fdist = normalize(dist1); + fdist = -fdist; + fdist *= sca; + + //normalmap + rotationmatrix(-relWinddir, RotationMatrix); + + vec4 nmap0 = texture2D(water_normalmap, vec2((waterTex1 + disdis*sca2) * RotationMatrix ) * windScale * 2.0) * 2.0 - 1.0; + vec4 nmap2 = texture2D(water_normalmap, vec2(waterTex2 * tscale * RotationMatrix ) * windScale * 2.0) * 2.0 - 1.0; + vec4 nmap3 = texture2D(bowwave_nmap, gl_TexCoord[0].st) * 2.0 - 1.0; + vec4 vNorm = normalize(mix(nmap3, nmap0 + nmap2, 0.3 )* waveRoughness); + vNorm = -vNorm; + + //load reflection + vec4 tmp = vec4(lightdir, 0.0); + vec4 refTex = texture2D(water_reflection, vec2(tmp + waterTex1) * 32.0) ; + vec4 refTexGrey = texture2D(water_reflection_grey, vec2(tmp + waterTex1) * 32.0) ; + vec4 refl ; + // cover = 0; + + /*if(cover >= 1.5){ + refl= normalize(refTex); + } + else + { + refl = normalize(refTexGrey); + refl.r *= (0.75 + 0.15 * cover); + refl.g *= (0.80 + 0.15 * cover); + refl.b *= (0.875 + 0.125 * cover); + refl.a *= 1.0; + } + */ + + refl.r = sea_r; + refl.g = sea_g; + refl.b = sea_b; + refl.a = 1.0; + + + float intensity; + // de-saturate for reduced light + refl.rgb = mix(refl.rgb, vec3 (0.248, 0.248, 0.248), 1.0 - smoothstep(0.1, 0.8, ground_scattering)); + + // de-saturate light for overcast haze + intensity = length(refl.rgb); + refl.rgb = mix(refl.rgb, intensity * vec3 (1.0, 1.0, 1.0), 0.5 * smoothstep(0.1, 0.9, overcast)); + + vec3 N0 = vec3(texture2D(water_normalmap, vec2((waterTex1 + disdis*sca2)* RotationMatrix) * windScale * 2.0) * 2.0 - 1.0); + vec3 N1 = vec3(texture2D(water_normalmap, vec2(waterTex2 * tscale * RotationMatrix ) * windScale * 2.0) * 2.0 - 1.0); + vec3 N2 = vec3(texture2D(bowwave_nmap, gl_TexCoord[0].st)*2.0-1.0); + //vec3 Nf = normalize((normal+N0+N1)*waveRoughness); + vec3 N = normalize(mix(normal+N2, normal+N0+N1, 0.3)* waveRoughness); + N = -N; + + // specular + + specular_light = gl_Color.rgb; + + vec3 specular_color = vec3(specular_light) + * pow(max(0.0, dot(N, H)), water_shininess) * 6.0; + vec4 specular = vec4(specular_color, 0.5); + + specular = specular * saturation * 0.3; + + //calculate fresnel + vec4 invfres = vec4( dot(vNorm, viewt) ); + vec4 fres = vec4(1.0) + invfres; + refl *= fres; + + vec4 alpha0 = texture2D(alpha_tex, gl_TexCoord[0].st); + + //calculate final colour + vec4 ambient_light; + ambient_light.rgb = max(specular_light.rgb, vec3(0.1, 0.1, 0.1)); + ambient_light.a = 1.0; + vec4 finalColor; + + finalColor = refl + specular * smoothstep(0.3, 0.6, ground_scattering); + + // cover = 0; + + /*if(cover >= 1.5){ + finalColor = refl + specular; + } else { + finalColor = refl; + }*/ + + //add foam + + float foamSlope = 0.05 + 0.01 * windScale; + //float waveSlope = mix(N0.g, N1.g, 0.25); + + vec4 foam_texel = texture2D(sea_foam, vec2(waterTex2 * tscale) * 50.0); + float waveSlope = N.g; + + if (windEffect >= 12.0) + if (waveSlope >= foamSlope){ + finalColor = mix(finalColor, max(finalColor, finalColor + foam_texel), smoothstep(foamSlope, 0.5, N.g)); + } + + //generate final colour + finalColor *= ambient_light+ alpha0 * 0.35; + + + +float delta_z = hazeLayerAltitude - eye_alt; + + +if (dist > 40.0) +{ + + +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,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 )); + } + 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 )); + } + 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); + +// 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; +hazeColor.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0); +hazeColor.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0); +hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0); + +// now dim the light for haze +float eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1; + +// 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); + + +if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly + { + 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)))); + } + + + + finalColor.rgb = mix(eqColorFactor * hazeColor * eShade, finalColor.rgb,transmission); + + + } + + + //finalColor.rgb = fog_Func(finalColor.rgb, fogType); + gl_FragColor = vec4(finalColor.rgb, alpha0.a * 1.35); + //gl_FragColor = finalColor; + + } diff --git a/Shaders/wake_lightfield.vert b/Shaders/wake_lightfield.vert new file mode 100644 index 000000000..8e2cddbb5 --- /dev/null +++ b/Shaders/wake_lightfield.vert @@ -0,0 +1,232 @@ +// This shader is mostly an adaptation of the shader found at +// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion +// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10 +// © Michael Horsch - 2005 +// Major update and revisions - 2011-10-07 +// © Emilian Huminiuc and Vivian Meazza +// Optimisation - 2012-5-05 +// © Emilian Huminiuc and Vivian Meazza +// Ported to the Atmospheric Light Scattering Framework +// by Thorsten Renk, Aug. 2013 + +#version 120 +#define fps2kts 0.5925 + +varying vec4 waterTex1; +varying vec4 waterTex2; +varying vec3 relPos; +varying vec3 rawPos; +varying vec3 viewerdir; +varying vec3 lightdir; +varying vec3 normal; + +varying float steepness; +varying float earthShade; +varying float yprime_alt; +varying float mie_angle; + +uniform float osg_SimulationTime; +uniform float WindE, WindN, spd, hdg; +uniform float hazeLayerAltitude; +uniform float terminator; +uniform float terrain_alt; +uniform float avisibility; +uniform float visibility; +uniform float overcast; +uniform float ground_scattering; + +uniform mat4 osg_ViewMatrixInverse; + +vec3 specular_light; + +// This is the value used in the skydome scattering shader - use the same here for consistency? +const float EarthRadius = 5800000.0; +const float terminator_width = 200000.0; + +///////////////////////// + + +/////// functions ///////// + +void relWind(out float rel_wind_speed_kts, float rel_wind_from_deg) +{ + //calculate the carrier speed north and east in kts + float speed_north_kts = cos(radians(hdg)) * spd ; + float speed_east_kts = sin(radians(hdg)) * spd ; + + //calculate the relative wind speed north and east in kts + float rel_wind_speed_from_east_kts = WindE*fps2kts + speed_east_kts; + float rel_wind_speed_from_north_kts = WindN*fps2kts + speed_north_kts; + + //combine relative speeds north and east to get relative windspeed in kts + rel_wind_speed_kts = sqrt((rel_wind_speed_from_east_kts * rel_wind_speed_from_east_kts) + (rel_wind_speed_from_north_kts * rel_wind_speed_from_north_kts)); + + //calculate the relative wind direction + rel_wind_from_deg = degrees(atan(rel_wind_speed_from_east_kts, rel_wind_speed_from_north_kts)); +} + +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 < -15.0) {return 0.0;} + +return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d)); +} + + + +void main(void) +{ + + float relWindspd=0; + float relWinddir=0; + //compute relative wind speed and direction + relWind (relWindspd, relWinddir); + + vec3 N = normalize(gl_Normal); + normal = N; + + viewerdir = vec3(gl_ModelViewMatrixInverse[3]) - vec3(gl_Vertex); + lightdir = normalize(vec3(gl_ModelViewMatrixInverse * gl_LightSource[0].position)); + + vec3 shadedFogColor = vec3(0.65, 0.67, 0.78); + rawPos = (osg_ViewMatrixInverse *gl_ModelViewMatrix * gl_Vertex).xyz; + + vec4 t1 = vec4(osg_SimulationTime*0.005217, 0.0, 0.0, 0.0); + vec4 t2 = vec4(osg_SimulationTime*-0.0012, 0.0, 0.0, 0.0); + + float windFactor = -relWindspd * 0.1; +// float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.6; + + waterTex1 = gl_MultiTexCoord0 + t1 * windFactor; + waterTex2 = gl_MultiTexCoord0 + t2 * windFactor; + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_Position = ftransform(); + + // here start computations for the haze layer + + + float yprime; + float lightArg; + float intensity; + float vertex_alt; + float scattering; + + // we need several geometrical quantities + + // first current altitude of eye position in model space + vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0); + + // and relative position to vector + relPos = gl_Vertex.xyz - ep.xyz; + + + // unfortunately, we need the distance in the vertex shader, although the more accurate version + // is later computed in the fragment shader again + float dist = length(relPos); + + +// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m + vertex_alt = max(gl_Vertex.z,100.0); + scattering = 0.5 + 0.5 * ground_scattering + 0.5* (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt); + + // branch dependent on daytime + +if (terminator < 1000000.0) // the full, sunrise and sunset computation +{ + + + // establish coordinates relative to sun position + vec3 lightHorizon = normalize(vec3(lightdir.x,lightdir.y, 0.0)); + + // yprime is the distance of the vertex into sun direction + yprime = -dot(relPos, lightHorizon); + + // this gets an altitude correction, higher terrain gets to see the sun earlier + yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt); + + // two times terminator width governs how quickly light fades into shadow + // now the light-dimming factor + earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4; + + // parametrized version of the Flightgear ground lighting function + lightArg = (terminator-yprime_alt)/100000.0; + + specular_light.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0); + specular_light.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0); + specular_light.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0); + + specular_light = max(specular_light * scattering, vec3 (0.05, 0.05, 0.05)); + + intensity = length(specular_light.rgb); + specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.6,ground_scattering) )); + + // correct ambient light intensity and hue before sunrise - seems unnecessary and create artefacts though... + //if (earthShade < 0.5) + //{ + //specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.7,earthShade) )); + //} + + // directional scattering for low sun + if (lightArg < 10.0) + {mie_angle = (0.5 * dot(normalize(relPos), lightdir) ) + 0.5;} + else + {mie_angle = 1.0;} + + + + + +// the haze gets the light at the altitude of the haze top if the vertex in view is below +// but the light at the vertex if the vertex is above + +vertex_alt = max(vertex_alt,hazeLayerAltitude); + +if (vertex_alt > hazeLayerAltitude) + { + if (dist > 0.8 * avisibility) + { + vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist)); + yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt); + } + } +else + { + vertex_alt = hazeLayerAltitude; + yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt); + } + +} + +else // the faster, full-day version without lightfields + +{ + //vertex_alt = max(gl_Vertex.z,100.0); + + earthShade = 1.0; + mie_angle = 1.0; + + if (terminator > 3000000.0) + {specular_light = vec3 (1.0, 1.0, 1.0);} + else + { + + lightArg = (terminator/100000.0 - 10.0)/20.0; + specular_light.b = 0.78 + lightArg * 0.21; + specular_light.g = 0.907 + lightArg * 0.091; + specular_light.r = 0.904 + lightArg * 0.092; + } + + specular_light = specular_light * scattering; + + yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude); + +} + +gl_FrontColor.rgb = specular_light; +gl_BackColor.rgb = gl_FrontColor.rgb; + +}