// -*-C++-*- #version 120 #define MAX_LAYERS 8 #define MAX_DISTANCE 3000.0 uniform float visibility; uniform float avisibility; uniform float scattering; uniform float overlay_bias; uniform float season; uniform float dust_cover_factor; uniform float overlay_max_height; uniform float overlay_hardness; uniform float overlay_density; uniform float overlay_scale; uniform float overlay_steepness_factor; uniform float overlay_brightness_bottom; uniform float overlay_brightness_top; uniform float overlay_secondary_hardness; uniform float overlay_secondary_density; uniform float snowlevel; uniform float wetness; uniform float snow_thickness_factor; uniform int overlay_autumn_flag; uniform int overlay_secondary_flag; uniform int cloud_shadow_flag; uniform sampler2D overlayPrimaryTex; uniform sampler2D overlaySecondaryTex; uniform float osg_SimulationTime; varying vec2 g_rawpos; // Horizontal position in model space varying float g_distance_to_eye; // Distance to the camera. Layers were disregarded varying vec3 g_normal; varying in float g_altitude; flat in float g_layer; // The layer where the fragment lives (0-1 range) float rand2D(in vec2 co); float Noise2D(in vec2 co, in float wavelength); vec3 filter_combined (in vec3 color) ; float shadow_func_nearest (in float x, in float y, in float noise, in float dist); void main() { if (g_distance_to_eye > MAX_DISTANCE) {discard;} vec2 texCoord = gl_TexCoord[0].st; vec2 pos_rotated = vec2 (0.707 * g_rawpos.x + 0.707 * g_rawpos.y, 0.707 * g_rawpos.x - 0.707 * g_rawpos.y); //float noise_1m = 0.5 * Noise2D(pos_rotated.xy, 1.0 * overlay_scale); //noise_1m += 0.5 * Noise2D(g_rawpos.xy, 1.1 * overlay_scale); float noise_1m = Noise2D(pos_rotated.xy, 1.0 * overlay_scale); float noise_2m = Noise2D(g_rawpos.xy, 2.0 * overlay_scale); ; float noise_10m = Noise2D(g_rawpos.xy, 10.0 * overlay_scale); float value = 0.0; float d_fade =smoothstep(100.0, MAX_DISTANCE, g_distance_to_eye); float steepness = dot (normalize(g_normal), vec3 (0.0, 0.0, 1.0)); float steepness_bias = smoothstep(overlay_steepness_factor, overlay_steepness_factor + 0.1, steepness); float overlayPattern = 0.2 * noise_10m + 0.3 * noise_2m + 0.5 * noise_1m - 0.2 * g_layer - 0.1 + 0.2 * overlay_density ; overlayPattern *= steepness_bias; float secondaryPattern = 0.2 * (1.0-noise_10m) + 0.3 * (1.0-noise_2m) + 0.5 * (1.0-noise_1m) - 0.4 * g_layer - 0.2 + 0.2 * overlay_secondary_density ; secondaryPattern *= overlay_secondary_flag; float secondaryMix = 0.0; if (overlayPattern > 0.5) { value = smoothstep(0.5, (0.8 - 0.25 * overlay_hardness), overlayPattern); } else if (secondaryPattern > 0.5) { value = smoothstep(0.5, (0.8 - 0.25 * overlay_secondary_hardness), secondaryPattern); secondaryMix = 1.0; } else {discard;} vec3 texel = texture2D(overlayPrimaryTex, texCoord * 20.0).rgb; vec3 secondary_texel = texture2D(overlaySecondaryTex, texCoord * 20.0).rgb; // autumn coloring if (overlay_autumn_flag == 1) { texel.r = min(1.0, (1.0 + 2.5 * 0.1 * season) * texel.r); texel.g = texel.g; texel.b = max(0.0, (1.0 - 4.0 * 0.1 * season) * texel.b); float intensity = length(texel.rgb) * (1.0 - 0.5 * smoothstep(1.1,2.0,season)); texel.rgb = intensity * normalize(mix(texel.rgb, vec3(0.23,0.17,0.08), smoothstep(1.1,2.0, season))); } texel = mix (texel, secondary_texel, secondaryMix); float layer_arg = mix(g_layer, 1.0, smoothstep(250.0, 5000.0, g_distance_to_eye)); texel.rgb *= (overlay_brightness_bottom + (overlay_brightness_top - overlay_brightness_bottom) * g_layer); texel.rgb *= (1.0 - 0.5 * wetness); // dust overlay const vec3 dust_color = vec3 (0.76, 0.65, 0.45); texel = mix (texel, dust_color, 0.7 * dust_cover_factor); // snow overlay //vec3 snow_texel = vec3 (0.95, 0.95, 0.95); float snow_factor = 0.2+0.8* smoothstep(0.2,0.8, 0.3 + 0.5 * snow_thickness_factor +0.0001*(g_altitude -snowlevel) ); snow_factor *= smoothstep(0.5, 0.7, steepness); snow_factor *= smoothstep(g_layer - 0.1, g_layer , snow_factor + 0.2); //texel.rgb = mix(texel.rgb, snow_texel.rgb, snow_factor * smoothstep(snowlevel, snowlevel+200.0, g_altitude - 100.0)); value *= (1.0 - snow_factor * smoothstep(snowlevel, snowlevel+200.0, g_altitude - 100.0)); // do a conservative simple fog model, fading to alpha float min_visibility = min(visibility, avisibility); float base_alpha = clamp(0.4 * overlay_max_height/0.3, 0.4, 1.0); value*= base_alpha * (1.0 - d_fade); float targ = 8.0 * g_distance_to_eye/min_visibility; value *= exp(-targ - targ * targ * targ * targ); value= clamp(value, 0.0, 1.0); // cloud shadows float cloud_shade = 1.0; if (cloud_shadow_flag == 1) { vec2 eyePos = (gl_ModelViewMatrixInverse * vec4 (0.0, 0.0, 0.0, 1.0)).xy; vec2 relPos = g_rawpos - eyePos; cloud_shade = shadow_func_nearest(relPos.x, relPos.y, 1.0, g_distance_to_eye); } // lighting is very simple, the ground underneath should do most of it vec3 N = normalize (gl_NormalMatrix * g_normal); float NdotL = 0.5 + 1.0 * clamp(dot (N, gl_LightSource[0].position.xyz), 0.0, 1.0) * cloud_shade; texel *= length(gl_LightSource[0].diffuse.rgb)/1.73 * scattering * NdotL; texel = clamp(texel, 0.0, 1.0); vec4 fragColor = vec4 (texel, value); fragColor.rgb = filter_combined(fragColor.rgb); fragColor = clamp(fragColor, 0.0, 1.0); gl_FragColor = fragColor; }