diff --git a/Effects/cloud.eff b/Effects/cloud.eff index ae8a04c7f..33c0842dc 100644 --- a/Effects/cloud.eff +++ b/Effects/cloud.eff @@ -29,6 +29,189 @@ /sim/startup/ysize + + + + /sim/rendering/shaders/skydome + + 1.0 + + + + 1.0 + /sim/rendering/shaders/clouds + + + + + + true + + 0.5 0.5 0.5 1.0 + 0.5 0.5 0.5 1.0 + off + + + greater + 0.01 + + smooth + + src-alpha + one-minus-src-alpha + + + false + + + 10 + DepthSortedBin + + + 0 + 2d + texture[0]/image + clamp + clamp + + + Shaders/3dcloud-ALS-detailed.vert + Shaders/3dcloud-ALS-detailed.frag + Shaders/filters-ALS.frag + Shaders/noise.frag + + usrAttr1 + 10 + + + usrAttr2 + 11 + + + + baseTexture + sampler-2d + 0 + + + range + float + range + + + detail_range + float + detail + + + scattering + float + scattering + + + terminator + float + terminator + + + altitude + float + altitude + + + cloud_self_shading + float + cloud_self_shading + + + moonlight + float + moonlight + + + air_pollution + float + air_pollution + + + visibility + float + visibility + + + flash + float + flash + + + lightning_pos_x + float + lightning-pos-x + + + lightning_pos_y + float + lightning-pos-y + + + lightning_range + float + lightning-range + + + gamma + float + gamma + + + brightness + float + brightness + + + use_filtering + bool + use_filtering + + + use_night_vision + bool + use_night_vision + + + use_IR_vision + bool + use_IR_vision + + + delta_T + float + delta_T + + + fact_grey + float + fact_grey + + + fact_black + float + fact_black + + + display_xsize + int + display_xsize + + + display_ysize + int + display_ysize + + + + + diff --git a/Shaders/3dcloud-ALS-detailed.frag b/Shaders/3dcloud-ALS-detailed.frag new file mode 100644 index 000000000..61c627d7f --- /dev/null +++ b/Shaders/3dcloud-ALS-detailed.frag @@ -0,0 +1,84 @@ +#version 120 + +uniform sampler2D baseTexture; +uniform float scattering; + +varying float fogFactor; +varying float mie_frag; +varying float mie_frag_mod; +varying float z_pos; +varying float bottom_shade; + +varying vec3 internal_pos; +varying vec3 hazeColor; + +vec3 filter_combined (in vec3 color) ; + +void main(void) +{ + vec4 base = texture2D( baseTexture, gl_TexCoord[0].st); + if (base.a < 0.02) + discard; + + float mie_factor = 0.0; + float geo_factor = 1.0; + + float mie_sign = 1.0; + if (mie_frag < 0.0) {mie_sign = -1.0;} + + if (mie_sign > 0.0) + {mie_factor = smoothstep(0.8, 1.0, mie_frag);} + else + {mie_factor = -1.0 * (1.0 - smoothstep(-1.0, -0.8, mie_frag));} + + mie_factor *= mie_frag_mod; + + // suppress effect in cloud center + + float z_bias = 0.2 * (1.0 - smoothstep(2.0, 3.0, z_pos)); + + geo_factor *= smoothstep(-0.9 - z_bias, -0.4 - z_bias, internal_pos.x) * (1.0 -smoothstep(0.4 + z_bias, 0.9 + z_bias, internal_pos.x)); + geo_factor *= smoothstep(-0.9 - z_bias, -0.4 - z_bias, internal_pos.y) * (1.0 -smoothstep(0.4 + z_bias, 0.9 + z_bias, internal_pos.y)); + geo_factor *= smoothstep(0, 0.3, internal_pos.z) * (1.0 - smoothstep(0.5, 1.2, internal_pos.z)); + + if (mie_sign > 0.0) + { + mie_factor *=(1.0 -geo_factor); + } + + float transparency = smoothstep(0.0, 0.7, base.a); + float opacity = smoothstep(0.7, 1.0, base.a); + + float inverse_mie = 0.0; + + if ((opacity == 0.0) && (mie_sign > 0.0)) // Mie forward scattering enhancing light + {mie_factor *= (1.0 - pow(transparency, 2.0));} + else if ((opacity == 0.0) && (mie_sign < 0.0)) // Mie forward scattering reducing reflected light + { + inverse_mie = (1.0 - pow(transparency, 2.0)) * smoothstep(0.65, 0.8, scattering); + inverse_mie *= (1.0 - smoothstep(-1.0, -0.5, mie_frag)); + } + else if (mie_sign > 0.0) // bulk light absorption + {mie_factor *= - 4.0 * pow(opacity, 2.0);} + + + // darken the bulk of the away-facing cloud + + float bulk_shade_factor = (1.0 - 0.6 * geo_factor * smoothstep(0.5, 1.0, mie_frag)); + bulk_shade_factor -= 0.3 * smoothstep(0.5, 1.0, mie_frag) * (1.0 - mie_frag_mod) * (1.0 - smoothstep(0.4, 0.5, bottom_shade)); + + + float mie_enhancement = 1.0 + clamp(mie_factor, 0.0, 1.0); + mie_enhancement = mie_enhancement * bulk_shade_factor; + + vec4 finalColor = base * gl_Color; + finalColor.rgb *= mie_enhancement * (1.0 - 0.4 * inverse_mie); + finalColor.rgb = max(finalColor.rgb, gl_Color.rgb * 1.2 * bottom_shade); + + finalColor.rgb = mix(hazeColor, finalColor.rgb, fogFactor ); + finalColor.rgb = filter_combined(finalColor.rgb); + + + gl_FragColor.rgb = finalColor.rgb; + gl_FragColor.a = mix(0.0, finalColor.a, 1.0 - 0.5 * (1.0 - fogFactor)); +} diff --git a/Shaders/3dcloud-ALS-detailed.vert b/Shaders/3dcloud-ALS-detailed.vert new file mode 100644 index 000000000..946d06023 --- /dev/null +++ b/Shaders/3dcloud-ALS-detailed.vert @@ -0,0 +1,293 @@ +// -*-C++-*- +#version 120 + +varying float fogFactor; +varying vec3 hazeColor; +varying float mie_frag; +varying float mie_frag_mod; +varying vec3 internal_pos; +varying float bottom_shade; +varying float z_pos; + +uniform float range; // From /sim/rendering/clouds3d-vis-range +uniform float detail_range; // From /sim/rendering/clouds3d_detail-range +uniform float scattering; +uniform float terminator; +uniform float altitude; +uniform float cloud_self_shading; +uniform float visibility; +uniform float moonlight; +uniform float air_pollution; +uniform float flash; +uniform float lightning_pos_x; +uniform float lightning_pos_y; +uniform float lightning_range; + +attribute vec3 usrAttr1; +attribute vec3 usrAttr2; + +float alpha_factor = usrAttr1.r; +float shade_factor = usrAttr1.g; +float cloud_height = usrAttr1.b; +float bottom_factor = usrAttr2.r; +float middle_factor = usrAttr2.g; +float top_factor = usrAttr2.b; + +const float EarthRadius = 5800000.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.03;} + + +return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d)); +} + + +float mie_func (in float x, in float Mie) +{ +return x + 2.0 * x * Mie * (1.0 -0.8*x) * (1.0 -0.8*x); +} + +void main(void) +{ + + + //shade_factor = shade_factor * cloud_self_shading; + //top_factor = top_factor * cloud_self_shading; + //shade_factor = min(shade_factor, top_factor); + //middle_factor = min(middle_factor, top_factor); + //bottom_factor = min(bottom_factor, top_factor); + + float intensity; + float mix_factor; + + bottom_shade = bottom_factor; + + vec3 shadedFogColor = vec3(0.55, 0.67, 0.88); + vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight * scattering; + gl_TexCoord[0] = gl_MultiTexCoord0; + vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0); + vec4 l = gl_ModelViewMatrixInverse * vec4(0.0,0.0,1.0,1.0); + vec3 u = normalize(ep.xyz - l.xyz); + + // Find a rotation matrix that rotates 1,0,0 into u. u, r and w are + // the columns of that matrix. + vec3 absu = abs(u); + vec3 r = normalize(vec3(-u.y, u.x, 0.0)); + vec3 w = cross(u, r); + + // Do the matrix multiplication by [ u r w pos]. Assume no + // scaling in the homogeneous component of pos. + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + gl_Position.xyz = gl_Vertex.x * u; + gl_Position.xyz += gl_Vertex.y * r; + gl_Position.xyz += gl_Vertex.z * w; + // Apply Z scaling to allow sprites to be squashed in the z-axis + gl_Position.z = gl_Position.z * gl_Color.w; + + // Now shift the sprite to the correct position in the cloud. + gl_Position.xyz += gl_Color.xyz; + + internal_pos = gl_Position.xyz/ cloud_height; + + + // Determine a lighting normal based on the vertex position from the + // center of the cloud, so that sprite on the opposite side of the cloud to the sun are darker. + float n = dot(normalize(-gl_LightSource[0].position.xyz), + normalize(vec3(gl_ModelViewMatrix * vec4(- gl_Position.x, - gl_Position.y, - gl_Position.z, 0.0)))); + + // prepare suppression of shadeward Mie terms + float n1 = dot(normalize(-gl_LightSource[0].position.xyz), + normalize(vec3(gl_ModelViewMatrix * vec4(- gl_Color.x, - gl_Color.y, - gl_Color.z, 0.0)))); + + //z_pos = dot(normalize(-gl_LightSource[0].position.xyz), + // vec3(gl_ModelViewMatrix * vec4(- gl_Position.x, - gl_Position.y, - gl_Position.z, 0.0)))/cloud_height; + + + float mie_suppress = smoothstep(0.0, 0.3, n1); + + // Determine the position - used for fog and shading calculations + float fogCoord = length(vec3(gl_ModelViewMatrix * vec4(gl_Color.x, gl_Color.y, gl_Color.z, 1.0))); + float center_dist = length(vec3(gl_ModelViewMatrix * vec4(0.0,0.0,0.0,1.0))); + + z_pos = (fogCoord - center_dist)/cloud_height; + + if ((fogCoord > detail_range) && (fogCoord > center_dist) && (shade_factor < 0.7)) { + // More than detail_range away, so discard all sprites on opposite side of + // cloud center by shifting them beyond the view fustrum + gl_Position = vec4(0.0,0.0,10.0,1.0); + gl_FrontColor.a = 0.0; + } else { + + // Determine the shading of the vertex. We shade it based on it's position + // in the cloud relative to the sun, and it's vertical position in the cloud. + float shade = mix(shade_factor, top_factor, smoothstep(-0.3, 0.3, n)); + //if (n < 0) { + // shade = mix(top_factor, shade_factor, abs(n)); + //} + + if (gl_Position.z < 0.5 * cloud_height) { + shade = min(shade, mix(bottom_factor, middle_factor, gl_Position.z * 2.0 / cloud_height)); + } else { + shade = min(shade, mix(middle_factor, top_factor, gl_Position.z * 2.0 / cloud_height - 1.0)); + } + + //float h = gl_Position.z / cloud_height; + //if (h < 0.5) { + // shade = min(shade, mix(bottom_factor, middle_factor, smoothstep(0.0, 0.5, h))); + //} else { + // shade = min(shade, mix(middle_factor, top_factor, smoothstep(2.0 * (h - 0.5))); + // } + + // Final position of the sprite + vec3 relVector = gl_Position.xyz - ep.xyz; + gl_Position = gl_ModelViewProjectionMatrix * gl_Position; + + + // Light at the final position + + // first obtain normal to sun position + + vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz; + vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0)); + + + + // yprime is the distance of the vertex into sun direction, corrected for altitude + // the altitude correction is clamped to reasonable values, sometimes altitude isn't parsed correctly, leading + // to overbright or overdark clouds + // float vertex_alt = clamp(altitude * 0.30480 + relVector.z,1000.0,10000.0); + float vertex_alt = clamp(altitude + relVector.z, 300.0, 10000.0); + float yprime = -dot(relVector, lightHorizon); + float yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt); + + // two times terminator width governs how quickly light fades into shadow + float terminator_width = 200000.0; + float earthShade = 1.0- 0.9* smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt); + float earthShadeFactor = 1.0 - smoothstep(0.4, 0.5, earthShade); + + // compute the light at the position + vec4 light_diffuse; + + float lightArg = (terminator-yprime_alt)/100000.0; + + light_diffuse.b = light_func(lightArg -1.2 * air_pollution, 1.330e-05, 0.264, 2.227, 1.08e-05, 1.0); + light_diffuse.g = light_func(lightArg -0.6 * air_pollution, 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 = 1.0; + + //light_diffuse *= cloud_self_shading; + intensity = (1.0 - (0.8 * (1.0 - earthShade))) * length(light_diffuse.rgb); + light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, (1.0 - smoothstep(0.5,0.9, min(scattering, cloud_self_shading) )))); + + // correct ambient light intensity and hue before sunrise + if (earthShade < 0.6) + { + light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.6,earthShade ) )); + + } + + + + gl_FrontColor.rgb = intensity * shade * normalize(mix(light_diffuse.rgb, shadedFogColor, smoothstep(0.1,0.4, (1.0 - shade) ))) ; + + // lightning + vec2 lightningRelVector = relVector.xy - vec2(lightning_pos_x, lightning_pos_y); + float rCoord = length(lightningRelVector); + + vec3 flash_color = vec3 (0.43, 0.57, 1.0); + float flash_factor = flash; + + if (flash == 2) + { + flash_color = vec3 (0.8, 0.7, 0.4); + flash_factor = 1; + } + + float rn = 0.5 + 0.5 * fract(gl_Color.x); + gl_FrontColor.rgb += flash_factor * flash_color * (1.0 - smoothstep(lightning_range, 5.0 * lightning_range, rCoord)) * rn; + + + // fading of cloudlets + + if ((fogCoord > (0.9 * detail_range)) && (fogCoord > center_dist) && (shade_factor < 0.7)) { + // cloudlet is almost at the detail range, so fade it out. + gl_FrontColor.a = 1.0 - smoothstep(0.9 * detail_range, detail_range, fogCoord); + } else { + // As we get within 100m of the sprite, it is faded out. Equally at large distances it also fades out. + gl_FrontColor.a = min(smoothstep(10.0, 100.0, fogCoord), 1.0 - smoothstep(0.9 * range, range, fogCoord)); + } + gl_FrontColor.a = gl_FrontColor.a * (1.0 - smoothstep(visibility, 3.0* visibility, fogCoord)); + + fogFactor = exp(-fogCoord/visibility); + + // haze of ground haze shader is slightly bluish + hazeColor = light_diffuse.rgb; + hazeColor.r = hazeColor.r * 0.83; + hazeColor.g = hazeColor.g * 0.9; + hazeColor = hazeColor * scattering; + + + // Mie correction + float Mie = 0.0; + float MieFactor = dot(normalize(lightFull), normalize(relVector)); + + + mie_frag = MieFactor; + mie_frag_mod = mie_suppress * (1.0 - smoothstep(0.4, 0.6, bottom_factor)) * (1.0 - smoothstep(detail_range, 1.5 * detail_range, fogCoord)) * smoothstep(0.65, 0.8, scattering) + * smoothstep(0.7, 1.0, top_factor); + + + if (bottom_factor < 0.4) {mie_frag_mod = 0.0;} + + if (bottom_factor > 0.4) + { + MieFactor = dot(normalize(lightFull), normalize(relVector)); + Mie = 1.5 * smoothstep(0.9,1.0, MieFactor) * smoothstep(0.6, 0.8, bottom_factor) * (1.0-earthShadeFactor) ; + //if (MieFactor < 0.0) {Mie = - Mie;} + } + //else {Mie = 0.0;} + + if (Mie > 0.0) + { + hazeColor.r = mie_func(hazeColor.r, Mie); + hazeColor.g = mie_func(hazeColor.g, 0.8* Mie); + hazeColor.b = mie_func(hazeColor.b, 0.5* Mie); + + gl_FrontColor.r = mie_func(gl_FrontColor.r, Mie); + gl_FrontColor.g = mie_func(gl_FrontColor.g, 0.8* Mie); + gl_FrontColor.b = mie_func(gl_FrontColor.b, 0.5*Mie); + } + else if (MieFactor < 0.0) + { + float thickness_reduction = smoothstep(0.4, 0.8, bottom_factor) ; + float light_reduction = dot (lightFull, lightHorizon); + light_reduction *= light_reduction; + + float factor_b = 0.8 + 0.2 * (1.0 - smoothstep(0.0, 0.7, -MieFactor) * thickness_reduction * light_reduction) ; + float factor_r = 0.6 + 0.4 * (1.0 - smoothstep(0.0, 0.7, -MieFactor) * thickness_reduction * light_reduction) ; + float factor_g = 0.65 + 0.35 * (1.0 - smoothstep(0.0, 0.7, -MieFactor) * thickness_reduction * light_reduction) ; + hazeColor.r *= factor_r; + hazeColor.g *= factor_g; + hazeColor.b *= factor_b; + + gl_FrontColor.r *= factor_r; + gl_FrontColor.g *= factor_g; + gl_FrontColor.b *= factor_b; + } + + gl_FrontColor.rgb = gl_FrontColor.rgb + moonLightColor * earthShadeFactor; + hazeColor.rgb = hazeColor.rgb + moonLightColor * earthShadeFactor; + gl_FrontColor.a = gl_FrontColor.a * alpha_factor; + gl_BackColor = gl_FrontColor; + } +} diff --git a/defaults.xml b/defaults.xml index 40e436971..d40f7d2f5 100644 --- a/defaults.xml +++ b/defaults.xml @@ -128,6 +128,7 @@ Started September 2000 by David Megginson, david@megginson.com 8 false + 0.0 1.0 1.0 1.0 diff --git a/gui/dialogs/shaders-lightfield.xml b/gui/dialogs/shaders-lightfield.xml index edc13c1a4..58f7ae83f 100644 --- a/gui/dialogs/shaders-lightfield.xml +++ b/gui/dialogs/shaders-lightfield.xml @@ -45,6 +45,32 @@ + + hbox + right + + + left + + + + cloud + 0.0 + 1.0 + 1.0 + 0.17 + true + /sim/rendering/shaders/clouds + + dialog-apply + cloud + + + + 55 + + + hbox right