diff --git a/Effects/cloud-static.eff b/Effects/cloud-static.eff
index 52870a571..55543d9c4 100644
--- a/Effects/cloud-static.eff
+++ b/Effects/cloud-static.eff
@@ -4,7 +4,81 @@
+
+
+
+
+
+
+
+
+
+
+ /sim/rendering/shaders/skydome
+ /sim/rendering/clouds3d-enable
+
+ 1.0
+
+
+
+
+
+
+ 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
+
+
+ 9
+ DepthSortedBin
+
+
+ 0
+
+
+
+
+
+
+
+
+ Shaders/cloud-static-lightfield.vert
+ Shaders/cloud-static-lightfield.frag
+
+
+ baseTexture
+ sampler-2d
+ 0
+
+
+ terminator
+ float
+
+
+
+ altitude
+ float
+
+
+ true
+
+
@@ -58,6 +132,16 @@
sampler-2d
0
+
+ terminator
+ float
+
+
+
+ altitude
+ float
+
+
true
diff --git a/Effects/cloud.eff b/Effects/cloud.eff
index 0dc464100..fa43fbb0f 100644
--- a/Effects/cloud.eff
+++ b/Effects/cloud.eff
@@ -6,8 +6,99 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+ /sim/rendering/shaders/skydome
+
+ 1.0
+
+
+
+
+
+
+ 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
+
+ clamp
+ clamp
+
+
+ Shaders/3dcloud-lightfield.vert
+ Shaders/3dcloud-lightfield.frag
+
+ usrAttr1
+ 10
+
+
+ usrAttr2
+ 11
+
+
+
+ baseTexture
+ sampler-2d
+ 0
+
+
+ range
+ float
+
+
+
+ scattering
+ float
+
+
+
+ terminator
+ float
+
+
+
+ altitude
+ float
+
+
+ true
+
+
@@ -68,6 +159,21 @@
float
+
+ scattering
+ float
+
+
+
+ terminator
+ float
+
+
+
+ altitude
+ float
+
+
true
diff --git a/Effects/model-default.eff b/Effects/model-default.eff
index a332b8245..d2e313cf4 100644
--- a/Effects/model-default.eff
+++ b/Effects/model-default.eff
@@ -32,6 +32,105 @@
+
+
+
+
+ /sim/rendering/shaders/skydome
+
+
+ 2.0
+
+
+
+ GL_ARB_shader_objects
+ GL_ARB_shading_language_100
+ GL_ARB_vertex_shader
+ GL_ARB_fragment_shader
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Shaders/terrain-haze.vert
+ Shaders/terrain-haze.frag
+
+
+ visibility
+ float
+
+
+
+ avisibility
+ float
+
+
+
+ hazeLayerAltitude
+ float
+
+
+
+ scattering
+ float
+
+
+
+ texture
+ sampler-2d
+ 0
+
+
+ colorMode
+ int
+
+
+
+
+
@@ -126,7 +225,7 @@
-
+ Shaders/include_fog.vert
Shaders/default.vert
Shaders/include_fog.frag
diff --git a/Effects/rain-layer.eff b/Effects/rain-layer.eff
index 828237fb6..ee9c78c5d 100644
--- a/Effects/rain-layer.eff
+++ b/Effects/rain-layer.eff
@@ -4,10 +4,88 @@
-
+
+
+
+
+
+
+
+
+
+
+ /sim/rendering/shaders/skydome
+ /sim/rendering/clouds3d-enable
+
+ 1.0
+
+
+
+
+
+
+ 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
+
+
+ 9
+ DepthSortedBin
+
+
+ 0
+
+
+
+
+
+
+
+
+ Shaders/rain-layer-lightfield.vert
+ Shaders/rain-layer-lightfield.frag
+
+
+ baseTexture
+ sampler-2d
+ 0
+
+
+ range
+ float
+
+
+
+ scattering
+ float
+
+
+
+ terminator
+ float
+
+
+ true
+
+
@@ -66,7 +144,16 @@
float
-
+
+ scattering
+ float
+
+
+
+ terminator
+ float
+
+
true
diff --git a/Effects/skydome.eff b/Effects/skydome.eff
index 849af3f32..09fd3ede9 100644
--- a/Effects/skydome.eff
+++ b/Effects/skydome.eff
@@ -1,145 +1,112 @@
- Effects/skydome
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /sim/rendering/shaders/skydome
-
-
- 2.0
-
-
-
- GL_ARB_shader_objects
- GL_ARB_shading_language_100
- GL_ARB_vertex_shader
- GL_ARB_fragment_shader
-
-
-
-
+ Effects/skydome
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /sim/rendering/shader-effects
+ /sim/rendering/shaders/skydome
+
+
+ 2.0
+
+
+
+ GL_ARB_shader_objects
+ GL_ARB_shading_language_100
+ GL_ARB_vertex_shader
+ GL_ARB_fragment_shader
+
+
+
+
-
- true
- smooth
- back
-
- Shaders/skydome.vert
- Shaders/skydome.frag
-
-
- mK
- float
-
-
-
-
-
- rK
- float
-
-
-
-
-
- density
- float
-
-
-
-
-
- overcast
- float
-
-
-
-
-
- saturation
- float
-
-
-
-
-
- scattering
- float
-
-
-
-
-
- visibility
- float
-
-
-
-
-
- hazeLayerAltitude
- float
-
-
-
-
-
- terminator
- float
-
-
-
-
-
- avisibility
- float
-
-
-
-
-
-
+
+ true
+ smooth
+ back
+
+ Shaders/skydome.vert
+ Shaders/skydome.frag
+
+
+ mK
+ float
+
+
+
+ rK
+ float
+
+
+
+ density
+ float
+
+
+
+ overcast
+ float
+
+
+
+ saturation
+ float
+
+
+
+ scattering
+ float
+
+
+
+ visibility
+ float
+
+
+
+ hazeLayerAltitude
+ float
+
+
+
+ terminator
+ float
+
+
+
+ avisibility
+ float
+
+
+
+ terrain_alt
+ float
+
+
+
+
-
-
-
- false
- smooth
- back
-
-
+
+
+
+ false
+ smooth
+ back
+
+
-
\ No newline at end of file
+
diff --git a/Effects/terrain-default.eff b/Effects/terrain-default.eff
index 9f01dfa6d..d4f259abc 100644
--- a/Effects/terrain-default.eff
+++ b/Effects/terrain-default.eff
@@ -35,28 +35,166 @@
0
RenderBin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+ /sim/rendering/shaders/skydome
+
+
+ 2.0
+
+
+
+ GL_ARB_shader_objects
+ GL_ARB_shading_language_100
+ GL_ARB_vertex_shader
+ GL_ARB_fragment_shader
+
+
+
+
+
+ true
+
+
+
+
+
+
+ ambient-and-diffuse
+
+
+ smooth
+ back
+
+ -1
+ RenderBin
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ Shaders/include_fog.vert
+ Shaders/default.vert
+ Shaders/include_fog.frag
+ Shaders/terrain-nocolor.frag
+
+
+ texture
+ sampler-2d
+ 0
+
+ 0 0 0 0
+
+
+ true
+
+
+
+
+
+
+ ambient-and-diffuse
+
+
+
+ smooth
+ back
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ Shaders/terrain-haze.vert
+ Shaders/terrain-haze.frag
+
+
+ visibility
+ float
+
+
+
+ avisibility
+ float
+
+
+
+ hazeLayerAltitude
+ float
+
+
+
+ scattering
+ float
+
+
+
+ terminator
+ float
+
+
+
+ terrain_alt
+ float
+
+
+
+ overcast
+ float
+
+
+
+ eye_alt
+ float
+
+
+
+ texture
+ sampler-2d
+ 0
+
+
+ colorMode
+ int
+ 2
+
+
+ lequal
+ false
+
+
+
+
+
/sim/rendering/shaders/generic
@@ -123,7 +261,7 @@
-
+ Shaders/include_fog.vert
Shaders/default.vert
Shaders/include_fog.frag
Shaders/terrain-nocolor.frag
@@ -254,6 +392,8 @@
+
+
true
diff --git a/Environment/environment.xml b/Environment/environment.xml
index 9b17450e7..b1fb84d58 100644
--- a/Environment/environment.xml
+++ b/Environment/environment.xml
@@ -309,6 +309,7 @@
+
false
false
@@ -330,7 +331,7 @@
- 0.05
+ 60.0
diff --git a/Environment/local-weather-defaults.xml b/Environment/local-weather-defaults.xml
index bd5dcf320..6826b38e7 100644
--- a/Environment/local-weather-defaults.xml
+++ b/Environment/local-weather-defaults.xml
@@ -25,6 +25,7 @@
1.0
0.0
1.0
+ 11.69524
120000.0
diff --git a/Nasal/local_weather/cloud_definitions.nas b/Nasal/local_weather/cloud_definitions.nas
index 495fd4f6b..2f6ffd5d4 100644
--- a/Nasal/local_weather/cloud_definitions.nas
+++ b/Nasal/local_weather/cloud_definitions.nas
@@ -53,7 +53,7 @@ else if (type == "Cumulus (cloudlet)"){
cloudAssembly.min_height = 500.0;
cloudAssembly.max_height = 700.0;
cloudAssembly.min_cloud_width = 1300;
- cloudAssembly.min_cloud_height = 700;
+ cloudAssembly.min_cloud_height = 750;
cloudAssembly.bottom_shade = 0.7;
}
else
@@ -65,7 +65,7 @@ else if (type == "Cumulus (cloudlet)"){
cloudAssembly.min_height = 600.0;
cloudAssembly.max_height = 900.0;
cloudAssembly.min_cloud_width = 1300;
- cloudAssembly.min_cloud_height = 700;
+ cloudAssembly.min_cloud_height = 950;
cloudAssembly.bottom_shade = 0.4;
}
@@ -139,7 +139,7 @@ else if (type == "Cu (volume)"){
cloudAssembly.min_height = 800.0;
cloudAssembly.max_height = 1100.0;
cloudAssembly.min_cloud_width = 1500;
- cloudAssembly.min_cloud_height = 1000;
+ cloudAssembly.min_cloud_height = 1150;
cloudAssembly.bottom_shade = 0.4;
}
@@ -365,8 +365,8 @@ else if (type == "Cumulus (whisp)"){
cloudAssembly.max_width = 600.0 * mult;
cloudAssembly.min_height = 400.0 * mult;
cloudAssembly.max_height = 600.0 * mult;
- cloudAssembly.min_cloud_width = 800 * mult * mult;
- cloudAssembly.min_cloud_height = 800 * mult * mult;
+ cloudAssembly.min_cloud_width = 800;
+ cloudAssembly.min_cloud_height = 800;
cloudAssembly.z_scale = 1.0;
#signal that new routines are used
@@ -952,7 +952,7 @@ else if (type == "Stratus") {
cloudAssembly.min_height = 2000.0 * mult;
cloudAssembly.max_height = 2500.0 * mult;
cloudAssembly.min_cloud_width = 5000.0;
- cloudAssembly.min_cloud_height = 1.1 * cloudAssembly.max_height;
+ cloudAssembly.min_cloud_height = 50; #1.1 * cloudAssembly.max_height;
#signal that new routines are used
diff --git a/Nasal/local_weather/compat_layer.nas b/Nasal/local_weather/compat_layer.nas
index a0b4e985d..d4db29730 100644
--- a/Nasal/local_weather/compat_layer.nas
+++ b/Nasal/local_weather/compat_layer.nas
@@ -23,7 +23,7 @@
# create_cloud_array to place clouds from storage arrays into the scenery
# get_elevation to get the terrain elevation at given coordinates
# get_elevation_vector to get terrain elevation at given coordinate vector
-
+# set_wxradarecho_storm to provide info about a storm to the wxradar
# This file contains portability wrappers for the local weather system:
@@ -126,12 +126,17 @@ print("Compatibility layer: tests done.");
# features of a 2.4 binary
+# switch terrainsampler to active, should be initialized
+
+
features.can_set_light = 1;
features.can_set_scattering = 1;
features.terrain_presampling = 1;
features.terrain_presampling_active = 1;
features.can_disable_environment = 1;
+
+
# features of a current GIT binary
features.fast_geodinfo = 1;
@@ -750,6 +755,36 @@ if (local_weather.dynamics_flag == 1)
}
+
+###########################################################
+# place a model
+###########################################################
+
+var place_model = func(path, lat, lon, alt, heading) {
+
+
+
+var m = props.globals.getNode("models", 1);
+ for (var i = 0; 1; i += 1)
+ if (m.getChild("model", i, 0) == nil)
+ break;
+var model = m.getChild("model", i, 1);
+
+
+model.getNode("path", 1).setValue(path);
+model.getNode("latitude-deg", 1).setValue(lat);
+model.getNode("longitude-deg", 1).setValue(lon);
+model.getNode("elevation-ft", 1).setValue(alt);
+model.getNode("heading-deg", 1).setValue(heading);
+model.getNode("load", 1).remove();
+
+
+}
+
+
+
+
+
###########################################################
# place a single cloud using hard-coded system
###########################################################
@@ -953,12 +988,65 @@ for(var i = 0; i < n; i=i+1)
return elevation;
}
+###########################################################
+# set the wxradar echo of a storm
+###########################################################
+var set_wxradarecho_storm = func (lat, lon, base, top, radius, ref, turb, type) {
+
+# look for the next free index in the wxradar property tree entries
+
+var n = props.globals.getNode("/instrumentation/wxradar", 1);
+ for (var i = 0; 1; i += 1)
+ if (n.getChild("storm", i, 0) == nil)
+ break;
+var s = n.getChild("storm", i, 1);
+
+
+s.getNode("latitude-deg",1).setValue(lat);
+s.getNode("longitude-deg",1).setValue(lon);
+s.getNode("heading-deg",1).setValue(0.0);
+s.getNode("base-altitude-ft",1).setValue(base);
+s.getNode("top-altitude-ft",1).setValue(top);
+s.getNode("radius-nm",1).setValue(radius * m_to_nm);
+s.getNode("reflectivity-norm",1).setValue(ref);
+s.getNode("turbulence-norm",1).setValue(turb);
+s.getNode("type",1).setValue(type);
+s.getNode("show",1).setValue(1);
+}
+
+###########################################################
+# remove unused echos
+###########################################################
+
+var remove_wxradar_echos = func {
+
+var distance_to_remove = 70000.0;
+
+var storms = props.globals.getNode("/instrumentation/wxradar", 1).getChildren("storm");
+
+var pos = geo.aircraft_position();
+
+foreach (s; storms)
+ {
+ var d_sq = local_weather.calc_d_sq(pos.lat(), pos.lon(), s.getNode("latitude-deg").getValue(), s.getNode("longitude-deg").getValue());
+ if (d_sq > distance_to_remove * distance_to_remove)
+ {
+ s.remove();
+ }
+ }
+
+}
############################################################
# global variables
############################################################
+# conversions
+
+var nm_to_m = 1852.00;
+var m_to_nm = 1.0/nm_to_m;
+
# some common abbreviations
var lw = "/local-weather/";
diff --git a/Nasal/local_weather/local_weather.nas b/Nasal/local_weather/local_weather.nas
index 1262ddb64..95a61e4c0 100644
--- a/Nasal/local_weather/local_weather.nas
+++ b/Nasal/local_weather/local_weather.nas
@@ -928,6 +928,8 @@ setprop(lw~"current/wind-speed-kt",windspeed_current);
setprop("/environment/config/boundary/entry[0]/wind-from-heading-deg",winddir);
setprop("/environment/config/boundary/entry[0]/wind-speed-kt",windspeed_ground);
+#setprop("/environment/sea/surface/wind-from-east-fps",windspeed_ground * math.sin(winddir * math.pi/180.0));
+#setprop("/environment/sea/surface/wind-from-east-fps",windspeed_ground * math.cos(winddir * math.pi/180.0));
# end hack
@@ -1609,6 +1611,12 @@ settimer ( func { setsize(weather_dynamics.cloudQuadtrees,0);},0.1); # to avoid
setsize(effectVolumeArray,0);
n_effectVolumeArray = 0;
+
+# clear any wxradar echos
+
+if (wxradar_support_flag ==1)
+ {props.globals.getNode("/instrumentation/wxradar", 1).removeChildren("storm");}
+
# if we have used METAR, we may no longer want to do so
metar_flag = 0;
@@ -2887,8 +2895,8 @@ var terrain_presampling_start = func (blat, blon, nc, size, alpha) {
# initialize the result vector
-setsize(terrain_n,20);
-for(var j=0;j<20;j=j+1){terrain_n[j]=0;}
+setsize(terrain_n,40);
+for(var j=0;j<40;j=j+1){terrain_n[j]=0;}
if (thread_flag == 1)
{
@@ -2911,10 +2919,10 @@ else
setprop(lw~"tmp/presampling-status", "finished");
}
-if (compat_layer.features.terrain_presampling_active == 1)
+if (compat_layer.features.terrain_presampling == 1)
{
print("Starting hard-coded terrain presampling");
-
+ setprop("/environment/terrain/area[0]/enabled",1);
setprop(lw~"tmp/presampling-status", "sampling");
setprop("/environment/terrain/area[0]/enabled", 1 );
setprop("/environment/terrain/area[0]/input/latitude-deg", blat );
@@ -3000,7 +3008,7 @@ var elevation_vec = compat_layer.get_elevation_array(lat_vec, lon_vec);
for (i=0; i int(0.5 *n_tot)) {alt_med = i * 500.0; break;}
}
sum = 0;
- for (var i=0; i<20;i=i+1)
+ for (var i=0; i<40;i=i+1)
{
sum = sum + terrain_n[i];
if (sum > int(0.3 *n_tot)) {alt_20 = i * 500.0; break;}
}
- for (var i=0; i<20;i=i+1) {alt_mean = alt_mean + terrain_n[i] * i * 500.0;}
+ for (var i=0; i<40;i=i+1) {alt_mean = alt_mean + terrain_n[i] * i * 500.0;}
alt_mean = alt_mean/n_tot;
- for (var i=0; i<20;i=i+1) {if (terrain_n[i] > 0) {alt_min = i * 500.0; break;}}
+ for (var i=0; i<40;i=i+1) {if (terrain_n[i] > 0) {alt_min = i * 500.0; break;}}
var n_max = 0;
sum = 0;
- for (var i=0; i<19;i=i+1)
+ for (var i=0; i<39;i=i+1)
{
sum = sum + terrain_n[i];
if (terrain_n[i] > n_max) {n_max = terrain_n[i];}
@@ -3090,6 +3098,11 @@ append(alt_50_array, alt_med);
append(alt_20_array, alt_20);
append(alt_min_array, alt_min);
append(alt_mean_array, alt_mean);
+
+
+current_mean_alt = 0.5 * (current_mean_alt + alt_20);
+
+
}
@@ -3592,7 +3605,7 @@ debug_output_flag = getprop(lw~"config/debug-output-flag");
fps_control_flag = getprop(lw~"config/fps-control-flag");
realistic_visibility_flag = getprop(lw~"config/realistic-visibility-flag");
detailed_terrain_interaction_flag = getprop(lw~"config/detailed-terrain-interaction-flag");
-scattering_shader_flag = getprop("/sim/rendering/scattering-shader");
+scattering_shader_flag = getprop("/sim/rendering/shaders/skydome");
}
@@ -4257,11 +4270,11 @@ setlistener(lw~"config/target-framerate", func {target_framerate = getprop(lw~"c
setlistener(lw~"config/small-scale-persistence", func {weather_tiles.small_scale_persistence = getprop(lw~"config/small-scale-persistence");});
setlistener(lw~"config/ground-haze-factor", func {ground_haze_factor = getprop(lw~"config/ground-haze-factor");});
-setlistener(lw~"config/max-vis-range-m", func {max_vis_range = getprop(lw~"config/max-vis-range-m");});
+setlistener(lw~"config/aux-max-vis-range-m", func {max_vis_range = math.exp(getprop(lw~"config/aux-max-vis-range-m")); setprop(lw~"config/max-vis-range-m",max_vis_range);});
setlistener(lw~"config/temperature-offset-degc", func {temperature_offset = getprop(lw~"config/temperature-offset-degc");});
-setlistener("/sim/rendering/scattering-shader", func {scattering_shader_flag = getprop("/sim/rendering/scattering-shader"); });
+setlistener("/sim/rendering/shaders/skydome", func {scattering_shader_flag = getprop("/sim/rendering/shaders/skydome"); });
}
@@ -4273,6 +4286,7 @@ var test = func {
var lat = getprop("position/latitude-deg");
var lon = getprop("position/longitude-deg");
+var alt = getprop("position/altitude-ft");
thread_flag = 0;
dynamics_flag = 0;
@@ -4294,11 +4308,11 @@ presampling_flag = 0;
#var pos = geo.aircraft_position();
-debug.dump(geodinfo(lat, lon));
+# debug.dump(geodinfo(lat, lon));
#create_cumulonimbus_cloud(lat, lon, 6000.0, 2.5);
-# geo.put_model("Models/Astro/Earth.ac",lat, lon);
+local_weather.place_model("Models/Weather/cloudsphere.ac",lat, lon, alt-10000.0, 0.0);
#setprop("/environment/terrain/area[0]/input/latitude-deg", lat );
#setprop("/environment/terrain/area[0]/input/longitude-deg", lon );
@@ -4586,7 +4600,7 @@ var ec = "/environment/config/";
# a hash map of the strength for convection associated with terrain types
-var landcover_map = {BuiltUpCover: 0.35, Town: 0.35, Freeway:0.35, BarrenCover:0.3, HerbTundraCover: 0.25, GrassCover: 0.2, CropGrassCover: 0.2, EvergreenBroadCover: 0.2, EvergreenNeedleCover: 0.2, Sand: 0.25, Grass: 0.2, Ocean: 0.01, Marsh: 0.05, Lake: 0.01, ShrubCover: 0.15, Landmass: 0.2, CropWoodCover: 0.15, MixedForestCover: 0.15, DryCropPastureCover: 0.25, MixedCropPastureCover: 0.2, IrrCropPastureCover: 0.15, DeciduousBroadCover: 0.1, DeciduousNeedleCover: 0.1, Bog: 0.05, pa_taxiway : 0.35, pa_tiedown: 0.35, pc_taxiway: 0.35, pc_tiedown: 0.35, Glacier: 0.03, SnowCover: 0.04, DryLake: 0.3, IntermittentStream: 0.2, DryCrop: 0.2, Lava: 0.3, GolfCourse: 0.2, Rock: 0.3, Construction: 0.35};
+var landcover_map = {BuiltUpCover: 0.35, Town: 0.35, Freeway:0.35, BarrenCover:0.3, HerbTundraCover: 0.25, GrassCover: 0.2, CropGrassCover: 0.2, EvergreenBroadCover: 0.2, EvergreenNeedleCover: 0.2, Sand: 0.25, Grass: 0.2, Ocean: 0.01, Marsh: 0.05, Lake: 0.01, ShrubCover: 0.15, Landmass: 0.2, CropWoodCover: 0.15, MixedForestCover: 0.15, DryCropPastureCover: 0.25, MixedCropPastureCover: 0.2, IrrCropPastureCover: 0.15, DeciduousBroadCover: 0.1, DeciduousNeedleCover: 0.1, Bog: 0.05, pa_taxiway : 0.35, pa_tiedown: 0.35, pc_taxiway: 0.35, pc_tiedown: 0.35, Glacier: 0.03, SnowCover: 0.04, DryLake: 0.3, IntermittentStream: 0.2, DryCrop: 0.2, Lava: 0.3, GolfCourse: 0.2, Rock: 0.3, Construction: 0.35, PackIce: 0.04, NaturalCrop: 0.2};
# a hash map of average vertical cloud model sizes
@@ -4694,11 +4708,12 @@ var detailed_terrain_interaction_flag = 1;
var hardcoded_clouds_flag = 1;
var realistic_visibility_flag = 0;
var scattering_shader_flag = 0;
+var wxradar_support_flag = 1;
var ground_haze_factor = 1.0;
var max_vis_range = 120000.0;
var temperature_offset = 0.0;
-
+var current_mean_alt = 0.0;
# globals for framerate controlled cloud management
@@ -4758,6 +4773,8 @@ setprop(lw~"effect-volumes/number-active-sat",0);
# setprop(lw~"config/max-vis-range-m", 120000.0);
setprop(lw~"config/temperature-offset-degc", 0.0);
+setprop("/sim/rendering/eye-altitude-m", getprop("/position/altitude-ft") * ft_to_m);
+
# create properties for tile management
setprop(lw~"tiles/tile-counter",0);
diff --git a/Nasal/local_weather/weather_dynamics.nas b/Nasal/local_weather/weather_dynamics.nas
index 49ff8dae2..8f1615676 100644
--- a/Nasal/local_weather/weather_dynamics.nas
+++ b/Nasal/local_weather/weather_dynamics.nas
@@ -117,10 +117,24 @@ time_lw = time_lw + dt_lw;
# directly referencing /sim/time/sun-angle-rad as uniform doesn't
# work since that is a tied property
-var sun_angle = 1.57079632675 - getprop("/sim/time/sun-angle-rad");
+#var sun_angle = 1.57079632675 - getprop("/sim/time/sun-angle-rad");
-var terminator_offset = sun_angle / 0.017451 * 110000.0 + 250000.0;
-setprop("/environment/terminator-relative-position-m",terminator_offset);
+#var terminator_offset = sun_angle / 0.017451 * 110000.0;# + 250000.0;
+#setprop("/environment/terminator-relative-position-m",terminator_offset);
+
+var viewpos = geo.viewer_position();
+
+# setprop("/environment/alt-in-haze-m", getprop("/environment/ground-haze-thickness-m")-viewpos.alt());
+
+setprop("/sim/rendering/eye-altitude-m", viewpos.alt());
+
+if (local_weather.presampling_flag == 1)
+ {
+ var mean_terrain_elevation_m = ft_to_m * local_weather.current_mean_alt ; }
+else
+ {var mean_terrain_elevation_m = 0.0;}
+
+setprop("/environment/mean-terrain-elevation-m", mean_terrain_elevation_m);
if (getprop(lw~"timing-loop-flag") ==1) {settimer(timing_loop, 0);}
diff --git a/Nasal/local_weather/weather_tile_management.nas b/Nasal/local_weather/weather_tile_management.nas
index 25b741d21..aebf4f015 100644
--- a/Nasal/local_weather/weather_tile_management.nas
+++ b/Nasal/local_weather/weather_tile_management.nas
@@ -53,7 +53,7 @@ var this_frame_action_flag = 0; # use this flag to avoid overlapping tile operat
setsize(active_tile_list,0);
#append(active_tile_list,0); # tile zero formally containing static objects is always active
-var distance_to_load = current_visibility;
+var distance_to_load = current_visibility + 10000.0;
if (distance_to_load > 65000.0) {distance_to_load = 65000.0;}
if (distance_to_load < 29000.0) {distance_to_load = 29000.0;}
@@ -64,7 +64,9 @@ if (distance_to_load < 29000.0) {distance_to_load = 29000.0;}
#if (distance_to_load < 29000.0)
# {distance_to_load = 29000.0;}
-var distance_to_remove = distance_to_load + 500.0;
+var distance_to_remove = distance_to_load + 20000.0;
+if (distance_to_remove > 65500.0) {distance_to_remove = 65500.0;}
+
# check here if we have a new weather station if METAR is running
@@ -202,7 +204,7 @@ foreach (var t; tNode) {
-if (getprop(lw~"tile-loop-flag") ==1) {settimer(tile_management_loop, 5.0);}
+if (getprop(lw~"tile-loop-flag") ==1) {settimer(tile_management_loop, 4.0);}
}
@@ -713,6 +715,11 @@ if (local_weather.dynamics_flag ==1)
local_weather.assemble_effect_array();
+if (local_weather.wxradar_support_flag == 1)
+ {
+ local_weather.remove_wxradar_echos();
+ }
+
}
diff --git a/Nasal/local_weather/weather_tiles.nas b/Nasal/local_weather/weather_tiles.nas
index ffc41e383..e3d28581a 100644
--- a/Nasal/local_weather/weather_tiles.nas
+++ b/Nasal/local_weather/weather_tiles.nas
@@ -112,14 +112,21 @@ alt_offset = 0.0;
#create_4_8_cirrocumulus_streaks(blat, blon, 10000.0 + alt_offset, alpha);
#create_4_8_alttstratus_streaks(blat, blon, 5000+alt_offset, alpha) ;
+# create_4_8_alttstratus_streaks(blat, blon, 5000+alt_offset, alpha) ;
#create_2_8_cirrocumulus_patches(blat, blon, 13000+alt_offset, alpha) ;
-#create_8_8_nimbus_rain(blat, blon, 3000+alt_offset, alpha, 0.3) ;
+# create_8_8_nimbus_rain(blat, blon, 3000.0, alpha, 0.3) ;
#create_8_8_tstratus(blat, blon, 5000+alt_offset, alpha);
-#create_8_8_cirrostratus(blat, blon, 5000+alt_offset, alpha);
-create_thunderstorm_scenario (blat, blon, 3000.0, alpha);
+
+# create_8_8_cirrostratus(blat, blon, 30000.0, alpha);
+
+#create_thunderstorm_scenario (blat, blon, 3000.0, alpha);
#create_big_thunderstorm (blat, blon, 3000.0, alpha);
+#create_2_8_cirrus(blat, blon, 30000.0, alpha);
+#create_2_8_cirrus(blat, blon, 20000.0, alpha);
+create_4_8_cirrus(blat, blon, 30000.0, alpha);
+
#create_4_8_altocumulus_perlucidus(blat, blon, 5000+alt_offset, alpha) ;
#create_detailed_stratocumulus_bank(blat, blon, 4000+alt_offset,alpha);
@@ -193,7 +200,7 @@ else
#rn = 0.1;
-if (rn > 0.8)
+if (rn > 0.833)
{
# cloud scenario 1: weak cumulus development and blue thermals
@@ -213,7 +220,7 @@ if (rn > 0.8)
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.0, 25000.0, 30000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.6)
+else if (rn > 0.666)
{
# cloud scenario 2: some Cirrocumulus patches
@@ -227,7 +234,7 @@ else if (rn > 0.6)
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.1, alt+alt_offset +30000.0, alt+alt_offset + 35000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.4)
+else if (rn > 0.5)
{
# cloud scenario 3: Cirrostratus undulatus over weak cumulus
@@ -240,7 +247,7 @@ else if (rn > 0.4)
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.15, alt+alt_offset +28000.0, alt+alt_offset + 32000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.2)
+else if (rn > 0.333)
{
# cloud scenario 4: Cirrostratus undulatus streak
@@ -252,7 +259,7 @@ else if (rn > 0.2)
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.15, alt+alt_offset +28000.0, alt+alt_offset + 32000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.0)
+else if (rn > 0.166)
{
# cloud scenario 5: Cirrus
@@ -267,7 +274,13 @@ else if (rn > 0.0)
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.0, alt+alt_offset +28000.0, alt+alt_offset + 33000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
}
+else if (rn > 0.0)
+ {
+ # cloud scenario 6: strong Cirrus cover
+ create_4_8_cirrus(blat, blon, alt + alt_offset + 35000.0, alpha);
+ local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.0, alt+alt_offset +28000.0, alt+alt_offset + 33000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
+ }
# store convective altitude and strength
@@ -528,18 +541,12 @@ else if (rn > 0.666)
}
else if (rn > 0.555)
{
- # cloud scenario 4: Cumulonimbus banks
+ # cloud scenario 4: thin Stratus streaks
strength = 0.7 + rand() * 0.3;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
- for (var i = 0; i < 3; i = i + 1)
- {
- x = 2.0 * (rand()-0.5) * 16000;
- y = 2.0 * (rand()-0.5) * 16000;
-
- create_cloud_bank("Cumulonimbus", blat+get_lat(x,y,phi), blon+get_lon(x,y,phi), alt+alt_offset, 1600.0, 800.0, 3000.0, 9, alpha);
- }
+ create_4_8_alttstratus_streaks(blat, blon, alt+alt_offset +10000.0, alpha);
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.0, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
@@ -854,8 +861,6 @@ if (rand() < small_scale_persistence)
else
{rnd_store = rn;}
-#rn = 0.1;
-
if (rn > 0.8)
{
@@ -1001,7 +1006,7 @@ local_weather.set_weather_station(blat, blon, alt_offset, vis, T, D, p * hp_to_i
# set a closed Nimbostratus layer
-var alt = spread * 400.0;
+var alt = spread * 400.0 + local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft;
var strength = 0.0;
#var alt = 3000.0;
@@ -2533,7 +2538,7 @@ var create_8_8_cirrostratus = func (lat, lon, alt, alpha) {
if (local_weather.hardcoded_clouds_flag == 1) {alt = alt - local_weather.offset_map["Cirrostratus"];}
-local_weather.create_streak("Cirrostratus",lat,lon,alt,500.0,30,1250.0,0.0,400.0,30,1250.0,0.0,400.0,alpha,1.0);
+local_weather.create_streak("Cirrostratus",lat,lon,alt,500.0,30,1300.0,0.0,400.0,30,1300.0,0.0,400.0,alpha,1.0);
}
var create_8_8_nimbus = func (lat, lon, alt, alpha) {
@@ -3060,6 +3065,19 @@ else
}
+var create_4_8_cirrus = func (lat, lon, alt, alpha) {
+
+var phi = alpha * math.pi/180.0;
+
+var x = 2.0 * (rand()-0.5) * 1000;
+var y = 2.0 * (rand()-0.5) * 1000;
+
+
+local_weather.create_streak("Cirrus",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,1500.0,4,10000.0,0.0, 3000.0, 4,10000.0,0.0,3000.0,alpha,1.0);
+
+}
+
+
var create_2_8_stratus = func (lat, lon, alt, alpha) {
if (local_weather.hardcoded_clouds_flag == 1) {alt = alt - local_weather.offset_map["Stratus"];}
@@ -3430,7 +3448,14 @@ append(elat, lat); append(elon, lon); append(erad, 4000.0 * scale * 1.2);
# set precipitation, visibility, updraft and turbulence in the cloud
-local_weather.create_effect_volume(1, lat, lon, 4000.0 * 0.7 * scale, 4000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 600.0, 0.8, -1, 0.6, 15.0,1 ,-1);
+local_weather.create_effect_volume(1, lat, lon, 4000.0 * 0.7 * scale, 4000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 1100.0, 0.8, -1, 0.6, 15.0,1 ,-1);
+
+# set the wxradar echo
+
+if (local_weather.wxradar_support_flag == 1)
+ {
+ compat_layer.set_wxradarecho_storm (lat, lon, alt, 20000.0, 4000.0 * 0.7 * scale, 1.0, 0.6, "single_cell");
+ }
}
@@ -3458,7 +3483,15 @@ append(elat, lat); append(elon, lon); append(erad, 6000.0 * scale * 1.2);
# set precipitation, visibility, updraft and turbulence in the cloud
-local_weather.create_effect_volume(1, lat, lon, 6000.0 * 0.7 * scale, 6000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 500.0, 1.0, -1, 0.8, 20.0,1,-1 );
+local_weather.create_effect_volume(1, lat, lon, 6000.0 * 0.7 * scale, 6000.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 1100.0, 1.0, -1, 0.8, 20.0,1,-1 );
+
+# set the wxradar echo
+
+if (local_weather.wxradar_support_flag == 1)
+ {
+ compat_layer.set_wxradarecho_storm (lat, lon, alt, 20000.0, 6000.0 * 0.7 * scale, 1.0, 0.8, "single_cell");
+ }
+
}
@@ -3492,7 +3525,14 @@ local_weather.create_layer("Stratus (thin)", lat+get_lat(0,-4000,phi), lon+get_l
# set the exclusion region for the Cumulus layer
append(elat, lat); append(elon, lon); append(erad, 7500.0 * scale * 1.2);
-local_weather.create_effect_volume(1, lat, lon, 7500.0 * 0.7 * scale, 7500.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 500.0, 1.0, -1, 1.0, 25.0,1,-1 );
+local_weather.create_effect_volume(1, lat, lon, 7500.0 * 0.7 * scale, 7500.0 * 0.7 * scale , 0.0, 0.0, 20000.0, 1100.0, 1.0, -1, 1.0, 25.0,1,-1 );
+
+# set the wxradar echo
+
+if (local_weather.wxradar_support_flag == 1)
+ {
+ compat_layer.set_wxradarecho_storm (lat, lon, alt, 24000.0, 7500.0 * 0.7 * scale, 1.0, 1.0, "single_cell");
+ }
}
diff --git a/Shaders/3dcloud-lightfield.frag b/Shaders/3dcloud-lightfield.frag
new file mode 100644
index 000000000..dd90fdddf
--- /dev/null
+++ b/Shaders/3dcloud-lightfield.frag
@@ -0,0 +1,15 @@
+uniform sampler2D baseTexture;
+varying float fogFactor;
+
+varying vec3 hazeColor;
+
+void main(void)
+{
+ vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);
+ vec4 finalColor = base * gl_Color;
+ //gl_FragColor.rgb = mix(gl_Fog.color.rgb, finalColor.rgb, fogFactor );
+ gl_FragColor.rgb = mix(hazeColor, finalColor.rgb, fogFactor );
+ //gl_FragColor.a = mix(0.0, finalColor.a, fogFactor);
+ gl_FragColor.a = mix(0.0, finalColor.a, 1.0 - 0.5 * (1.0 - fogFactor));
+}
+
diff --git a/Shaders/3dcloud-lightfield.vert b/Shaders/3dcloud-lightfield.vert
new file mode 100644
index 000000000..0f512fbea
--- /dev/null
+++ b/Shaders/3dcloud-lightfield.vert
@@ -0,0 +1,169 @@
+// -*-C++-*-
+#version 120
+
+varying float fogFactor;
+varying vec3 hazeColor;
+
+uniform float range; // From /sim/rendering/clouds3d-vis-range
+uniform float scattering;
+uniform float terminator;
+uniform float altitude;
+
+attribute vec3 usrAttr1;
+attribute vec3 usrAttr2;
+
+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.0;}
+
+
+return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
+}
+
+void main(void)
+{
+
+ float intensity;
+ 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;
+
+ // 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))));
+
+ // Determine the position - used for fog and shading calculations
+ vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);
+ float fogCoord = abs(ecPosition.z);
+
+ // 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);
+
+ // compute the light at the position
+ vec4 light_diffuse;
+
+ float lightArg = (terminator-yprime_alt)/100000.0;
+
+ light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 2.227, 1.08e-05, 1.0);
+ light_diffuse.g = light_func(lightArg, 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 = 0.0;
+
+ intensity = length(light_diffuse);
+ light_diffuse = intensity * normalize(mix(light_diffuse, 2.0*vec4 (0.55, 0.6, 0.8, 1.0), (1.0 - smoothstep(0.3,0.8, scattering))));
+
+
+
+
+ //gl_FrontColor = gl_LightSource[0].diffuse * shade + gl_FrontLightModelProduct.sceneColor;
+ gl_FrontColor = light_diffuse * shade + gl_FrontLightModelProduct.sceneColor;
+
+ // 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(range*0.9, range, fogCoord));
+ //gl_BackColor = gl_FrontColor;
+
+ // Fog doesn't affect clouds as much as other objects.
+ float fadeScale = 0.05 + 0.2 * log(fogCoord/1000.0);
+ if (fadeScale < 0.05) fadeScale = 0.05;
+ fogFactor = exp( -gl_Fog.density * fogCoord * fadeScale);
+
+
+ // Fog doesn't affect clouds as much as other objects.
+ //fogFactor = exp( -gl_Fog.density * fogCoord * 0.5);
+ //fogFactor = clamp(fogFactor, 0.0, 1.0);
+
+// haze of ground haze shader is slightly bluish
+ //hazeColor = vec3 (gl_LightSource[0].diffuse.x, gl_LightSource[0].diffuse.y, gl_LightSource[0].diffuse.z);
+ hazeColor = light_diffuse.xyz;
+ hazeColor.x = hazeColor.x * 0.83;
+ hazeColor.y = hazeColor.y * 0.9;
+ hazeColor = hazeColor * scattering;
+
+ // in sunset or sunrise conditions, do extra shading of clouds
+
+ // two times terminator width governs how quickly light fades into shadow
+ float terminator_width = 200000.0;
+ float earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
+
+ // change haze color to blue hue for strong fogging
+ intensity = length(hazeColor);
+ hazeColor = intensity * normalize(mix(hazeColor, 2.0* vec3 (0.55, 0.6, 0.8), (1.0 - smoothstep(0.3,0.8,scattering))));
+
+
+ hazeColor = hazeColor * earthShade;
+ gl_FrontColor.xyz = gl_FrontColor.xyz * earthShade;
+ gl_BackColor = gl_FrontColor;
+}
diff --git a/Shaders/cloud-static-lightfield.frag b/Shaders/cloud-static-lightfield.frag
new file mode 100644
index 000000000..1c84c0a47
--- /dev/null
+++ b/Shaders/cloud-static-lightfield.frag
@@ -0,0 +1,12 @@
+uniform sampler2D baseTexture;
+varying float fogFactor;
+
+varying vec3 hazeColor;
+
+void main(void)
+{
+ vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);
+ vec4 finalColor = base * gl_Color;
+ gl_FragColor.rgb = mix(hazeColor, finalColor.rgb, fogFactor );
+ gl_FragColor.a = mix(0.0, finalColor.a, 1.0 - 0.5 * (1.0 - fogFactor));
+}
diff --git a/Shaders/cloud-static-lightfield.vert b/Shaders/cloud-static-lightfield.vert
new file mode 100644
index 000000000..1efb10a4e
--- /dev/null
+++ b/Shaders/cloud-static-lightfield.vert
@@ -0,0 +1,119 @@
+// -*-C++-*-
+#version 120
+
+varying float fogFactor;
+varying vec3 hazeColor;
+
+uniform float terminator;
+uniform float altitude;
+
+const float shade = 1.0;
+const float cloud_height = 1000.0;
+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.0;}
+
+
+return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
+}
+
+void main(void)
+{
+
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ //gl_TexCoord[0] = gl_MultiTexCoord0 + vec4(textureIndexX, textureIndexY, 0.0, 0.0);
+ 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);
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position.x = gl_Vertex.x;
+ gl_Position.y += gl_Vertex.y;
+ gl_Position.z += gl_Vertex.z;
+ gl_Position.xyz += gl_Color.xyz;
+
+
+ // 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(mat3x3(gl_ModelViewMatrix) * (- gl_Position.xyz)));;
+
+ // Determine the position - used for fog and shading calculations
+ vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);
+ float fogCoord = abs(ecPosition.z);
+ float fract = smoothstep(0.0, cloud_height, gl_Position.z + cloud_height);
+
+ 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
+ //float vertex_alt = max(altitude * 0.30480 + relVector.z,100.0);
+ float vertex_alt = altitude + relVector.z;
+ float yprime = -dot(relVector, lightHorizon);
+ float yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
+
+ // compute the light at the position
+ vec4 light_diffuse;
+
+ float lightArg = (terminator-yprime_alt)/100000.0;
+
+ light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 2.827, 1.08e-05, 1.0);
+ light_diffuse.g = light_func(lightArg, 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 = 0.0;
+
+
+// Determine the shading of the sprite based on its vertical position and position relative to the sun.
+ n = min(smoothstep(-0.5, 0.0, n), fract);
+// Determine the shading based on a mixture from the backlight to the front
+ vec4 backlight = light_diffuse * shade;
+
+ gl_FrontColor = mix(backlight, gl_LightSource[0].diffuse, n);
+ gl_FrontColor += gl_FrontLightModelProduct.sceneColor;
+
+ // 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(100.0, 250.0, fogCoord), 1.0 - smoothstep(70000.0, 75000.0, fogCoord));
+
+ // Fog doesn't affect rain as much as other objects.
+ //fogFactor = exp( -gl_Fog.density * fogCoord * 0.4);
+ //fogFactor = clamp(fogFactor, 0.0, 1.0);
+
+float fadeScale = 0.05 + 0.2 * log(fogCoord/1000.0);
+ if (fadeScale < 0.05) fadeScale = 0.05;
+ fogFactor = exp( -gl_Fog.density * fogCoord * fadeScale);
+
+ hazeColor = light_diffuse.xyz;
+ hazeColor.x = hazeColor.x * 0.83;
+ hazeColor.y = hazeColor.y * 0.9;
+
+ // in sunset or sunrise conditions, do extra shading of clouds
+
+
+
+ // two times terminator width governs how quickly light fades into shadow
+ float terminator_width = 200000.0;
+
+ // now dim the light
+ float earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
+
+ hazeColor = hazeColor * earthShade;
+ gl_FrontColor.xyz = gl_FrontColor.xyz * earthShade;
+ gl_BackColor = gl_FrontColor;
+
+}
diff --git a/Shaders/rain-layer-lightfield.frag b/Shaders/rain-layer-lightfield.frag
new file mode 100644
index 000000000..000da97c8
--- /dev/null
+++ b/Shaders/rain-layer-lightfield.frag
@@ -0,0 +1,12 @@
+uniform sampler2D baseTexture;
+varying float fogFactor;
+
+varying vec3 hazeColor;
+
+void main(void)
+{
+ vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);
+ vec4 finalColor = base * gl_Color;
+ gl_FragColor.rgb = mix(hazeColor, finalColor.rgb, fogFactor );
+ gl_FragColor.a = mix(0.0, finalColor.a, fogFactor);
+}
diff --git a/Shaders/rain-layer-lightfield.vert b/Shaders/rain-layer-lightfield.vert
new file mode 100644
index 000000000..b212a867a
--- /dev/null
+++ b/Shaders/rain-layer-lightfield.vert
@@ -0,0 +1,122 @@
+// -*-C++-*-
+#version 120
+
+varying float fogFactor;
+varying vec3 hazeColor;
+
+uniform float range; // From /sim/rendering/clouds3d-vis-range
+uniform float scattering;
+uniform float terminator;
+uniform float altitude;
+
+
+float shade = 0.8;
+float cloud_height = 1000.0;
+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;
+return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
+}
+
+void main(void)
+{
+
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ //gl_TexCoord[0] = gl_MultiTexCoord0 + vec4(textureIndexX, textureIndexY, 0.0, 0.0);
+ 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);
+
+ gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+ gl_Position.x = gl_Vertex.x;
+ gl_Position.y += gl_Vertex.y;
+ gl_Position.z += gl_Vertex.z;
+ gl_Position.xyz += gl_Color.xyz;
+
+
+
+ // 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(mat3x3(gl_ModelViewMatrix) * (- gl_Position.xyz)));;
+
+ // Determine the position - used for fog and shading calculations
+ vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);
+ float fogCoord = abs(ecPosition.z);
+ float fract = smoothstep(0.0, cloud_height, gl_Position.z + cloud_height);
+
+ 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
+ float vertex_alt = max(altitude * 0.30480 + relVector.z,100.0);
+ float yprime = -dot(relVector, lightHorizon);
+ float yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
+
+ // compute the light at the position
+ vec4 light_diffuse;
+
+ float lightArg = (terminator-yprime_alt)/100000.0;
+
+ light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 2.827, 1.08e-05, 1.0);
+ light_diffuse.g = light_func(lightArg, 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 = 0.0;
+
+ //light_diffuse = light_diffuse * scattering;
+ float intensity = length(light_diffuse);
+ light_diffuse = intensity * normalize(mix(light_diffuse, 2.0*vec4 (0.55, 0.6, 0.8, 1.0), (1.0 - smoothstep(0.3,0.8, scattering))));
+
+// Determine the shading of the sprite based on its vertical position and position relative to the sun.
+ n = min(smoothstep(-0.5, 0.0, n), fract);
+// Determine the shading based on a mixture from the backlight to the front
+ vec4 backlight = gl_LightSource[0].diffuse * shade;
+
+ gl_FrontColor = mix(backlight, gl_LightSource[0].diffuse, n);
+ gl_FrontColor += gl_FrontLightModelProduct.sceneColor;
+
+ // 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(100.0, 250.0, fogCoord), 1.0 - smoothstep(range*0.9, range, fogCoord));
+ gl_BackColor = gl_FrontColor;
+
+ // Fog doesn't affect rain as much as other objects.
+ //fogFactor = exp( -gl_Fog.density * fogCoord * 0.4);
+ //fogFactor = clamp(fogFactor, 0.0, 1.0);
+
+float fadeScale = 0.05 + 0.2 * log(fogCoord/1000.0);
+ if (fadeScale < 0.05) fadeScale = 0.05;
+ fogFactor = exp( -gl_Fog.density * 1.0 * fogCoord * fadeScale);
+
+ hazeColor = light_diffuse.xyz;
+ hazeColor.x = hazeColor.x * 0.83;
+ hazeColor.y = hazeColor.y * 0.9;
+ hazeColor = hazeColor * scattering;
+
+// change haze color to blue hue for strong fogging
+ intensity = length(hazeColor);
+ hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,scattering))));
+
+ // two times terminator width governs how quickly light fades into shadow
+ float terminator_width = 200000.0;
+
+ // now dim the light
+ float earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
+
+ hazeColor = hazeColor * earthShade;
+ gl_FrontColor.xyz = gl_FrontColor.xyz * earthShade;
+ gl_BackColor = gl_FrontColor;
+
+}
diff --git a/Shaders/skydome.frag b/Shaders/skydome.frag
index c50309fc5..a65f5e5d9 100644
--- a/Shaders/skydome.frag
+++ b/Shaders/skydome.frag
@@ -7,8 +7,21 @@
varying vec3 rayleigh;
varying vec3 mie;
varying vec3 eye;
-varying float ct;
-
+varying vec3 hazeColor;
+varying float ct;
+//varying float cosphi;
+varying float delta_z;
+varying float alt;
+varying float earthShade;
+
+uniform float overcast;
+uniform float saturation;
+uniform float visibility;
+uniform float avisibility;
+uniform float scattering;
+
+const float EarthRadius = 5800000.0;
+
float miePhase(in float cosTheta, in float g)
{
float g2 = g*g;
@@ -32,36 +45,154 @@ void main()
{
float cosTheta = dot(normalize(eye), gl_LightSource[0].position.xyz);
+ // position of the horizon line
+
+ float lAltitude = alt + delta_z;
+ float radiusEye = EarthRadius + alt;
+ float radiusLayer = EarthRadius + lAltitude;
+ float cthorizon;
+ float ctterrain;
+
+ if (radiusEye > radiusLayer) cthorizon = -sqrt(radiusEye * radiusEye - radiusLayer * radiusLayer)/radiusEye;
+ else cthorizon = sqrt(radiusLayer * radiusLayer - radiusEye * radiusEye)/radiusLayer;
+
+ ctterrain = -sqrt(radiusEye * radiusEye - EarthRadius * EarthRadius)/radiusEye;
vec3 color = rayleigh * rayleighPhase(cosTheta);
color += mie * miePhase(cosTheta, -0.8);
- vec3 white = vec3(1.0,1.0,1.0);
-
-
- //float scale = dot(normalize(white),normalize(color));
- //float scale1 = 1.0 - exp(-5.0 * length(color));
- //float scale2 = length(color)/length(white);
-
- //if (scale1>1.0) color = color/scale1;
-
- //color = color/scale1;
-
+ vec3 black = vec3(0.0,0.0,0.0);
- if (color.x > 0.8) color.x = 0.8 + 0.8* log(color.x/0.8);
- if (color.y > 0.8) color.y = 0.8 + 0.8* log(color.y/0.8);
- if (color.z > 0.8) color.z = 0.8 + 0.8* log(color.z/0.8);
+ float ovc = overcast;
- vec3 fogColor = vec3 (gl_Fog.color.x, gl_Fog.color.y, gl_Fog.color.z);
-
- if (ct > -0.03) color = mix(color, fogColor ,smoothstep(0.2, -0.2, ct));
- else color = mix (color, fogColor, smoothstep(0.2,-0.2,-0.03));
+
+ float sat = 1.0 - ((1.0 - saturation) * 2.0);
+ if (sat < 0.3) sat = 0.3;
+
+
+ // float wscale = 1.732;
+// an overexposure filter, the log() seems to be pretty expensive though
-
+// if (color.x > 0.8) color.x = 0.8 + 0.8* log(color.x/0.8);
+// if (color.y > 0.8) color.y = 0.8 + 0.8* log(color.y/0.8);
+// if (color.z > 0.8) color.z = 0.8 + 0.8* log(color.z/0.8);
+
+//vec3 fogColor = vec3 (gl_Fog.color.x, gl_Fog.color.y, gl_Fog.color.z);
+
+
+// reduce the whiteout near the horizon generated by the single scattering approximation
+
+if (ct > cthorizon) color = mix(color, black ,smoothstep(0.2+cthorizon, -0.2+cthorizon, ct));
+else color = mix (color, black, smoothstep(0.2+cthorizon,-0.2+cthorizon, cthorizon));
+
+
+
+
+// fog computations for a ground haze layer, extending from zero to lAltitude
+
+
+
+float transmission;
+float vAltitude;
+float delta_zv;
+
+float costheta = ct;
+
+float vis= visibility;
+
+// hack - in an effect volume the visibility only may be reduced, so we take care here
+if (avisibility < visibility){vis = avisibility;}
+
+ if (delta_z > 0.0) // we're inside the layer
+ {
+ if (costheta>0.0 + ctterrain) // looking up, view ray intersecting upper layer edge
+ {
+ transmission = exp(-min((delta_z/max(costheta,0.1)),25000.0)/vis);
+ //transmission = 1.0;
+ vAltitude = min(vis * costheta, delta_z);
+ delta_zv = delta_z - vAltitude;
+ }
+
+ else // looking down, view range intersecting terrain (which may not be drawn)
+ {
+ transmission = exp(alt/vis/costheta);
+ vAltitude = min(-vis * costheta, alt);
+ delta_zv = delta_z + vAltitude;
+ }
+ }
+ else // we see the layer from above
+ {
+ if (costheta < 0.0 + cthorizon)
+ {
+ transmission = exp(-min(lAltitude/abs(costheta),25000.0)/vis);
+ transmission = transmission * exp(-alt/avisibility/abs(costheta));
+ transmission = 1.0 - (1.0 - transmission) * smoothstep(0+cthorizon, -0.02+cthorizon, costheta);
+ vAltitude = min(lAltitude, -vis * costheta);
+ delta_zv = vAltitude;
+ }
+ else
+ {
+ transmission = 1.0;
+ delta_zv = 0.0;
+ }
+ }
+
+// combined intensity reduction by cloud shading and fog self-shading, corrected for Weber-Fechner perception law
+
+float eqColorFactor;
+ eqColorFactor = 1.0 - 0.1 * delta_zv/vis - (1.0 -scattering);
+
+
+
+
+
+// there's always residual intensity, we should never be driven to zero
+if (eqColorFactor < 0.2) eqColorFactor = 0.2;
+
+
+// postprocessing of haze color
+vec3 hColor = hazeColor;
+
+// high altitude desaturation
+float intensity = length(hColor);
+hColor = intensity * normalize (mix(hColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
+
+// blue hue
+hColor.x = 0.83 * hColor.x;
+hColor.y = 0.9 * hColor.y;
+
+
+
+// further blueshift when in shadow, either cloud shadow, or self-shadow or Earth shadow, dependent on indirect
+// light
+
+float fade_out = max(0.65 - 0.3 *overcast, 0.45);
+intensity = length(hColor);
+hColor = intensity * normalize(mix(hColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,earthShade) ));
+hColor = intensity * normalize(mix(hColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0 - smoothstep(0.3,0.8,eqColorFactor))));
+hColor = hColor * earthShade;
+
+// accounting for overcast and saturation
+
+
+color = ovc * mix(color, hazeColor * earthShade ,smoothstep(-0.1+ctterrain, 0.0+ctterrain, ct)) + (1-ovc) * color;
+color = sat * color + (1.0 - sat) * mix(color, black, smoothstep(0.4+cthorizon,0.2+cthorizon,ct));
+
+
+// the terrain below the horizon gets drawn in one optical thickness
+vec3 terrainHazeColor = eqColorFactor * hColor;
+color = mix(color, terrainHazeColor ,smoothstep(0.01 + ctterrain, 0.0+ctterrain, ct));
+
+// mix fog the skydome with the right amount of haze
+
+color = transmission * color + (1.0-transmission) * eqColorFactor * hColor;
+
+
gl_FragColor = vec4(color, 1.0);
- gl_FragDepth = 0.1;
+ gl_FragDepth = 0.1;
+
}
diff --git a/Shaders/skydome.vert b/Shaders/skydome.vert
index 5c3505f01..58219e6e6 100644
--- a/Shaders/skydome.vert
+++ b/Shaders/skydome.vert
@@ -6,19 +6,30 @@
uniform mat4 osg_ViewMatrix;
-uniform mat4 osg_ViewMatrixInverse;
-
+uniform mat4 osg_ViewMatrixInverse;
+uniform float hazeLayerAltitude;
+uniform float terminator;
+uniform float avisibility;
+uniform float visibility;
+uniform float terrain_alt;
+
varying vec3 rayleigh;
varying vec3 mie;
varying vec3 eye;
-varying float ct;
-
+varying vec3 hazeColor;
+varying float ct;
+//varying float cosphi;
+varying float delta_z;
+varying float alt;
+varying float earthShade;
+
// Dome parameters from FG and screen
const float domeSize = 80000.0;
const float realDomeSize = 100000.0;
const float groundRadius = 0.984503332 * domeSize;
const float altitudeScale = domeSize - groundRadius;
-
+const float EarthRadius = 5800000.0;
+
// Dome parameters when calculating scattering
// Assuming dome size is 5.0
const float groundLevel = 0.984503332 * 5.0;
@@ -35,7 +46,22 @@ uniform float density = 0.5; //1.0
vec3 rayleighK = rK * vec3(5.602, 7.222, 19.644);
vec3 mieK = vec3(mK);
vec3 sunIntensity = 10.0*vec3(120.0, 125.0, 130.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.0;}
+
+return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
+}
+
+
// Find intersections of ray to skydome
// ray must be normalized
// cheight is camera height
@@ -51,7 +77,6 @@ float intersection (in float cheight, in vec3 ray, in float rad2)
float outscatterscale(in float costheta)
{
- if (costheta < -0.12) costheta = -0.12 - 4.0* (costheta+0.12) ;
float x = 1.0 - costheta;
@@ -89,7 +114,12 @@ void main()
// Make it so that 0.0 is ground level and 1.0 is 100km (space) level
float altitude = distance(groundPoint, vec4(0.0, 0.0, 0.0, 1.0));
float scaledAltitude = altitude / realDomeSize;
-
+
+ // the local horizon angle
+ float radiusEye = EarthRadius + altitude;
+ float ctterrain = -sqrt(radiusEye * radiusEye - EarthRadius * EarthRadius)/radiusEye;
+
+
// Camera's position, z is up!
float cameraRealAltitude = groundLevel + heightScale*scaledAltitude;
vec3 camera = vec3(0.0, 0.0, cameraRealAltitude);
@@ -110,21 +140,27 @@ void main()
vec3 lightDirection = gl_LightSource[0].position.xyz;
// Cos theta of camera's position and sample point
- // Since camera is 0,0,z, dot porduct is just the z coordinate
+ // Since camera is 0,0,z, dot product is just the z coordinate
float cameraCosTheta;
// If sample is above camera, reverse ray direction
if(positionDelta.z < 0.0) cameraCosTheta = -positionDelta.z / deltaLength;
else cameraCosTheta = positionDelta.z / deltaLength;
+
float cameraCosTheta1 = -positionDelta.z / deltaLength;
+
// Total attenuation from camera to skydome
float totalCameraScatter = outscatter(cameraCosTheta, scaledAltitude);
- // Do numerical integration of scsattering function from skydome to camera
- vec3 color = vec3(0.0);
+ // Do numerical integration of scattering function from skydome to camera
+ vec3 color = vec3(0.0);
+
+ // no scattering integrations where terrain is later drawn
+ if (cameraCosTheta1 > (ctterrain-0.05))
+ {
for(int i = 0; i < nSamples; i++)
{
// Altitude of the sample point 0...1
@@ -158,24 +194,98 @@ void main()
color += inScatter * deltaLength;
sample += positionDelta;
}
-
+ }
color *= sunIntensity;
ct = cameraCosTheta1;
rayleigh = rayleighK * color;
mie = mieK * color;
eye = gl_NormalMatrix * positionDelta;
-
-
-
- // We need to move the camera so that the dome appears to be centered around earth
+
+ // We need to move the camera so that the dome appears to be centered around earth
// to make the dome render correctly!
float moveDown = -altitude; // Center dome on camera
moveDown += groundRadius;
moveDown += scaledAltitude * altitudeScale; // And move correctly according to altitude
// Vertex transformed correctly so that at 100km we are at space border
- vec4 finalVertex = realVertex - vec4(0.0, 0.0, 1.0, 0.0) * moveDown;
+ vec4 finalVertex = realVertex - vec4(0.0, 0.0, 1.0, 0.0) * moveDown;
+
+ // prepare some stuff for a ground haze layer
+
+ delta_z = hazeLayerAltitude - altitude;
+ alt = altitude;
+
+
+ // establish coordinates relative to sun position
+ vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
+ vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
+ vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0) );
+
+
+ vec3 relVector = normalize(finalVertex.xyz - ep.xyz);
+
+ // and compute the twilight shading
+
+
+ // yprime is the coordinate from/towards terminator
+ float yprime;
+
+ if (alt > hazeLayerAltitude) // we're looking from above and can see far
+ {
+ if (ct < 0.0)
+ {
+ yprime = -dot(relVector,lightHorizon) * altitude/-(ct-0.001);
+ yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
+ }
+ else // the only haze we see looking up is overcast, assume its altitude
+ {
+ yprime = -dot(relVector,lightHorizon) * avisibility;
+ yprime = yprime -sqrt(2.0 * EarthRadius * 10000.0);
+ }
+ }
+ else
+ {yprime = -dot(relVector,lightHorizon) * avisibility;
+ yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
+ }
+
+ if (terminator > 1000000.0){yprime = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);}
+
+ //float edgeAlt = max(hazeLayerAltitude - (alt-terrain_alt)/avisibility * visibility, terrain_alt);
+
+ //yprime = yprime -sqrt(2.0 * EarthRadius * edgeAlt);
+
+ float terminator_width = 200000.0;
+ earthShade = 0.9 * smoothstep((terminator_width+ terminator), (-terminator_width + terminator), yprime) + 0.1;
+
+
+//hazeColor = vec3 (gl_LightSource[0].diffuse.x, gl_LightSource[0].diffuse.y, gl_LightSource[0].diffuse.z);
+
+ //hazeColor.x = hazeColor.x * 0.83;
+ //hazeColor.y = hazeColor.y * 0.9;
+
+ float lightArg = (terminator-yprime)/100000.0;
+ vec4 light_diffuse;
+ light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
+ light_diffuse.g = light_func(lightArg, 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 = 0.0;
+ hazeColor = light_diffuse.xyz;
+
+ float intensity = length(hazeColor.xyz);
+ float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator -sqrt(2.0 * EarthRadius * terrain_alt));
+ float mie_angle = (0.5 * dot(normalize(relVector), normalize(lightFull)) ) + 0.5;
+ 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 - would be best here this causes a box-like bug for some reason
+// so it moved to the fragment shader where it has no issues
+
+//float intensity = length(hazeColor.xyz);
+//hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.8* smoothstep(5000.0, 50000.0, alt)));
+
+
+
// Transform
gl_Position = gl_ModelViewProjectionMatrix * finalVertex;
}
diff --git a/Shaders/terrain-haze.frag b/Shaders/terrain-haze.frag
new file mode 100644
index 000000000..bf14090b9
--- /dev/null
+++ b/Shaders/terrain-haze.frag
@@ -0,0 +1,285 @@
+// -*-C++-*-
+
+// written by Thorsten Renk, Oct 2011, based on default.frag
+// Ambient term comes in gl_Color.rgb.
+varying vec4 diffuse_term;
+varying vec3 normal;
+varying vec3 relPos;
+
+//varying vec3 hazeColor;
+//varying float fogCoord;
+
+uniform sampler2D texture;
+
+//varying float ct;
+//varying float delta_z;
+//varying float alt;
+
+varying float earthShade;
+//varying float yprime;
+//varying float vertex_alt;
+varying float yprime_alt;
+varying float mie_angle;
+
+
+uniform float visibility;
+uniform float avisibility;
+uniform float scattering;
+uniform float terminator;
+uniform float terrain_alt;
+uniform float hazeLayerAltitude;
+uniform float overcast;
+//uniform float altitude;
+uniform float eye_alt;
+
+const float EarthRadius = 5800000.0;
+const float terminator_width = 200000.0;
+
+float alt;
+
+float luminance(vec3 color)
+{
+ return dot(vec3(0.212671, 0.715160, 0.072169), color);
+}
+
+
+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 (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()
+{
+
+// this is taken from default.frag
+ vec3 n;
+ float NdotL, NdotHV, fogFactor;
+ vec4 color = gl_Color;
+ vec3 lightDir = gl_LightSource[0].position.xyz;
+ vec3 halfVector = gl_LightSource[0].halfVector.xyz;
+ vec4 texel;
+ vec4 fragColor;
+ vec4 specular = vec4(0.0);
+ float intensity;
+
+
+
+ vec4 light_specular = gl_LightSource[0].specular;
+
+ // If gl_Color.a == 0, this is a back-facing polygon and the
+ // normal should be reversed.
+ n = (2.0 * gl_Color.a - 1.0) * normal;
+ n = normalize(n);
+
+ NdotL = dot(n, lightDir);
+ if (NdotL > 0.0) {
+ color += diffuse_term * NdotL;
+ NdotHV = max(dot(n, halfVector), 0.0);
+ if (gl_FrontMaterial.shininess > 0.0)
+ specular.rgb = (gl_FrontMaterial.specular.rgb
+ * light_specular.rgb
+ * pow(NdotHV, gl_FrontMaterial.shininess));
+ }
+ color.a = diffuse_term.a;
+ // This shouldn't be necessary, but our lighting becomes very
+ // saturated. Clamping the color before modulating by the texture
+ // is closer to what the OpenGL fixed function pipeline does.
+ color = clamp(color, 0.0, 1.0);
+ texel = texture2D(texture, gl_TexCoord[0].st);
+ fragColor = color * texel + specular;
+
+
+
+// here comes the terrain haze model
+
+
+float delta_z = hazeLayerAltitude - eye_alt;
+float dist = length(relPos);
+
+
+if (dist > 40.0)
+{
+
+alt = 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;
+ //lambda = visibility;
+ vAltitude = min(distance_in_layer,visibility) * 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;}
+ //lambda = visibility;
+ 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)
+ {
+ transmission_arg = transmission_arg + (distance_in_layer/visibility);
+ // this combines the Weber-Fechner intensity
+ eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -scattering);
+
+ }
+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 -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
+earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
+
+// Mie-like factor
+
+if (lightArg < 5.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);
+hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, 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* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,earthShade) ));
+
+// change haze color to blue hue for strong fogging
+//intensity = length(hazeColor);
+hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,eqColorFactor))));
+
+
+// reduce haze intensity when looking at shaded surfaces, only in terminator region
+
+float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
+hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
+
+
+// determine the right mix of transmission and haze
+
+//fragColor.xyz = transmission * fragColor.xyz + (1.0-transmission) * eqColorFactor * hazeColor * earthShade;
+
+fragColor.xyz = mix(eqColorFactor * hazeColor * earthShade, fragColor.xyz,transmission);
+
+gl_FragColor = fragColor;
+
+}
+else // if dist < 40.0 no fogging at all
+{
+gl_FragColor = fragColor;
+}
+
+}
+
diff --git a/Shaders/terrain-haze.vert b/Shaders/terrain-haze.vert
new file mode 100644
index 000000000..f1cd4732d
--- /dev/null
+++ b/Shaders/terrain-haze.vert
@@ -0,0 +1,233 @@
+// -*-C++-*-
+
+// Shader that uses OpenGL state values to do per-pixel lighting
+//
+// The only light used is gl_LightSource[0], which is assumed to be
+// directional.
+//
+// Diffuse colors come from the gl_Color, ambient from the material. This is
+// equivalent to osg::Material::DIFFUSE.
+// Haze part added by Thorsten Renk, Oct. 2011
+
+
+#define MODE_OFF 0
+#define MODE_DIFFUSE 1
+#define MODE_AMBIENT_AND_DIFFUSE 2
+
+// The constant term of the lighting equation that doesn't depend on
+// the surface normal is passed in gl_{Front,Back}Color. The alpha
+// component is set to 1 for front, 0 for back in order to work around
+// bugs with gl_FrontFacing in the fragment shader.
+varying vec4 diffuse_term;
+varying vec3 normal;
+varying vec3 relPos;
+
+varying float earthShade;
+//varying float yprime;
+//varying float vertex_alt;
+varying float yprime_alt;
+varying float mie_angle;
+
+
+
+
+uniform int colorMode;
+uniform float hazeLayerAltitude;
+uniform float terminator;
+uniform float terrain_alt;
+uniform float avisibility;
+uniform float visibility;
+uniform float overcast;
+uniform float scattering;
+
+
+// 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;
+
+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()
+{
+
+ vec4 light_diffuse;
+ vec4 light_ambient;
+
+ //float yprime_alt;
+ float yprime;
+ float lightArg;
+ float intensity;
+ float vertex_alt;
+
+// this code is copied from default.vert
+
+ //vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
+ gl_Position = ftransform();
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ normal = gl_NormalMatrix * gl_Normal;
+ vec4 ambient_color, diffuse_color;
+ if (colorMode == MODE_DIFFUSE) {
+ diffuse_color = gl_Color;
+ ambient_color = gl_FrontMaterial.ambient;
+ } else if (colorMode == MODE_AMBIENT_AND_DIFFUSE) {
+ diffuse_color = gl_Color;
+ ambient_color = gl_Color;
+ } else {
+ diffuse_color = gl_FrontMaterial.diffuse;
+ ambient_color = gl_FrontMaterial.ambient;
+ }
+
+
+
+ // here start computations for the haze layer
+ // 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);
+
+ // branch dependent on daytime
+
+if (terminator < 1000000.0) // the full, sunrise and sunset computation
+{
+ // 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);
+
+ // establish coordinates relative 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
+ 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;
+
+ // directional scattering for low sun
+ if (lightArg < 5.0)
+ {mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
+ else
+ {mie_angle = 1.0;}
+
+
+ light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
+ light_diffuse.g = light_func(lightArg, 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 = 0.0;
+ light_diffuse = light_diffuse * scattering;
+
+ light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
+ light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
+ light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
+ light_ambient.a = 0.0;
+
+
+
+
+// correct ambient light intensity and hue before sunrise
+if (earthShade < 0.5)
+ {
+ light_ambient = light_ambient * (0.4 + 0.6 * smoothstep(0.2, 0.5, earthShade));
+ intensity = length(light_ambient.xyz);
+
+ light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
+
+ intensity = length(light_diffuse.xyz);
+ light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
+ }
+
+
+// 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)
+ {light_diffuse = vec4 (1.0, 1.0, 1.0, 0.0);
+ light_ambient = vec4 (0.33, 0.4, 0.5, 0.0); }
+ else
+ {
+
+ lightArg = (terminator/100000.0 - 10.0)/20.0;
+ light_diffuse.b = 0.78 + lightArg * 0.21;
+ light_diffuse.g = 0.907 + lightArg * 0.091;
+ light_diffuse.r = 0.904 + lightArg * 0.092;
+ light_diffuse.a = 0.0;
+
+ light_ambient.b = 0.41 + lightArg * 0.08;
+ light_ambient.g = 0.333 + lightArg * 0.06;
+ light_ambient.r = 0.316 + lightArg * 0.016;
+ light_ambient.a = 0.0;
+ }
+
+ light_diffuse = light_diffuse * scattering;
+ yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
+
+
+}
+
+
+// default lighting based on texture and material using the light we have just computed
+
+ diffuse_term = diffuse_color* light_diffuse;
+ vec4 constant_term = gl_FrontMaterial.emission + ambient_color *
+ (gl_LightModel.ambient + light_ambient);
+ // Super hack: if diffuse material alpha is less than 1, assume a
+ // transparency animation is at work
+ if (gl_FrontMaterial.diffuse.a < 1.0)
+ diffuse_term.a = gl_FrontMaterial.diffuse.a;
+ else
+ diffuse_term.a = gl_Color.a;
+ // Another hack for supporting two-sided lighting without using
+ // gl_FrontFacing in the fragment shader.
+ gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
+ gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
+}
+
diff --git a/gui/dialogs/local_weather_tiles.xml b/gui/dialogs/local_weather_tiles.xml
index c21db9feb..9863855c4 100644
--- a/gui/dialogs/local_weather_tiles.xml
+++ b/gui/dialogs/local_weather_tiles.xml
@@ -399,7 +399,7 @@
160
100
-
+
@@ -407,9 +407,9 @@
100
90
20
- 30000.0
- 140000.0
- /local-weather/config/max-vis-range-m
+ 9.90348
+ 12.429216196
+ /local-weather/config/aux-max-vis-range-m
dialog-apply
@@ -418,7 +418,17 @@
330
100
-
+
+
+
+
+
+ 380
+ 100
+
+ %.fm
+ true
+ /local-weather/config/max-vis-range-m