1// -*-C++-*- 2#version 120 3 4// written by Thorsten Renk, Oct 2011, based on default.frag 5// Ambient term comes in gl_Color.rgb. 6varying vec4 diffuse_term; 7varying vec3 normal; 8varying vec3 relPos; 9 10 11uniform float fg_Fcoef; 12 13uniform sampler2D texture; 14 15 16varying float yprime_alt; 17varying float mie_angle; 18 19varying float flogz; 20 21 22uniform float visibility; 23uniform float avisibility; 24uniform float scattering; 25uniform float terminator; 26uniform float terrain_alt; 27uniform float hazeLayerAltitude; 28uniform float overcast; 29uniform float eye_alt; 30uniform float cloud_self_shading; 31 32const float EarthRadius = 5800000.0; 33const float terminator_width = 200000.0; 34 35float alt; 36float eShade; 37 38float fog_func (in float targ, in float alt); 39vec3 get_hazeColor(in float light_arg); 40vec3 filter_combined (in vec3 color) ; 41 42float getShadowing(); 43 44float luminance(vec3 color) 45{ 46 return dot(vec3(0.212671, 0.715160, 0.072169), color); 47} 48 49 50 51void main() 52{ 53 54 vec3 shadedFogColor = vec3(0.55, 0.67, 0.88); 55// this is taken from default.frag 56 vec3 n; 57 float NdotL, NdotHV, fogFactor; 58 vec4 color = gl_Color; 59 vec3 lightDir = gl_LightSource[0].position.xyz; 60 vec3 halfVector = gl_LightSource[0].halfVector.xyz; 61 vec4 texel; 62 vec4 fragColor; 63 vec4 specular = vec4(0.0); 64 float intensity; 65 66 float effective_scattering = min(scattering, cloud_self_shading); 67 68 69 vec4 light_specular = gl_LightSource[0].specular; 70 71 // If gl_Color.a == 0, this is a back-facing polygon and the 72 // normal should be reversed. 73 n = (2.0 * gl_Color.a - 1.0) * normal; 74 n = normalize(n); 75 76 NdotL = dot(n, lightDir); 77 if (NdotL > 0.0) { 78 float shadowmap = getShadowing(); 79 color += diffuse_term * NdotL * shadowmap; 80 NdotHV = max(dot(n, halfVector), 0.0); 81 if (gl_FrontMaterial.shininess > 0.0) 82 specular.rgb = (gl_FrontMaterial.specular.rgb 83 * light_specular.rgb 84 * pow(NdotHV, gl_FrontMaterial.shininess) 85 * shadowmap); 86 } 87 color.a = diffuse_term.a; 88 // This shouldn't be necessary, but our lighting becomes very 89 // saturated. Clamping the color before modulating by the texture 90 // is closer to what the OpenGL fixed function pipeline does. 91 color = clamp(color, 0.0, 1.0); 92 texel = texture2D(texture, gl_TexCoord[0].st); 93 fragColor = color * texel + specular; 94 95 96 97// here comes the terrain haze model 98 99 100float delta_z = hazeLayerAltitude - eye_alt; 101float dist = length(relPos); 102 103float mvisibility = min(visibility,avisibility); 104 105if (dist > 0.04 * mvisibility) 106{ 107 108alt = eye_alt; 109 110 111float transmission; 112float vAltitude; 113float delta_zv; 114float H; 115float distance_in_layer; 116float transmission_arg; 117 118// angle with horizon 119float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist; 120 121 122// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer 123 124if (delta_z > 0.0) // we're inside the layer 125 { 126 if (ct < 0.0) // we look down 127 { 128 distance_in_layer = dist; 129 vAltitude = min(distance_in_layer,mvisibility) * ct; 130 delta_zv = delta_z - vAltitude; 131 } 132 else // we may look through upper layer edge 133 { 134 H = dist * ct; 135 if (H > delta_z) {distance_in_layer = dist/H * delta_z;} 136 else {distance_in_layer = dist;} 137 vAltitude = min(distance_in_layer,visibility) * ct; 138 delta_zv = delta_z - vAltitude; 139 } 140 } 141 else // we see the layer from above, delta_z < 0.0 142 { 143 H = dist * -ct; 144 if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading 145 { 146 distance_in_layer = 0.0; 147 delta_zv = 0.0; 148 } 149 else 150 { 151 vAltitude = H + delta_z; 152 distance_in_layer = vAltitude/H * dist; 153 vAltitude = min(distance_in_layer,visibility) * (-ct); 154 delta_zv = vAltitude; 155 } 156 } 157 158 159// ground haze cannot be thinner than aloft visibility in the model, 160// so we need to use aloft visibility otherwise 161 162 163transmission_arg = (dist-distance_in_layer)/avisibility; 164 165 166float eqColorFactor; 167 168 169 170if (visibility < avisibility) 171 { 172 transmission_arg = transmission_arg + (distance_in_layer/visibility); 173 // this combines the Weber-Fechner intensity 174 eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -effective_scattering); 175 176 } 177else 178 { 179 transmission_arg = transmission_arg + (distance_in_layer/avisibility); 180 // this combines the Weber-Fechner intensity 181 eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -effective_scattering); 182 } 183 184 185 186transmission = fog_func(transmission_arg, alt); 187 188// there's always residual intensity, we should never be driven to zero 189if (eqColorFactor < 0.2) {eqColorFactor = 0.2;} 190 191 192float lightArg = (terminator-yprime_alt)/100000.0; 193vec3 hazeColor = get_hazeColor(lightArg); 194 195 196 197// now dim the light for haze 198eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt); 199 200// Mie-like factor 201 202if (lightArg < 10.0) 203 {intensity = length(hazeColor); 204 float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt)); 205 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)) ); 206 } 207 208// high altitude desaturation of the haze color 209 210intensity = length(hazeColor); 211hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt))); 212 213// blue hue of haze 214 215hazeColor.x = hazeColor.x * 0.83; 216hazeColor.y = hazeColor.y * 0.9; 217 218 219// additional blue in indirect light 220float fade_out = max(0.65 - 0.3 *overcast, 0.45); 221intensity = length(hazeColor); 222hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) )); 223 224// change haze color to blue hue for strong fogging 225//intensity = length(hazeColor); 226hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor)))); 227 228 229// reduce haze intensity when looking at shaded surfaces, only in terminator region 230 231float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission)); 232hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator)); 233 234 235 236 237// don't let the light fade out too rapidly 238lightArg = (terminator + 200000.0)/100000.0; 239float minLightIntensity = min(0.2,0.16 * lightArg + 0.5); 240vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4); 241hazeColor *= eqColorFactor * eShade; 242hazeColor.rgb = max(hazeColor.rgb, minLight.rgb); 243 244// determine the right mix of transmission and haze 245 246fragColor.rgb = mix(hazeColor, fragColor.rgb,transmission); 247} 248 249fragColor.rgb = filter_combined(fragColor.rgb); 250 251gl_FragColor = fragColor; 252// logarithmic depth 253gl_FragDepth = log2(flogz) * fg_Fcoef * 0.5; 254} 255 256