diff --git a/Effects/surface-lights.eff b/Effects/surface-lights.eff index 601d2d855..13334448a 100644 --- a/Effects/surface-lights.eff +++ b/Effects/surface-lights.eff @@ -8,8 +8,105 @@ clamp clamp + /environment/ground-visibility-m + /environment/visibility-m + /environment/ground-haze-thickness-m + /sim/rendering/eye-altitude-m + + + + + /sim/rendering/point-sprites + /sim/rendering/shaders/skydome + + + 2.0 + + + + GL_ARB_point_sprite + GL_ARB_point_parameters + GL_ARB_shader_objects + GL_ARB_shading_language_100 + GL_ARB_vertex_shader + GL_ARB_fragment_shader + + + + + + + 8 + DepthSortedBin + + false + + src-alpha + one-minus-src-alpha + + + gequal + 0.1 + + directional + + point + point + + + min-size + max-size + size + attenuation + + + 0 + true + texture[0]/type + texture[0]/wrap-s + texture[0]/wrap-t + + + Shaders/surface-light-lightfield.vert + Shaders/surface-light-lightfield.frag + + + size + float + size + + + visibility + float + visibility + + + avisibility + float + avisibility + + + hazeLayerAltitude + float + lthickness + + + eye_alt + float + eye_alt + + + texture + sampler-2d + 0 + + true + + + + diff --git a/Shaders/surface-light-lightfield.frag b/Shaders/surface-light-lightfield.frag new file mode 100644 index 000000000..5db78a578 --- /dev/null +++ b/Shaders/surface-light-lightfield.frag @@ -0,0 +1,120 @@ +// -*-C++-*- + +uniform sampler2D texture; + +uniform float visibility; +uniform float avisibility; +uniform float hazeLayerAltitude; +uniform float eye_alt; + +varying vec3 relPos; +varying float pixelSize; + +float alt; + + +float fog_func (in float targ) +{ + + +float fade_mix; + +// for large altitude > 30 km, we switch to some component of quadratic distance fading to +// create the illusion of improved visibility range + +targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn + + +if (alt < 30000.0) + {return exp(-targ - targ * targ * targ * targ);} +else if (alt < 50000.0) + { + fade_mix = (alt - 30000.0)/20000.0; + return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0)); + } +else + { + return exp(- targ * targ - pow(targ,4.0)); + } + +} + + + +void main() +{ + + float dist = length(relPos); + float delta_z = hazeLayerAltitude - 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,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; + if (visibility < avisibility) + { + transmission_arg = transmission_arg + (distance_in_layer/visibility); + } + else + { + transmission_arg = transmission_arg + (distance_in_layer/avisibility); + } + + + + transmission = fog_func(transmission_arg); + float dist_att = exp(-0.3/pixelSize); + + vec4 texel = texture2D(texture,gl_TexCoord[0].st); + gl_FragColor = vec4 (gl_Color.rgb, texel.a * transmission * dist_att); + + +} diff --git a/Shaders/surface-light-lightfield.vert b/Shaders/surface-light-lightfield.vert new file mode 100644 index 000000000..7762ab9a5 --- /dev/null +++ b/Shaders/surface-light-lightfield.vert @@ -0,0 +1,24 @@ + +// -*-C++-*- + +// Shader that uses OpenGL state values to do per-pixel lighting + +uniform float size; + +varying vec3 relPos; +varying float pixelSize; + + + +void main() +{ + gl_FrontColor= gl_Color; + gl_Position = ftransform(); + + vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0); + relPos = gl_Vertex.xyz - ep.xyz; + float dist = length(relPos); + float lightScale = size * size * size * size * size / 1000.0; + pixelSize = min(size * size/25.0,lightScale/dist); + gl_PointSize = pixelSize; +}