diff --git a/Effects/cloud-static.eff b/Effects/cloud-static.eff
index 55543d9c4..737407c79 100644
--- a/Effects/cloud-static.eff
+++ b/Effects/cloud-static.eff
@@ -66,15 +66,15 @@
sampler-2d
0
-
- terminator
- float
-
+
+ terminator
+ float
+
-
- altitude
- float
-
+
+ altitude
+ float
+
true
@@ -132,15 +132,15 @@
sampler-2d
0
-
- terminator
- float
-
+
+ terminator
+ float
+
-
- altitude
- float
-
+
+ altitude
+ float
+
true
diff --git a/Effects/cloud.eff b/Effects/cloud.eff
index fa43fbb0f..47a6efe08 100644
--- a/Effects/cloud.eff
+++ b/Effects/cloud.eff
@@ -86,15 +86,15 @@
float
-
- terminator
- float
-
+
+ terminator
+ float
+
-
- altitude
- float
-
+
+ altitude
+ float
+
true
@@ -164,15 +164,15 @@
float
-
- terminator
- float
-
+
+ terminator
+ float
+
-
- altitude
- float
-
+
+ altitude
+ float
+
true
diff --git a/Effects/rain-layer.eff b/Effects/rain-layer.eff
index ee9c78c5d..e9835076a 100644
--- a/Effects/rain-layer.eff
+++ b/Effects/rain-layer.eff
@@ -78,10 +78,10 @@
float
-
- terminator
- float
-
+
+ terminator
+ float
+
true
@@ -149,10 +149,10 @@
float
-
- terminator
- float
-
+
+ terminator
+ float
+
true
diff --git a/Effects/skydome.eff b/Effects/skydome.eff
index a7070ff55..1c916d08d 100644
--- a/Effects/skydome.eff
+++ b/Effects/skydome.eff
@@ -1,9 +1,9 @@
-
-
- Effects/skydome
-
-
-
+
+
+ Effects/skydome
+
+
+
@@ -12,100 +12,101 @@
-
-
-
-
-
- /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
-
+
+
+
+
+
+ /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
+
-
- rK
- float
-
+
+ overcast
+ float
+
-
- density
- float
-
+
+ saturation
+ float
+
-
- overcast
- float
-
+
+ scattering
+ float
+
-
- saturation
- float
-
+
+ visibility
+ float
+
-
- scattering
- float
-
+
+ hazeLayerAltitude
+ float
+
-
- visibility
- float
-
+
+ terminator
+ float
+
-
- hazeLayerAltitude
- float
-
+
+ avisibility
+ float
+
-
- terminator
- float
-
-
-
- avisibility
- float
-
-
-
- terrain_alt
- float
-
-
-
-
-
-
-
-
- false
- smooth
- back
-
-
-
-
+
+ terrain_alt
+ float
+
+
+
+
+
+
+
+
+ false
+ smooth
+ back
+
+
+
+
diff --git a/Effects/terrain-default.eff b/Effects/terrain-default.eff
index 28a190d22..ea632780d 100644
--- a/Effects/terrain-default.eff
+++ b/Effects/terrain-default.eff
@@ -30,6 +30,13 @@
normalized
+
+ Textures.high/Terrain/snow3.dds
+ linear-mipmap-linear
+ repeat
+ repeat
+ normalized
+
false
0
@@ -40,14 +47,420 @@
+
+
+
+
+
+
+
+
+ /sim/rendering/shaders/skydome
+
+ 4.0
+ /sim/rendering/shaders/landmass
+
+
+
+ 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
+
+
+
+
+
+
+
+
+
+ 1
+ noise
+
+
+ 6
+
+
+
+
+
+
+
+
+
+ Shaders/terrain-haze-detailed.vert
+ Shaders/terrain-haze-detailed.frag
+
+
+ visibility
+ float
+
+
+
+ avisibility
+ float
+
+
+
+ hazeLayerAltitude
+ float
+
+
+
+ scattering
+ float
+
+
+
+ ground_scattering
+ float
+
+
+
+ terminator
+ float
+
+
+
+ terrain_alt
+ float
+
+
+
+ overcast
+ float
+
+
+
+ eye_alt
+ float
+
+
+
+ mysnowlevel
+ float
+
+
+
+ dust_cover_factor
+ float
+
+
+
+ fogstructure
+ float
+
+
+
+ texture
+ sampler-2d
+ 0
+
+
+ NoiseTex
+ sampler-3d
+ 1
+
+
+ snow_texture
+ sampler-2d
+ 6
+
+
+ colorMode
+ int
+ 2
+
+
+ lequal
+ false
+
+
+
+
+
+
+
+
+ /sim/rendering/shaders/skydome
+
+ 4.0
+ /sim/rendering/shaders/landmass
+
+
+
+ 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
+
+
+
+
+
+
+
+
+
+ 1
+ noise
+
+
+ 6
+
+
+
+
+
+
+
+
+
+ Shaders/terrain-haze-detailed.vert
+ Shaders/terrain-haze-detailed.frag
+
+
+ visibility
+ float
+
+
+
+ avisibility
+ float
+
+
+
+ hazeLayerAltitude
+ float
+
+
+
+ scattering
+ float
+
+
+
+ ground_scattering
+ float
+
+
+
+ terminator
+ float
+
+
+
+ terrain_alt
+ float
+
+
+
+ overcast
+ float
+
+
+
+ eye_alt
+ float
+
+
+
+ mysnowlevel
+ float
+
+
+
+ dust_cover_factor
+ float
+
+
+
+ fogstructure
+ float
+
+
+
+ texture
+ sampler-2d
+ 0
+
+
+ NoiseTex
+ sampler-3d
+ 1
+
+
+ snow_texture
+ sampler-2d
+ 6
+
+
+ colorMode
+ int
+ 2
+
+
+ lequal
+ false
+
+
+
+
+
+
@@ -158,6 +571,11 @@
float
+
+ ground_scattering
+ float
+
+
terminator
float
diff --git a/Effects/water.eff b/Effects/water.eff
index ec71fe839..49c0a6630 100644
--- a/Effects/water.eff
+++ b/Effects/water.eff
@@ -109,26 +109,443 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /sim/rendering/shaders/skydome
+
+ 4.0
+ /sim/rendering/shaders/water
+
+
+
+ 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
+
+
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Shaders/water_lightfield.vert
+
+ Shaders/water_lightfield.frag
+
+
+
+
+ water_normalmap
+ sampler-2d
+ 2
+
+
+ water_dudvmap
+ sampler-2d
+ 3
+
+
+
+ sea_foam
+ sampler-2d
+ 5
+
+
+ perlin_normalmap
+ sampler-2d
+ 6
+
+
+ saturation
+ float
+
+
+
+
+
+
+ WindE
+ float
+
+
+
+
+
+ WindN
+ float
+
+
+
+
+
+
+ WaveFreq
+ float
+
+
+
+
+
+ WaveAmp
+ float
+
+
+
+
+
+ WaveSharp
+ float
+
+
+
+
+
+ WaveAngle
+ float
+
+
+
+
+
+ WaveFactor
+ float
+
+
+
+
+
+ WaveDAngle
+ float
+
+
+
+
+
+
+
+
+
+ visibility
+ float
+
+
+
+
+
+ avisibility
+ float
+
+
+
+
+
+ hazeLayerAltitude
+ float
+
+
+
+
+
+ scattering
+ float
+
+
+
+
+
+ ground_scattering
+ float
+
+
+
+ terminator
+ float
+
+
+
+
+
+ terrain_alt
+ float
+
+
+
+ overcast
+ float
+
+
+
+ eye_alt
+ float
+
+
+
+
+ sea_r
+ float
+
+
+
+ sea_g
+ float
+
+
+
+ sea_b
+ float
+
+
+
+
+
+
+
+
+
+
+
+
@@ -742,7 +1159,6 @@
-
Overcast
diff --git a/Environment/environment.xml b/Environment/environment.xml
index 1ae19dc53..b2b65d2bb 100644
--- a/Environment/environment.xml
+++ b/Environment/environment.xml
@@ -333,12 +333,22 @@
0.05
+ 0.148
+ 0.27
+ 0.3
16000.0
+ 0.0
2000.0
1000000.0
0.0
-
+ 3200.0
+ 0.0
+
+
+ 0.7
+ 0.0
+
diff --git a/Nasal/local_weather/cloud_definitions.nas b/Nasal/local_weather/cloud_definitions.nas
index 2f6ffd5d4..51843548c 100644
--- a/Nasal/local_weather/cloud_definitions.nas
+++ b/Nasal/local_weather/cloud_definitions.nas
@@ -410,7 +410,7 @@ else if (type == "Cumulus bottom"){
cloudAssembly.num_tex_y = 1;
#characterize the cloud
- cloudAssembly.bottom_shade = 1.0;
+ cloudAssembly.bottom_shade = 0.5;
cloudAssembly.n_sprites = 4;
cloudAssembly.min_width = 600.0 * mult;
cloudAssembly.max_width = 800.0 * mult;
@@ -452,7 +452,7 @@ else if (type == "Congestus bottom"){
cloudAssembly.num_tex_y = 1;
#characterize the cloud
- cloudAssembly.bottom_shade = 0.7;
+ cloudAssembly.bottom_shade = 0.5;
cloudAssembly.n_sprites = 4;
cloudAssembly.min_width = 1100.0 * mult;
cloudAssembly.max_width = 1400.0 * mult;
diff --git a/Nasal/local_weather/cloud_placement_lowlevel.nas b/Nasal/local_weather/cloud_placement_lowlevel.nas
new file mode 100644
index 000000000..5232fe39e
--- /dev/null
+++ b/Nasal/local_weather/cloud_placement_lowlevel.nas
@@ -0,0 +1,243 @@
+########################################################
+# routines to set up, transform and manage advanced weather
+# Thorsten Renk, April 2012
+########################################################
+
+# function purpose
+#
+# create_undulatus to create an undulating cloud pattern
+# create_cumulus_alleys to create an alley pattern of Cumulus clouds
+# create_layer to create a cloud layer with optional precipitation
+
+###########################################################
+# place an undulatus pattern
+###########################################################
+
+var create_undulatus = func (type, blat, blong, balt, alt_var, nx, xoffset, edgex, x_var, ny, yoffset, edgey, y_var, und_strength, direction, tri) {
+
+var flag = 0;
+var path = "Models/Weather/blank.ac";
+local_weather.calc_geo(blat);
+var dir = direction * math.pi/180.0;
+
+var ymin = -0.5 * ny * yoffset;
+var xmin = -0.5 * nx * xoffset;
+var xinc = xoffset * (tri-1.0) /ny;
+
+var jlow = int(nx*edgex);
+var ilow = int(ny*edgey);
+
+var und = 0.0;
+var und_array = [];
+
+for (var i=0; i(nx-jlow-1))) and ((i(ny-ilow-1)))) # select a small or no cloud
+ {
+ if (rn > 2.0) {flag = 1;} else {path = select_cloud_model(type,"small");}
+ }
+ if ((j(nx-jlow-1)) or (i(ny-ilow-1)))
+ {
+ if (rn > 5.0) {flag = 1;} else {path = select_cloud_model(type,"small");}
+ }
+ else { # select a large cloud
+ if (rn > 5.0) {flag = 1;} else {path = select_cloud_model(type,"large");}
+ }
+
+
+ if (flag==0){
+ if (thread_flag == 1)
+ {create_cloud_vec(path, lat, long, alt, 0.0);}
+ else
+ {local_weather.create_cloud(path, lat, long, alt, 0.0);}
+
+
+ }
+ }
+
+ }
+
+}
+
+
+
+###########################################################
+# place a Cumulus alley pattern
+###########################################################
+
+var create_cumulus_alleys = func (blat, blon, balt, alt_var, nx, xoffset, edgex, x_var, ny, yoffset, edgey, y_var, und_strength, direction, tri) {
+
+var flag = 0;
+var path = "Models/Weather/blank.ac";
+local_weather.calc_geo(blat);
+var dir = direction * math.pi/180.0;
+
+var ymin = -0.5 * ny * yoffset;
+var xmin = -0.5 * nx * xoffset;
+var xinc = xoffset * (tri-1.0) /ny;
+
+var jlow = int(nx*edgex);
+var ilow = int(ny*edgey);
+
+var und = 0.0;
+var und_array = [];
+
+var spacing = 0.0;
+var spacing_array = [];
+
+
+for (var i=0; i(nx-jlow-1))) and ((i(ny-ilow-1)))) # select a small or no cloud
+ {
+ if (rn > 2.0) {flag = 1;} else {strength = 0.3 + rand() * 0.5;}
+ }
+ if ((j(nx-jlow-1)) or (i(ny-ilow-1)))
+ {
+ if (rn > 5.0) {flag = 1;} else {strength = 0.7 + rand() * 0.5;}
+ }
+ else { # select a large cloud
+ if (rn > 5.0) {flag = 1;} else {strength = 1.1 + rand() * 0.6;}
+ }
+
+
+ if (flag==0){create_detailed_cumulus_cloud(lat, lon, alt, strength); }
+ }
+
+ }
+
+}
+
+
+###########################################################
+# place a cloud layer
+###########################################################
+
+var create_layer = func (type, blat, blon, balt, bthick, rx, ry, phi, density, edge, rainflag, rain_density) {
+
+
+var i = 0;
+var area = math.pi * rx * ry;
+var circ = math.pi * (rx + ry); # that's just an approximation
+var n = int(area/80000000.0 * 100 * density);
+var m = int(circ/63000.0 * 40 * rain_density);
+var path = "Models/Weather/blank.ac";
+
+#print("density: ",n);
+
+phi = phi * math.pi/180.0;
+
+if (contains(local_weather.cloud_vertical_size_map, type))
+ {var alt_offset = cloud_vertical_size_map[type]/2.0 * m_to_ft;}
+ else {var alt_offset = 0.0;}
+
+while(i ((1.0 - edge) * (1.0- edge)))
+ {
+ if (rand() > 0.4) {
+ path = select_cloud_model(type,"small");
+ if (thread_flag == 1)
+ {create_cloud_vec(path, lat, lon, alt, 0.0);}
+ else
+ {compat_layer.create_cloud(path, lat, lon, alt, 0.0);}
+ }
+ }
+ else {
+ path = select_cloud_model(type,"large");
+ if (thread_flag == 1)
+ {create_cloud_vec(path, lat, lon, alt, 0.0);}
+ else
+ {compat_layer.create_cloud(path, lat, lon, alt, 0.0);}
+ }
+ i = i + 1;
+ }
+ }
+
+i = 0;
+
+if (rainflag ==1){
+
+if (local_weather.hardcoded_clouds_flag == 1) {balt = balt + local_weather.offset_map[type]; }
+
+ while(i c.top_shade) {c.bottom_shade = c.top_shade;}
+c.middle_shade = c.top_shade;
+
# write the actual cloud into the scenery
@@ -812,8 +822,8 @@ var p = props.Node.new({ "layer" : 0,
"max-sprite-height-m": c.max_height,
"num-sprites": c.n_sprites,
"min-bottom-lighting-factor": c.bottom_shade,
- "min-middle-lighting-factor": 0.9,
- "min-top-lighting-factor": 1.0,
+ "min-middle-lighting-factor": c.middle_shade,
+ "min-top-lighting-factor": c.top_shade,
"min-shade-lighting-factor": c.bottom_shade,
"texture": c.texture_sheet,
"num-textures-x": c.num_tex_x,
diff --git a/Nasal/local_weather/local_weather.nas b/Nasal/local_weather/local_weather.nas
index 95a61e4c0..534da9704 100644
--- a/Nasal/local_weather/local_weather.nas
+++ b/Nasal/local_weather/local_weather.nas
@@ -34,15 +34,13 @@
# create_detailed_cumulus_cloud to place multiple cloudlets into a box based on a size parameter
# create_cumulonimbus_cloud to place multiple cloudlets into a box
# create_cumulonimbus_cloud_rain to place multiple cloudlets into a box and add a rain layer beneath
-# create_cumosys wrapper to place a convective cloud system based on terrain coverage
+# create_cumosys (wrapper to place a convective cloud system based on terrain coverage)
# cumulus_loop to place 25 Cumulus clouds each frame
# create_cumulus to place a convective cloud system based on terrain coverage
# recreate_cumulus to respawn convective clouds as part of the convective dynamics algorithm
# cumulus_exclusion_layer to create a layer with 'holes' left for thunderstorm placement
# create_rise_clouds to create a barrier cloud system
# create_streak to create a cloud streak
-# create_undulatus to create an undulating cloud pattern
-# create_layer to create a cloud layer with optional precipitation
# create_hollow_layer to create a cloud layer in a hollow cylinder (better for performance)
# create_cloudbox to create a sophisticated cumulus cloud with different textures (experimental)
# terrain_presampling_start to initialize terrain presampling
@@ -640,29 +638,65 @@ if (vis > max_vis_range)
if (scattering_shader_flag == 1)
{
- var rayleigh = 0.0003 ;
- var mie = 0.003;
+ #var rayleigh = 0.0003 ;
+ #var mie = 0.003;
+ #var density = 0.3;
+
+ # values to be used with new exposure filter
+ var rayleigh = 0.0003;
+ var mie = 0.005;
var density = 0.3;
+ var vis_factor = (vis - 30000.0)/90000.0;
+ if (vis_factor < 0.0) {vis_factor = 0.0;}
+ if (vis_factor > 1.0) {vis_factor = 1.0;}
+
+ #if (altitude < 30000.0)
+ # {
+ # rayleigh = 0.0004 - altitude/30000.0 * 0.0001;
+ # mie = 0.004 - altitude/30000.0 * 0.001;
+ # mie = 0.002 - altitude/30000.0 * 0.001;
+ # }
+ #else if (altitude < 60000.0)
+ # {
+ # rayleigh = 0.0003 - (altitude-30000.0)/30000.0 * 0.0001;
+ # mie = 0.003 - (altitude-30000.0)/30000.0 * 0.001;
+ # }
+ #else if (altitude < 85000.0)
+ # {
+ # rayleigh = 0.0002 - (altitude-60000.0)/25000.0 * 0.0001;
+ # mie = 0.002;
+ # }
+ #else
+ # {rayleigh = 0.0001; mie = 0.002;}
-
- if (altitude < 30000.0)
+ if (altitude < 36000.0)
{
- rayleigh = 0.0004 - altitude/30000.0 * 0.0001;
- mie = 0.004 - altitude/30000.0 * 0.001;
- }
- else if (altitude < 60000.0)
- {
- rayleigh = 0.0003 - (altitude-30000.0)/30000.0 * 0.0001;
- mie = 0.003 - (altitude-30000.0)/30000.0 * 0.001;
+ rayleigh = 0.0003 - 0.0001 * vis_factor;
+ mie = 0.005 - vis_factor * 0.002;
}
else if (altitude < 85000.0)
{
- rayleigh = 0.0002 - (altitude-60000.0)/25000.0 * 0.0001;
- mie = 0.002;
+ rayleigh = (0.0003 - 0.0001 * vis_factor) - (altitude-36000.0)/49000.0 * 0.0001;
+ mie = 0.005 - vis_factor * 0.002 - (altitude-36000.0)/49000.0 * 0.002;
}
else
- {rayleigh = 0.0001; mie = 0.002;}
+ {rayleigh = 0.0002 - 0.0001 * vis_factor; mie = 0.003 - vis_factor * 0.002;}
+
+ # now the pollution factor
+
+ if (altitude < alt1)
+ {
+ rayleigh = rayleigh +0.0003 * air_pollution_norm + 0.0004 * air_pollution_norm * (1.0 - (altitude/alt1) * (altitude/alt1));
+ density = density + 0.05 * air_pollution_norm + 0.05 * air_pollution_norm * (1.0 - (altitude/alt1) * (altitude/alt1));
+ }
+ else
+ {
+ rayleigh = rayleigh + 0.0003 * air_pollution_norm;
+ density = density + 0.05 * air_pollution_norm;
+ }
+
+
}
# otherwise compute normal skydome shader parameters
@@ -725,6 +759,8 @@ if (scattering_shader_flag == 1)
local_weather.setScattering(scatt);
local_weather.setOvercast(ovcst);
+
+
# now check if an effect volume writes the property and set only if not
@@ -928,10 +964,15 @@ 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
+# set scattering on the ground - this doesn't affect fog but is diffuse and specular light reduction
+# so it is stronger than normal scattering
+
+var scatt_ground = 2.0 * (scatt_max - 0.5);
+if (scatt_ground < 0.0) {scatt_ground = 0.0;}
+
+setprop("/environment/surface/scattering", scatt_ground);
if (getprop(lw~"interpolation-loop-flag") ==1) {settimer(interpolation_loop, interpolation_loop_time);}
@@ -1506,6 +1547,7 @@ if (path == "new") # we have to switch to new cloud generating routines
local_weather.cloudAssembly.lat = lat;
local_weather.cloudAssembly.lon = long;
local_weather.cloudAssembly.alt = alt;
+ local_weather.cloudAssembly.top_shade = top_shade;
#print(lat," ",long, " ", alt);
@@ -2564,158 +2606,10 @@ for (var i=0; i(nx-jlow-1))) and ((i(ny-ilow-1)))) # select a small or no cloud
- {
- if (rn > 2.0) {flag = 1;} else {path = select_cloud_model(type,"small");}
- }
- if ((j(nx-jlow-1)) or (i(ny-ilow-1)))
- {
- if (rn > 5.0) {flag = 1;} else {path = select_cloud_model(type,"small");}
- }
- else { # select a large cloud
- if (rn > 5.0) {flag = 1;} else {path = select_cloud_model(type,"large");}
- }
- if (flag==0){
- if (thread_flag == 1)
- {create_cloud_vec(path, lat, long, alt, 0.0);}
- else
- {compat_layer.create_cloud(path, lat, long, alt, 0.0);}
-
-
- }
- }
-
- }
-
-}
-###########################################################
-# place a cloud layer
-###########################################################
-
-var create_layer = func (type, blat, blon, balt, bthick, rx, ry, phi, density, edge, rainflag, rain_density) {
-
-
-var i = 0;
-var area = math.pi * rx * ry;
-var circ = math.pi * (rx + ry); # that's just an approximation
-var n = int(area/80000000.0 * 100 * density);
-var m = int(circ/63000.0 * 40 * rain_density);
-var path = "Models/Weather/blank.ac";
-
-#print("density: ",n);
-
-phi = phi * math.pi/180.0;
-
-if (contains(cloud_vertical_size_map, type))
- {var alt_offset = cloud_vertical_size_map[type]/2.0 * m_to_ft;}
- else {var alt_offset = 0.0;}
-
-while(i ((1.0 - edge) * (1.0- edge)))
- {
- if (rand() > 0.4) {
- path = select_cloud_model(type,"small");
- if (thread_flag == 1)
- {create_cloud_vec(path, lat, lon, alt, 0.0);}
- else
- {compat_layer.create_cloud(path, lat, lon, alt, 0.0);}
- }
- }
- else {
- path = select_cloud_model(type,"large");
- if (thread_flag == 1)
- {create_cloud_vec(path, lat, lon, alt, 0.0);}
- else
- {compat_layer.create_cloud(path, lat, lon, alt, 0.0);}
- }
- i = i + 1;
- }
- }
-
-i = 0;
-
-if (rainflag ==1){
-
-if (local_weather.hardcoded_clouds_flag == 1) {balt = balt + local_weather.offset_map[type]; }
-
- while(i (ivector_size-1)) {index = 0;}
+
+# pick one point for distance re-computation per loop iteration
+
+var viewpos = geo.aircraft_position();
+var ppos = geo.Coord.new();
+var s = interpolation_vector[index];
+ppos.set_latlon(s.lat,s.lon,0.0);
+s.distance = viewpos.distance_to(ppos);
+
+
+# interpolate the rgb values
+
+
+var sum_r = 0.148/1000000.0;
+var sum_g = 0.27/1000000.0;
+var sum_b = 0.3/1000000.0;
+var sum_norm = 1.0/1000000.0; # default point is 1000 km away
+
+for (var i = 0; i < ivector_size; i = i + 1)
+ {
+ s = interpolation_vector[i];
+ sum_norm = sum_norm + 1./s.distance * s.weight;
+ sum_r = sum_r + s.r/s.distance * s.weight;
+ sum_g = sum_g + s.g/s.distance * s.weight;
+ sum_b = sum_b + s.b/s.distance * s.weight;
+
+ #print("index: ", i, " dist: ", s.distance, " r: ", s.r);
+ }
+
+var r = sum_r / sum_norm;
+var g = sum_g / sum_norm;
+var b = sum_b / sum_norm;
+
+setprop("/environment/sea/color_r", r);
+setprop("/environment/sea/color_g", g);
+setprop("/environment/sea/color_b", b);
+
+
+settimer( func {sea_color_loop(index+1) },1.0);
+}
+
+var ivector_size = 0;
+var interpolation_vector = [];
diff --git a/Nasal/local_weather/weather_tiles.nas b/Nasal/local_weather/weather_tiles.nas
index e3d28581a..62d501ac5 100644
--- a/Nasal/local_weather/weather_tiles.nas
+++ b/Nasal/local_weather/weather_tiles.nas
@@ -54,6 +54,10 @@ var dir_index = getprop(lw~"tiles/tmp/dir-index");
local_weather.assemble_effect_array();
+# reset lighting
+
+local_weather.top_shade = 1.0;
+
if (local_weather.debug_output_flag == 1)
{print("Finished setting up tile type ",current_code, " in direction ",dir_index);}
@@ -104,16 +108,16 @@ alt_offset = 0.0;
#local_weather.create_cumosys(blat,blon, 3000.0, get_n(strength), 20000.0);
#create_2_8_altocumulus_streaks(blat, blon, 12000+alt_offset, alpha) ;
-#create_2_8_altocumulus_streaks(blat, blon, 12000+alt_offset, alpha) ;
+# create_2_8_altocumulus_streaks(blat, blon, 12000+alt_offset, alpha) ;
#create_6_8_stratus(blat, blon, 3000+alt_offset, alpha) ;
#create_4_8_tstratus_patches(blat, blon, 5000+alt_offset, alpha) ;
#create_4_8_sstratus_patches(blat, blon, 5000+alt_offset, alpha) ;
#create_4_8_cirrostratus_patches(blat, blon, 5000+alt_offset, alpha) ;
#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_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.0, alpha, 0.3) ;
#create_8_8_tstratus(blat, blon, 5000+alt_offset, alpha);
@@ -125,11 +129,16 @@ alt_offset = 0.0;
#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_cirrus(blat, blon, 30000.0, alpha);
-#create_4_8_altocumulus_perlucidus(blat, blon, 5000+alt_offset, alpha) ;
+#create_2_8_altocumulus_perlucidus(blat, blon, 12000+alt_offset, alpha) ;
-#create_detailed_stratocumulus_bank(blat, blon, 4000+alt_offset,alpha);
+# create_detailed_stratocumulus_bank(blat, blon, 4000,alpha);
+
+local_weather.top_shade = 0.6;
+
+create_4_8_cumulus_alleys(blat, blon, 3000.0, alpha);
+# create_4_8_cirrostratus_undulatus(blat, blon, 25000.0, alpha);
#store convective altitude and strength
@@ -191,6 +200,9 @@ var alt = spread * 400;
var strength = 0.0;
+# bias Cumulus clouds towards smaller sizes due to lack of water vapour and convection
+local_weather.convective_size_bias = -0.2 - rand() * 0.1;
+
var rn = rand();
if (rand() < small_scale_persistence)
@@ -198,9 +210,9 @@ if (rand() < small_scale_persistence)
else
{rnd_store = rn;}
-#rn = 0.1;
+# rn = 0.1;
-if (rn > 0.833)
+if (rn > 0.875)
{
# cloud scenario 1: weak cumulus development and blue thermals
@@ -220,7 +232,7 @@ if (rn > 0.833)
# 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.666)
+else if (rn > 0.75)
{
# cloud scenario 2: some Cirrocumulus patches
@@ -234,7 +246,7 @@ else if (rn > 0.666)
# 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.5)
+else if (rn > 0.625)
{
# cloud scenario 3: Cirrostratus undulatus over weak cumulus
@@ -247,7 +259,7 @@ else if (rn > 0.5)
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.333)
+else if (rn > 0.5)
{
# cloud scenario 4: Cirrostratus undulatus streak
@@ -259,7 +271,7 @@ else if (rn > 0.333)
# 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.166)
+else if (rn > 0.375)
{
# cloud scenario 5: Cirrus
@@ -274,13 +286,33 @@ else if (rn > 0.166)
# 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)
+else if (rn > 0.25)
{
# 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);
}
+else if (rn > 0.125)
+ {
+ # cloud scenario 7: clear
+
+ 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, 1.0, alt+alt_offset, alt+alt_offset + 2500.0);
+ }
+else if (rn > 0.0)
+ {
+ # cloud scenario 8: Cirrocumulus
+
+ if (rand() > 0.7) # this is very expensive, so don't do it for every tile
+ {create_2_8_cirrocumulus_patches(blat, blon, alt + alt_offset + 26000.0, alpha);}
+ else
+ {create_2_8_cirrocumulus(blat, blon, alt + alt_offset + 26000.0, alpha);}
+
+ # and specify the atmosphere
+ local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.2, alt+alt_offset +24000.0, alt+alt_offset + 26000.0, 0.9, alt+alt_offset, alt+alt_offset + 2500.0);
+
+ }
+
# store convective altitude and strength
@@ -347,7 +379,7 @@ else
# rn = 0.1;
-if (rn > 0.8)
+if (rn > 0.875)
{
# cloud scenario 1: possible Cirrus over Cumulus
strength = 0.2 + rand() * 0.4;
@@ -372,7 +404,7 @@ if (rn > 0.8)
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 + 30000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.6)
+else if (rn > 0.75)
{
# cloud scenario 2: Cirrostratus over weak Cumulus
@@ -385,7 +417,7 @@ else if (rn > 0.6)
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.2, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.4)
+else if (rn > 0.625)
{
# cloud scenario 3: Cirrocumulus sheet over Cumulus
@@ -404,7 +436,7 @@ else if (rn > 0.4)
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 + 24000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.2)
+else if (rn > 0.5)
{
# cloud scenario 4: Cirrostratus undulatus over weak Cumulus
@@ -416,7 +448,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 +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.0)
+else if (rn > 0.375)
{
# cloud scenario 5: some scattered Altocumuli over Cumulus
@@ -430,6 +462,43 @@ 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 +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
+else if (rn > 0.25)
+ {
+ # cloud scenario 6: Cirrocumulus over Cumulus
+ strength = 0.2 + rand() * 0.1;
+ local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
+
+ if (rand() > 0.8) # this is very expensive, so don't do it for every tile
+ {create_2_8_cirrocumulus_patches(blat, blon, alt + alt_offset + 26000.0, alpha);}
+ else
+ {create_2_8_cirrocumulus(blat, blon, alt + alt_offset + 26000.0, alpha);}
+
+ # and specify the atmosphere
+ local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.3, alt+alt_offset +24000.0, alt+alt_offset + 26000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
+ }
+else if (rn > 0.125)
+ {
+ # cloud scenario 7: just Cumulus
+
+ strength = 0.3 + rand() * 0.1;
+ local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.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 +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
+ }
+else if (rn > 0.0)
+ {
+ # cloud scenario 8: Altocumulus Perlucidus over Cumulus
+
+ strength = 0.2 + rand() * 0.1;
+ local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
+
+ create_2_8_altocumulus_perlucidus(blat, blon, alt + alt_offset + 12000.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);
+ }
+
# store convective altitude and strength
@@ -488,13 +557,17 @@ var strength = 0.0;
var rn = rand();
+
+
if (rand() < small_scale_persistence)
{rn = rnd_store;}
else
{rnd_store = rn;}
-if (rn > 0.888)
+# rn = 0.05;
+
+if (rn > 0.9)
{
# cloud scenario 1: Altocumulus patch over weak Cumulus
strength = 0.1 + rand() * 0.1;
@@ -509,7 +582,7 @@ if (rn > 0.888)
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);
}
-else if (rn > 0.777)
+else if (rn > 0.8)
{
# cloud scenario 2: Altocumulus streaks
strength = 0.15 + rand() * 0.2;
@@ -526,7 +599,7 @@ else if (rn > 0.777)
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);
}
-else if (rn > 0.666)
+else if (rn > 0.7)
{
# cloud scenario 3: Cirrus
@@ -539,7 +612,7 @@ else if (rn > 0.666)
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 + 22000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.555)
+else if (rn > 0.6)
{
# cloud scenario 4: thin Stratus streaks
@@ -552,7 +625,7 @@ else if (rn > 0.555)
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);
}
-else if (rn > 0.444)
+else if (rn > 0.5)
{
# cloud scenario 5: scattered Stratus
@@ -567,7 +640,7 @@ else if (rn > 0.444)
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.2, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.333)
+else if (rn > 0.4)
{
# cloud scenario 6: Cirrocumulus sheets
@@ -590,7 +663,7 @@ else if (rn > 0.333)
# 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.85, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.222)
+else if (rn > 0.3)
{
# cloud scenario 7: Thin Cirrocumulus sheets over weak Cumulus
@@ -603,7 +676,7 @@ else if (rn > 0.222)
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.05, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.111)
+else if (rn > 0.2)
{
# cloud scenario 8: Altocumulus perlucidus
@@ -615,7 +688,7 @@ else if (rn > 0.111)
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.25, alt+alt_offset +26000.0, alt+alt_offset + 30000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.0)
+else if (rn > 0.1)
{
# cloud scenario 9: Cumulus, Altocumulus and Cirrus
@@ -630,7 +703,16 @@ 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 +26000.0, alt+alt_offset + 30000.0, 0.8, alt+alt_offset, alt+alt_offset + 2500.0);
}
+else if (rn > 0.0)
+ {
+ # cloud scenario 10: Cumulus alleys and Cirrus
+ create_4_8_cumulus_alleys(blat, blon, alt+ alt_offset, alpha);
+ create_4_8_cirrus(blat, blon, alt + alt_offset + 35000.0, alpha);
+
+ # 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.8, alt+alt_offset, alt+alt_offset + 2500.0);
+ }
# store convective altitude and strength
@@ -700,8 +782,10 @@ if (rand() < small_scale_persistence)
else
{rnd_store = rn;}
+# rn = 0.05;
-if (rn > 0.857)
+
+if (rn > 0.875)
{
# cloud scenario 1: low Stratocumulus, thin streaks above
@@ -716,7 +800,7 @@ if (rn > 0.857)
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.75, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.714)
+else if (rn > 0.75)
{
# cloud scenario 2: weak Cumulus, Stratus undulatus above
@@ -730,7 +814,7 @@ else if (rn > 0.714)
# 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);
}
-else if (rn > 0.571)
+else if (rn > 0.625)
{
# cloud scenario 3: Stratocumulus banks with patches above
@@ -742,7 +826,7 @@ else if (rn > 0.571)
# 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.7, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.428)
+else if (rn > 0.5)
{
# cloud scenario 4: structured Stratus
@@ -753,7 +837,7 @@ else if (rn > 0.428)
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.25, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.7, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.285)
+else if (rn > 0.375)
{
# cloud scenario 5: Stratus blending with Cumulus with Cirrocumulus above
@@ -767,7 +851,7 @@ else if (rn > 0.285)
# 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 +20000.0, alt+alt_offset + 25000.0, 0.75, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else if (rn > 0.142)
+else if (rn > 0.250)
{
# cloud scenario 6: small Stratocumulus banks
@@ -781,7 +865,7 @@ else if (rn > 0.142)
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.3, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.75, alt+alt_offset, alt+alt_offset + 2500.0);
}
-else
+else if (rn > 0.125)
{
# cloud scenario 7: blended structured and unstructured Stratiform clouds
@@ -793,6 +877,19 @@ else
# and specify the atmosphere
local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.2, alt+alt_offset +20000.0, alt+alt_offset + 25000.0, 0.75, alt+alt_offset, alt+alt_offset + 2500.0);
}
+else if (rn > 0.0)
+ {
+ # cloud scenario 8: Cumulus alleys beneath a high dense stratus cover
+
+ local_weather.top_shade = 0.7;
+ create_4_8_cumulus_alleys(blat, blon, alt+ alt_offset, alpha);
+
+ local_weather.top_shade = 1.0;
+ create_6_8_tstratus_undulatus(blat, blon, alt+alt_offset + 6000.0,alpha);
+
+ # and specify the atmosphere
+ local_weather.set_atmosphere_ipoint(blat, blon, vis + 10000.0, alt+alt_offset, vis + 15000.0, 0.5, alt+alt_offset +5500.0, alt+alt_offset + 6500.0, 0.65, alt+alt_offset + 6000.0, alt+alt_offset + 7500.0);
+ }
@@ -1081,6 +1178,9 @@ local_weather.set_weather_station(blat, blon, alt_offset, vis, T, D, p * hp_to_i
var alt = spread * 400.0;
var strength = 0.0;
+# bias Cumulus clouds towards larger sizes due to strong convection
+local_weather.convective_size_bias = 0.3 + rand() * 0.1;
+
var rn = rand();
if (rand() < small_scale_persistence)
@@ -1093,7 +1193,7 @@ else
if (rn > 0.5)
{
# cloud scenario 1: strong Cumulus development
- strength = 0.8 + rand() * 0.2;
+ strength = 0.6 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
# and specify the atmosphere
@@ -1104,7 +1204,7 @@ else if (rn > 0.0)
{
# cloud scenario 2: Cirrocumulus sheets over Cumulus
- strength = 0.6 + rand() * 0.2;
+ strength = 0.5 + rand() * 0.1;
local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
for (var i = 0; i < 2; i = i + 1)
@@ -2293,19 +2393,23 @@ for (var i = n; i 0.66)
+ if (rn > 0.75)
{create_2_8_tstratus(blat, blon, altitude+metar_alt_offset, alpha);}
- else if (rn > 0.33)
+ else if (rn > 0.5)
{create_2_8_sstratus(blat, blon, altitude+metar_alt_offset, alpha);}
- else
+ else if (rn > 0.25)
+ {create_2_8_altocumulus_perlucidus(blat, blon, altitude+metar_alt_offset, alpha);}
+ else if (rn > 0.0)
{create_2_8_alttstratus(blat, blon, altitude+metar_alt_offset, alpha);}
}
else
{
var rn = rand();
- if (rn > 0.5)
+ if (rn > 0.9)
+ {create_2_8_cirrocumulus_patches(blat, blon, altitude+metar_alt_offset, alpha);}
+ if (rn > 0.4)
{create_2_8_cirrocumulus(blat, blon, altitude+metar_alt_offset, alpha);}
- else
+ else if (rn > 0.0)
{create_2_8_alttstratus(blat, blon, altitude+metar_alt_offset, alpha);}
}
@@ -2627,7 +2731,7 @@ if (rain > 0.1)
}
else
{
- local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, alt-1500.0, alt+900.0, 2000.0, -1 , -1, -1, -1,0 ,-1);
+ local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, alt, alt+900.0, 2000.0, -1 , -1, -1, -1,0 ,-1);
local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, 0.0, alt, -1, rain , -1, -1, -1,0 ,0.9);
}
@@ -3065,6 +3169,23 @@ else
}
+var create_4_8_cumulus_alleys = func (lat, lon, alt, alpha) {
+
+
+var phi = alpha * math.pi/180.0;
+var x = 2.0 * (rand()-0.5) * 5000;
+var y = 2.0 * (rand()-0.5) * 5000;
+var tri = 1.0 + 0.4 * rand();
+
+# create_cumulus_alleys = func (blat, blong, balt, alt_var, nx, xoffset, edgex, x_var, ny, yoffset, edgey, y_var, und_strength, direction, tri)
+
+local_weather.create_cumulus_alleys(lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt, 0.0, 9, 3500.0,0.2, 500.0, 30 ,1130.0, 0.2, 300.0, 1000.0, alpha,tri);
+
+}
+
+
+
+
var create_4_8_cirrus = func (lat, lon, alt, alpha) {
var phi = alpha * math.pi/180.0;
@@ -3133,6 +3254,22 @@ for (var i=0; i<8; i=i+1)
+var create_2_8_altocumulus_perlucidus = func (lat, lon, alt, alpha) {
+
+if (local_weather.hardcoded_clouds_flag == 1) {alt = alt - 300.0;}
+
+var phi = alpha * math.pi/180.0;
+
+for (var i=0; i<40; i=i+1)
+ {
+ var x = 2.0 * (rand()-0.5) * 18000;
+ var y = 2.0 * (rand()-0.5) * 18000;
+ var beta = (rand() -0.5) * 180.0;
+ local_weather.create_streak("Altocumulus perlucidus",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,300.0,2,1400.0,0.1,900.0,2,1400.0,0.1,900.0,alpha+beta,1.0);
+
+ }
+
+}
@@ -3386,14 +3523,14 @@ if (local_weather.hardcoded_clouds_flag == 0)
}
else
{
- local_weather.create_streak("Stratocumulus",lat+get_lat(x,y+7500,phi), lon+get_lon(x,y+7500,phi), alt-1000.0 ,500.0,m,1100.0,0.1,400.0,n,1100.0,0.1,400.0,alpha+90.0+beta,tri);
+ local_weather.create_streak("Stratocumulus",lat+get_lat(x,y+7500,phi), lon+get_lon(x,y+7500,phi), alt-local_weather.offset_map["Congestus"] + 400.0 ,500.0,m,1100.0,0.1,400.0,n,1100.0,0.1,400.0,alpha+90.0+beta,tri);
- local_weather.create_streak("Stratocumulus",lat+get_lat(x,y-7500,phi), lon+get_lon(x,y-7500,phi), alt-1000.0 ,500.0,m,1100.0,0.1,400.0,n,1100.0,0.1,400.0,alpha+270.0+beta,tri);
+ local_weather.create_streak("Stratocumulus",lat+get_lat(x,y-7500,phi), lon+get_lon(x,y-7500,phi), alt-local_weather.offset_map["Congestus"] + 400.0 ,500.0,m,1100.0,0.1,400.0,n,1100.0,0.1,400.0,alpha+270.0+beta,tri);
- local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y+5250,phi), lon+get_lon(x,y+5250,phi), alt-1000.0,0.0,m+1,700.0,0.2,400.0,n+1,700.0,0.0,400.0,alpha+90.0+beta,tri);
+ local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y+5250,phi), lon+get_lon(x,y+5250,phi), alt-local_weather.offset_map["Stratus"],0.0,m+1,700.0,0.2,400.0,n+1,700.0,0.0,400.0,alpha+90.0+beta,tri);
- local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y-5250,phi), lon+get_lon(x,y-5250,phi), alt-1000.0,0.0,m+1,700.0,0.2,400.0,n+1,700.0,0.0,400.0,alpha+270.0+beta,tri);
+ local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y-5250,phi), lon+get_lon(x,y-5250,phi), alt-local_weather.offset_map["Stratus"],0.0,m+1,700.0,0.2,400.0,n+1,700.0,0.0,400.0,alpha+270.0+beta,tri);
}
@@ -3413,14 +3550,14 @@ var n = int(6 + rand() * 5);
var alt_offset = 0.5 * local_weather.cloud_vertical_size_map["Cumulus"] * ft_to_m;
-local_weather.create_streak("Stratocumulus",lat+get_lat(x,y+7500,phi), lon+get_lon(x,y+7500,phi), alt + alt_offset,500.0,m,1100.0,0.12,400.0,n,1100.0,0.12,400.0,alpha+90.0+beta,tri);
+local_weather.create_streak("Stratocumulus",lat+get_lat(x,y+7500,phi), lon+get_lon(x,y+7500,phi), alt - local_weather.offset_map["Congestus"] + 400.0,500.0,m,1100.0,0.12,400.0,n,1100.0,0.12,400.0,alpha+90.0+beta,tri);
-local_weather.create_streak("Stratocumulus",lat+get_lat(x,y-7500,phi), lon+get_lon(x,y-7500,phi), alt + alt_offset,500.0,m,1100.0,0.12,400.0,n,1100.0,0.12,400.0,alpha+270.0+beta,tri);
+local_weather.create_streak("Stratocumulus",lat+get_lat(x,y-7500,phi), lon+get_lon(x,y-7500,phi), alt -local_weather.offset_map["Congestus"] + 400.0,500.0,m,1100.0,0.12,400.0,n,1100.0,0.12,400.0,alpha+270.0+beta,tri);
-local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y+7050,phi), lon+get_lon(x,y+7050,phi), alt,0.0,m,700.0,0.2,400.0,n,700.0,0.0,400.0,alpha+90.0+beta,tri);
+local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y+7050,phi), lon+get_lon(x,y+7050,phi), alt - local_weather.offset_map["Stratus"],0.0,m,700.0,0.2,400.0,n,700.0,0.0,400.0,alpha+90.0+beta,tri);
-local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y-7050,phi), lon+get_lon(x,y-7050,phi), alt,0.0,m,700.0,0.2,400.0,n,700.0,0.0,400.0,alpha+270.0+beta,tri);
+local_weather.create_streak("Stratocumulus bottom",lat+get_lat(x,y-7050,phi), lon+get_lon(x,y-7050,phi), alt-local_weather.offset_map["Stratus"],0.0,m,700.0,0.2,400.0,n,700.0,0.0,400.0,alpha+270.0+beta,tri);
}
@@ -3536,7 +3673,7 @@ if (local_weather.wxradar_support_flag == 1)
}
-# spectacular, but not useful in practice
+
var create_2_8_cirrocumulus_patches = func (lat, lon, alt, alpha) {
@@ -3550,9 +3687,7 @@ for (var i=0; i<2; i=i+1)
var tri = 1.5 + rand();
var beta = rand() * math.pi;
- #local_weather.create_streak("Cirrocumulus (new)",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt,0.0,50,150.0,0.2,50.0,50,150.0,0.2,50.0,alpha ,tri);
-
- local_weather.create_layer("Cirrocumulus (new)", lat+get_lat(x,y,phi), lon+get_lat(x,y,phi), alt, 0.0, 8500.0, 5000.0, beta, 15.0, 0.25, 0, 0.0);
+ local_weather.create_layer("Cirrocumulus (new)", lat+get_lat(x,y,phi), lon+get_lat(x,y,phi), alt, 0.0, 8000.0, 4500.0, beta, 10.0, 0.25, 0, 0.0);
}
}
diff --git a/Shaders/3dcloud-lightfield.frag b/Shaders/3dcloud-lightfield.frag
index dd90fdddf..5c55008f0 100644
--- a/Shaders/3dcloud-lightfield.frag
+++ b/Shaders/3dcloud-lightfield.frag
@@ -7,9 +7,8 @@ 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
index 0f512fbea..e965a24f9 100644
--- a/Shaders/3dcloud-lightfield.vert
+++ b/Shaders/3dcloud-lightfield.vert
@@ -2,6 +2,7 @@
#version 120
varying float fogFactor;
+//varying float MieFactor;
varying vec3 hazeColor;
uniform float range; // From /sim/rendering/clouds3d-vis-range
@@ -35,6 +36,12 @@ if (x < -15.0) {return 0.0;}
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)
{
@@ -104,6 +111,8 @@ void main(void)
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
@@ -146,7 +155,6 @@ void main(void)
//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;
@@ -163,7 +171,30 @@ void main(void)
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;
+ hazeColor = hazeColor * earthShade;
+ gl_FrontColor.xyz = gl_FrontColor.xyz * earthShade;
+
+ // Mie correction
+ float Mie;
+ float MieFactor;
+
+ if (shade_factor > 0.6)
+ {
+ MieFactor = dot(normalize(lightFull), normalize(relVector));
+ Mie = 1.5 * smoothstep(0.9,1.0, MieFactor) * smoothstep(0.6, 0.8, shade_factor);
+ }
+ 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);
+ }
+
+ gl_BackColor = gl_FrontColor;
}
diff --git a/Shaders/skydome.frag b/Shaders/skydome.frag
index a65f5e5d9..6b721a59f 100644
--- a/Shaders/skydome.frag
+++ b/Shaders/skydome.frag
@@ -80,13 +80,20 @@ void main()
// 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);
-
+
+// a different exposure filter
+//color.x = 1.0 - exp(-1.3 * color.x);
+//color.y = 1.0 - exp(-1.3 * color.y);
+//color.z = 1.0 - exp(-1.3 * color.z);
+
+if (color.x > 0.58) color.x = 1.0 - exp(-1.5 * color.x);
+if (color.y > 0.58) color.y = 1.0 - exp(-1.5 * color.y);
+if (color.z > 0.58) color.z = 1.0 - exp(-1.5 * 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));
+//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));
@@ -101,10 +108,10 @@ float delta_zv;
float costheta = ct;
-float vis= visibility;
+float vis = min(visibility, avisibility);
// hack - in an effect volume the visibility only may be reduced, so we take care here
-if (avisibility < visibility){vis = avisibility;}
+//if (avisibility < visibility){vis = avisibility;}
if (delta_z > 0.0) // we're inside the layer
{
@@ -142,11 +149,9 @@ if (avisibility < visibility){vis = avisibility;}
// 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);
-
-
+//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(avisibility, 1.5 * avisibility, -alt/costheta);
+float eqColorFactor = 1.0 - 0.1 * delta_zv/vis - (1.0 -scattering);
// there's always residual intensity, we should never be driven to zero
diff --git a/Shaders/skydome.vert b/Shaders/skydome.vert
index 58219e6e6..43673a5c8 100644
--- a/Shaders/skydome.vert
+++ b/Shaders/skydome.vert
@@ -43,7 +43,8 @@ const float fSamples = float(nSamples);
uniform float rK = 0.0003; //0.00015;
uniform float mK = 0.003; //0.0025;
uniform float density = 0.5; //1.0
-vec3 rayleighK = rK * vec3(5.602, 7.222, 19.644);
+//vec3 rayleighK = rK * vec3(5.602, 7.222, 19.644);
+vec3 rayleighK = rK * vec3(4.5, 8.62, 17.3);
vec3 mieK = vec3(mK);
vec3 sunIntensity = 10.0*vec3(120.0, 125.0, 130.0);
@@ -235,7 +236,7 @@ void main()
{
if (ct < 0.0)
{
- yprime = -dot(relVector,lightHorizon) * altitude/-(ct-0.001);
+ yprime = -dot(relVector,lightHorizon) * altitude/-ct;//(ct-0.001);
yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
else // the only haze we see looking up is overcast, assume its altitude
diff --git a/Shaders/terrain-haze-detailed.frag b/Shaders/terrain-haze-detailed.frag
new file mode 100644
index 000000000..8764e1956
--- /dev/null
+++ b/Shaders/terrain-haze-detailed.frag
@@ -0,0 +1,351 @@
+// -*-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 vec4 rawPos;
+
+
+//varying vec3 hazeColor;
+//varying float fogCoord;
+
+uniform sampler2D texture;
+uniform sampler3D NoiseTex;
+uniform sampler2D snow_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;
+varying float steepness;
+
+
+uniform float visibility;
+uniform float avisibility;
+uniform float scattering;
+//uniform float ground_scattering;
+uniform float terminator;
+uniform float terrain_alt;
+uniform float hazeLayerAltitude;
+uniform float overcast;
+//uniform float altitude;
+uniform float eye_alt;
+uniform float mysnowlevel;
+uniform float dust_cover_factor;
+uniform float fogstructure;
+
+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 snow_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);
+ snow_texel = texture2D(snow_texture, gl_TexCoord[0].st);
+
+
+// this is the snow and dust generating part, ger some noise vectors
+vec4 noisevec = texture3D(NoiseTex, (rawPos.xyz)*0.003); // small scale noise
+//vec4 nvL = texture3D(NoiseTex, (rawPos.xyz)*0.00066);
+vec4 nvL = texture3D(NoiseTex, (rawPos.xyz)*0.0001); // large scale noise
+vec4 nvR = texture3D(NoiseTex, (rawPos.xyz)*0.00003); // really large scale noise
+
+//float ns=0.06;
+ // ns += nvL[0]*0.4;
+ //ns += nvL[1]*0.6;
+ //ns += nvL[2]*2.0;
+ //ns += nvL[3]*4.0;
+ //ns += noisevec[0]*0.1;
+ //ns += noisevec[1]*0.4;
+
+ //ns += noisevec[2]*0.8;
+ //ns += noisevec[3]*2.1;
+
+ // gradient effect for snow
+
+
+// mix dust
+ vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
+ //dust_color.rgb = dust_color.rgb * nvL[1];
+
+ texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * nvL[1],0.0, 1.0) );
+
+
+ float snow_alpha = smoothstep(0.7, 0.8, abs(steepness));
+
+ //vec4 snow_texel = clamp(ns+nvL[2]*4.1+vec4(0.1, 0.1, nvL[2]*2.2, 1.0), 0.7, 1.0);
+ //snow_texel.a = snow_alpha * snow_texel.a;
+
+
+
+ // mix snow
+ texel = mix(texel, snow_texel, smoothstep(mysnowlevel, mysnowlevel+200.0, snow_alpha * (relPos.z + eye_alt)+ (noisevec[1] * abs(noisevec[1])+ nvL[1])*1500.0));
+
+// gradient
+ //fragColor = mix(vec4(ns-0.30, ns-0.29, ns-0.37, 1.0), fragColor, smoothstep(0.0, 0.40, steepness));// +nvL[2]*1.3));
+
+ 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;
+ vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
+ delta_zv = delta_z - vAltitude;
+ }
+ else // we may look through upper layer edge
+ {
+ H = dist * ct;
+ if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
+ else {distance_in_layer = dist;}
+ vAltitude = min(distance_in_layer,visibility) * ct;
+ delta_zv = delta_z - vAltitude;
+ }
+ }
+ else // we see the layer from above, delta_z < 0.0
+ {
+ H = dist * -ct;
+ if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
+ {
+ distance_in_layer = 0.0;
+ delta_zv = 0.0;
+ }
+ else
+ {
+ vAltitude = H + delta_z;
+ distance_in_layer = vAltitude/H * dist;
+ vAltitude = min(distance_in_layer,visibility) * (-ct);
+ delta_zv = vAltitude;
+ }
+ }
+
+
+// ground haze cannot be thinner than aloft visibility in the model,
+// so we need to use aloft visibility otherwise
+
+
+transmission_arg = (dist-distance_in_layer)/avisibility;
+
+
+float eqColorFactor;
+
+//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, relPos.z + eye_alt);
+
+
+if (visibility < avisibility)
+ {
+ transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 0.8 * visibility * fogstructure * (( 0.4 * nvL[1] + 0.6 * nvR[1]) -0.1) ));
+ //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/(1.0 * avisibility + 0.8 * avisibility * fogstructure * (( 0.4 * nvL[1] + 0.6 * nvR[1]) -0.1) ));
+ //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));
+
+// randomness
+
+//hazeColor.rgb = hazeColor.rgb + 0.2 * hazeColor.rgb * nvL[1];
+
+// determine the right mix of transmission and haze
+
+//fragColor.xyz = transmission * fragColor.xyz + (1.0-transmission) * eqColorFactor * hazeColor * earthShade;
+
+
+//fragColor.rgb = mix(fragColor.rgb, vec3 (1.0, 1.0, 1.0), overcast );
+
+
+fragColor.xyz = mix(eqColorFactor * hazeColor * earthShade, fragColor.xyz,transmission);
+
+
+gl_FragColor = fragColor;
+
+
+}
+else // if dist < 40.0 no fogging at all
+{
+gl_FragColor = fragColor;
+}
+
+
+//gl_FragColor.rgb = 5.0 * nvL[1] * vec3 (1.0, 1.0, 1.0);
+
+}
+
diff --git a/Shaders/terrain-haze-detailed.vert b/Shaders/terrain-haze-detailed.vert
new file mode 100644
index 000000000..7adfb8c66
--- /dev/null
+++ b/Shaders/terrain-haze-detailed.vert
@@ -0,0 +1,243 @@
+// -*-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 vec4 rawPos;
+
+varying float earthShade;
+//varying float yprime;
+//varying float vertex_alt;
+varying float yprime_alt;
+varying float mie_angle;
+varying float steepness;
+
+
+
+
+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;
+uniform float ground_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;
+ float scattering;
+
+ rawPos = gl_Vertex;
+ steepness = dot(normalize(gl_Normal), vec3 (0.0, 0.0, 1.0));
+
+// 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);
+
+ // 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);
+ scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
+
+ // branch dependent on daytime
+
+if (terminator < 1000000.0) // the full, sunrise and sunset computation
+{
+
+
+ // 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/Shaders/terrain-haze.frag b/Shaders/terrain-haze.frag
index bf14090b9..54595d5e1 100644
--- a/Shaders/terrain-haze.frag
+++ b/Shaders/terrain-haze.frag
@@ -20,11 +20,12 @@ varying float earthShade;
//varying float vertex_alt;
varying float yprime_alt;
varying float mie_angle;
-
+
uniform float visibility;
uniform float avisibility;
uniform float scattering;
+//uniform float ground_scattering;
uniform float terminator;
uniform float terrain_alt;
uniform float hazeLayerAltitude;
@@ -157,8 +158,7 @@ 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;
+ vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
delta_zv = delta_z - vAltitude;
}
else // we may look through upper layer edge
@@ -166,7 +166,6 @@ if (delta_z > 0.0) // we're inside the layer
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;
}
@@ -198,6 +197,7 @@ transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor;
+//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, relPos.z + eye_alt);
if (visibility < avisibility)
{
@@ -214,6 +214,7 @@ else
}
+
transmission = fog_func(transmission_arg);
// there's always residual intensity, we should never be driven to zero
@@ -234,7 +235,7 @@ earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width +
// Mie-like factor
-if (lightArg < 5.0)
+if (lightArg < 10.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)) );
diff --git a/Shaders/terrain-haze.vert b/Shaders/terrain-haze.vert
index f1cd4732d..fde08a6c7 100644
--- a/Shaders/terrain-haze.vert
+++ b/Shaders/terrain-haze.vert
@@ -38,7 +38,8 @@ uniform float terrain_alt;
uniform float avisibility;
uniform float visibility;
uniform float overcast;
-uniform float scattering;
+//uniform float scattering;
+uniform float ground_scattering;
// This is the value used in the skydome scattering shader - use the same here for consistency?
@@ -67,6 +68,7 @@ void main()
float lightArg;
float intensity;
float vertex_alt;
+ float scattering;
// this code is copied from default.vert
@@ -100,13 +102,16 @@ void main()
// 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);
-
+
+ // 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);
+ scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
+
// 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
@@ -129,12 +134,14 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun
- if (lightArg < 5.0)
+ if (lightArg < 10.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);
@@ -209,8 +216,6 @@ else // the faster, full-day version without lightfields
light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
-
-
}
diff --git a/Shaders/water_lightfield.frag b/Shaders/water_lightfield.frag
new file mode 100644
index 000000000..b86b3a4c6
--- /dev/null
+++ b/Shaders/water_lightfield.frag
@@ -0,0 +1,577 @@
+// This shader is mostly an adaptation of the shader found at
+// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
+// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
+// © Michael Horsch - 2005
+// Major update and revisions - 2011-10-07
+// © Emilian Huminiuc and Vivian Meazza
+
+#version 120
+
+uniform sampler2D water_normalmap;
+//uniform sampler2D water_reflection;
+uniform sampler2D water_dudvmap;
+//uniform sampler2D water_reflection_grey;
+uniform sampler2D sea_foam;
+uniform sampler2D perlin_normalmap;
+
+uniform sampler3D Noise;
+
+uniform float saturation, Overcast, WindE, WindN;
+//uniform float CloudCover0, CloudCover1, CloudCover2, CloudCover3, CloudCover4;
+uniform float osg_SimulationTime;
+//uniform int Status;
+
+varying vec4 waterTex1; //moving texcoords
+varying vec4 waterTex2; //moving texcoords
+varying vec4 waterTex4; //viewts
+//varying vec4 ecPosition;
+varying vec3 viewerdir;
+varying vec3 lightdir;
+//varying vec3 normal;
+varying vec3 specular_light;
+varying vec3 relPos;
+
+varying float earthShade;
+varying float yprime_alt;
+varying float mie_angle;
+
+uniform float WaveFreq ;
+uniform float WaveAmp ;
+uniform float WaveSharp ;
+uniform float WaveAngle ;
+uniform float WaveFactor ;
+uniform float WaveDAngle ;
+
+
+uniform float hazeLayerAltitude;
+uniform float terminator;
+uniform float terrain_alt;
+uniform float avisibility;
+uniform float visibility;
+uniform float overcast;
+uniform float scattering;
+uniform float ground_scattering;
+uniform float eye_alt;
+uniform float sea_r;
+uniform float sea_g;
+uniform float sea_b;
+
+const float terminator_width = 200000.0;
+const float EarthRadius = 5800000.0;
+////fog "include" /////
+//uniform int fogType;
+
+vec3 fog_Func(vec3 color, int type);
+//////////////////////
+
+/////// functions /////////
+
+void rotationmatrix(in float angle, out mat4 rotmat)
+ {
+ rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0,
+ sin( angle ), cos( angle ), 0.0, 0.0,
+ 0.0 , 0.0 , 1.0, 0.0,
+ 0.0 , 0.0 , 0.0, 1.0 );
+ }
+
+// wave functions ///////////////////////
+
+struct Wave {
+ float freq; // 2*PI / wavelength
+ float amp; // amplitude
+ float phase; // speed * 2*PI / wavelength
+ vec2 dir;
+ };
+
+Wave wave0 = Wave(1.0, 1.0, 0.5, vec2(0.97, 0.25));
+Wave wave1 = Wave(2.0, 0.5, 1.3, vec2(0.97, -0.25));
+Wave wave2 = Wave(1.0, 1.0, 0.6, vec2(0.95, -0.3));
+Wave wave3 = Wave(2.0, 0.5, 1.4, vec2(0.99, 0.1));
+
+float evaluateWave(in Wave w, vec2 pos, float t)
+ {
+ return w.amp * sin( dot(w.dir, pos) * w.freq + t * w.phase);
+ }
+
+// derivative of wave function
+float evaluateWaveDeriv(Wave w, vec2 pos, float t)
+ {
+ return w.freq * w.amp * cos( dot(w.dir, pos)*w.freq + t*w.phase);
+ }
+
+// sharp wave functions
+float evaluateWaveSharp(Wave w, vec2 pos, float t, float k)
+ {
+ return w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k);
+ }
+
+float evaluateWaveDerivSharp(Wave w, vec2 pos, float t, float k)
+ {
+ return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1) * cos( dot(w.dir, pos)*w.freq + t*w.phase);
+ }
+
+void sumWaves(float angle, float dangle, float windScale, float factor, out float ddx, float ddy)
+ {
+ mat4 RotationMatrix;
+ float deriv;
+ vec4 P = waterTex1 * 1024;
+
+ rotationmatrix(radians(angle + dangle * windScale + 0.6 * sin(P.x * factor)), RotationMatrix);
+ P *= RotationMatrix;
+
+ P.y += evaluateWave(wave0, P.xz, osg_SimulationTime);
+ deriv = evaluateWaveDeriv(wave0, P.xz, osg_SimulationTime );
+ ddx = deriv * wave0.dir.x;
+ ddy = deriv * wave0.dir.y;
+
+ P.y += evaluateWave(wave1, P.xz, osg_SimulationTime);
+ deriv = evaluateWaveDeriv(wave1, P.xz, osg_SimulationTime);
+ ddx += deriv * wave1.dir.x;
+ ddy += deriv * wave1.dir.y;
+
+ P.y += evaluateWaveSharp(wave2, P.xz, osg_SimulationTime, WaveSharp);
+ deriv = evaluateWaveDerivSharp(wave2, P.xz, osg_SimulationTime, WaveSharp);
+ ddx += deriv * wave2.dir.x;
+ ddy += deriv * wave2.dir.y;
+
+ P.y += evaluateWaveSharp(wave3, P.xz, osg_SimulationTime, WaveSharp);
+ deriv = evaluateWaveDerivSharp(wave3, P.xz, osg_SimulationTime, WaveSharp);
+ ddx += deriv * wave3.dir.x;
+ ddy += deriv * wave3.dir.y;
+ }
+
+
+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 (eye_alt < 30000.0)
+ {return exp(-targ - targ * targ * targ * targ);}
+else if (eye_alt < 50000.0)
+ {
+ fade_mix = (eye_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(void)
+ {
+
+ float dist = length(relPos);
+ const vec4 sca = vec4(0.005, 0.005, 0.005, 0.005);
+ const vec4 sca2 = vec4(0.02, 0.02, 0.02, 0.02);
+ const vec4 tscale = vec4(0.25, 0.25, 0.25, 0.25);
+
+ mat4 RotationMatrix;
+
+ // compute direction to viewer
+ vec3 E = normalize(viewerdir);
+
+ // compute direction to light source
+ vec3 L = lightdir; // normalize(lightdir);
+
+ // half vector
+ vec3 Hv = normalize(L + E);
+
+ //vec3 Normal = normalize(normal);
+ vec3 Normal = vec3 (0.0, 0.0, 1.0);
+
+ const float water_shininess = 240.0;
+
+ // approximate cloud cover
+ //float cover = 0.0;
+ //bool Status = true;
+
+ float windEffect = sqrt( WindE*WindE + WindN*WindN ) * 0.6; //wind speed in kt
+ float windScale = 15.0/(3.0 + windEffect); //wave scale
+ float windEffect_low = 0.3 + 0.7 * smoothstep(0.0, 5.0, windEffect); //low windspeed wave filter
+ float waveRoughness = 0.01 + smoothstep(0.0, 40.0, windEffect); //wave roughness filter
+
+ float mixFactor = 0.2 + 0.02 * smoothstep(0.0, 50.0, windEffect);
+ //mixFactor = 0.2;
+ mixFactor = clamp(mixFactor, 0.3, 0.8);
+
+ // there's no need to do wave patterns or foam for pixels which are so far away that we can't actually see them
+ // we only need detail in the near zone or where the sun reflection is
+
+ int detail_flag;
+ if ((dist > 15000.0) && (dot(normalize(vec3 (lightdir.x, lightdir.y, 0.0) ), normalize(relPos)) < 0.7 )) {detail_flag = 0;}
+ else {detail_flag = 1;}
+
+
+ // sine waves
+ float ddx, ddx1, ddx2, ddx3, ddy, ddy1, ddy2, ddy3;
+
+ if (detail_flag == 1)
+ {
+ float angle = 0.0;
+
+ wave0.freq = WaveFreq ;
+ wave0.amp = WaveAmp;
+ wave0.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ angle -= 45;
+ wave1.freq = WaveFreq * 2.0 ;
+ wave1.amp = WaveAmp * 1.25;
+ wave1.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ angle += 30;
+ wave2.freq = WaveFreq * 3.5;
+ wave2.amp = WaveAmp * 0.75;
+ wave2.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ angle -= 50;
+ wave3.freq = WaveFreq * 3.0 ;
+ wave3.amp = WaveAmp * 0.75;
+ wave3.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ // sum waves
+
+ ddx = 0.0, ddy = 0.0;
+ sumWaves(WaveAngle, -1.5, windScale, WaveFactor, ddx, ddy);
+
+ ddx1 = 0.0, ddy1 = 0.0;
+ sumWaves(WaveAngle, 1.5, windScale, WaveFactor, ddx1, ddy1);
+
+ //reset the waves
+ angle = 0.0;
+ float waveamp = WaveAmp * 0.75;
+
+ wave0.freq = WaveFreq ;
+ wave0.amp = waveamp;
+ wave0.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ angle -= 20;
+ wave1.freq = WaveFreq * 2.0 ;
+ wave1.amp = waveamp * 1.25;
+ wave1.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ angle += 35;
+ wave2.freq = WaveFreq * 3.5;
+ wave2.amp = waveamp * 0.75;
+ wave2.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ angle -= 45;
+ wave3.freq = WaveFreq * 3.0 ;
+ wave3.amp = waveamp * 0.75;
+ wave3.dir = vec2(cos(radians(angle)), sin(radians(angle)));
+
+ ddx2 = 0.0, ddy2 = 0.0;
+ sumWaves(WaveAngle + WaveDAngle, -1.5, windScale, WaveFactor, ddx2, ddy2);
+
+ ddx3 = 0.0, ddy3 = 0.0;
+ sumWaves(WaveAngle + WaveDAngle, 1.5, windScale, WaveFactor, ddx3, ddy3);
+ }
+ // end sine stuff
+
+ //cover = 5.0 * smoothstep(0.6, 1.0, scattering);
+ //cover = 5.0 * ground_scattering;
+
+ vec4 viewt = normalize(waterTex4);
+
+ vec4 disdis = texture2D(water_dudvmap, vec2(waterTex2 * tscale)* windScale) * 2.0 - 1.0;
+
+ vec4 vNorm;
+
+
+ //normalmaps
+ vec4 nmap = texture2D(water_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0;
+ vec4 nmap1 = texture2D(perlin_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0;
+
+ rotationmatrix(radians(3.0 * sin(osg_SimulationTime * 0.0075)), RotationMatrix);
+ nmap += texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * tscale) * windScale) * 2.0 - 1.0;
+ nmap1 += texture2D(perlin_normalmap, vec2(waterTex2 * RotationMatrix * tscale) * windScale) * 2.0 - 1.0;
+
+ nmap *= windEffect_low;
+ nmap1 *= windEffect_low;
+
+ // mix water and noise, modulated by factor
+ vNorm = normalize(mix(nmap, nmap1, mixFactor) * waveRoughness);
+ if (detail_flag == 1) {vNorm.r += ddx + ddx1 + ddx2 + ddx3;}
+ vNorm = -vNorm;
+ //dds fix
+
+
+
+
+ //load reflection
+
+ vec4 refl ;
+
+ refl.r = sea_r;
+ refl.g = sea_g;
+ refl.b = sea_b;
+ refl.a = 1.0;
+
+
+ float intensity;
+ // de-saturate for reduced light
+ refl.rgb = mix(refl.rgb, vec3 (0.248, 0.248, 0.248), 1.0 - smoothstep(0.3, 0.7, ground_scattering));
+
+ // de-saturate light for overcast haze
+ intensity = length(refl.rgb);
+ refl.rgb = mix(refl.rgb, intensity * vec3 (1.0, 1.0, 1.0), smoothstep(0.1, 0.8, overcast));
+
+ vec3 N;
+
+ if (detail_flag == 1)
+ {
+
+ vec3 N0 = vec3(texture2D(water_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0);
+ vec3 N1 = vec3(texture2D(perlin_normalmap, vec2(waterTex1 + disdis * sca) * windScale) * 2.0 - 1.0);
+
+ N0 += vec3(texture2D(water_normalmap, vec2(waterTex1 * tscale) * windScale) * 2.0 - 1.0);
+ N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex2 * tscale) * windScale) * 2.0 - 1.0);
+
+ rotationmatrix(radians(2.0 * sin(osg_SimulationTime * 0.005)), RotationMatrix);
+ N0 += vec3(texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale) * 2.0 - 1.0);
+ N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale) * 2.0 - 1.0);
+
+ rotationmatrix(radians(-4.0 * sin(osg_SimulationTime * 0.003)), RotationMatrix);
+ N0 += vec3(texture2D(water_normalmap, vec2(waterTex1 * RotationMatrix + disdis * sca2) * windScale) * 2.0 - 1.0);
+ N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex1 * RotationMatrix + disdis * sca) * windScale) * 2.0 - 1.0);
+
+ N0 *= windEffect_low;
+ N1 *= windEffect_low;
+
+ N0.r += (ddx + ddx1 + ddx2 + ddx3);
+ N0.g += (ddy + ddy1 + ddy2 + ddy3);
+
+ N = normalize(mix(Normal + N0, Normal + N1, mixFactor) * waveRoughness);
+
+ N = -N; //dds fix
+ }
+ else
+ {N = vec3 (0.0, 0.0, 1.0);}
+
+ //float lightArg = (terminator-yprime_alt)/100000.0;
+
+
+
+
+ vec3 specular_color = vec3(specular_light)
+ * pow(max(0.0, dot(N, Hv)), water_shininess) * 6.0;
+ vec4 specular = vec4(specular_color, 0.5);
+
+ specular = specular * saturation * 0.3 * earthShade ;
+
+ //calculate fresnel
+ vec4 invfres = vec4( dot(vNorm, viewt) );
+ vec4 fres = vec4(1.0) + invfres;
+ refl *= fres;
+
+
+
+ vec4 ambient_light;
+
+ ambient_light.rgb = specular_light.rgb;
+ ambient_light.a = 1.0;
+
+
+ vec4 finalColor;
+
+ //if(cover >= 1.5)
+ //if (ground_scattering > 0.4)
+ // {
+ // finalColor = refl + specular;
+ // } else {
+ // finalColor = refl;
+ // }
+
+ finalColor = refl + specular * smoothstep(0.3, 0.6, ground_scattering);
+
+ //add foam
+
+ if (dist < 10000.0)
+ {
+ float foamSlope = 0.10 + 0.1 * windScale;
+
+
+ vec4 foam_texel = texture2D(sea_foam, vec2(waterTex2 * tscale) * 25.0);
+ float waveSlope = N.g;
+
+ if (windEffect >= 8.0)
+ if (waveSlope >= foamSlope){
+ finalColor = mix(finalColor, max(finalColor, finalColor + foam_texel), smoothstep(0.01, 0.50, N.g));
+ }
+ }
+
+
+
+ finalColor *= ambient_light;
+
+
+
+// here comes the terrain haze model
+
+
+float delta_z = hazeLayerAltitude - eye_alt;
+
+
+
+if (dist > 40.0)
+{
+
+
+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,min(visibility,avisibility)) * ct;
+ delta_zv = delta_z - vAltitude;
+ }
+ else // we may look through upper layer edge
+ {
+ H = dist * ct;
+ if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
+ else {distance_in_layer = dist;}
+ //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.rgb = specular_light.rgb;
+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
+float eShade = 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, eye_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,eShade) ));
+
+// 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));
+
+ finalColor.rgb = mix(eqColorFactor * hazeColor * eShade, finalColor.rgb,transmission);
+
+
+ }
+ gl_FragColor = finalColor;
+
+}
diff --git a/Shaders/water_lightfield.vert b/Shaders/water_lightfield.vert
new file mode 100644
index 000000000..5da4193c6
--- /dev/null
+++ b/Shaders/water_lightfield.vert
@@ -0,0 +1,226 @@
+// This shader is mostly an adaptation of the shader found at
+// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
+// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
+// © Michael Horsch - 2005
+// Major update and revisions - 2011-10-07
+// © Emilian Huminiuc and Vivian Meazza
+
+#version 120
+
+varying vec4 waterTex1;
+varying vec4 waterTex2;
+varying vec4 waterTex4;
+//varying vec4 ecPosition;
+varying vec3 relPos;
+varying vec3 specular_light;
+
+varying vec3 viewerdir;
+varying vec3 lightdir;
+//varying vec3 normal;
+
+varying float earthShade;
+varying float yprime_alt;
+varying float mie_angle;
+
+uniform float osg_SimulationTime;
+uniform float WindE, WindN;
+
+uniform float hazeLayerAltitude;
+uniform float terminator;
+uniform float terrain_alt;
+uniform float avisibility;
+uniform float visibility;
+uniform float overcast;
+uniform float ground_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));
+}
+
+
+////fog "include"////////
+// uniform int fogType;
+//
+// void fog_Func(int type);
+/////////////////////////
+
+/////// functions /////////
+
+void rotationmatrix(in float angle, out mat4 rotmat)
+{
+ rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0,
+ sin( angle ), cos( angle ), 0.0, 0.0,
+ 0.0 , 0.0 , 1.0, 0.0,
+ 0.0 , 0.0 , 0.0, 1.0 );
+}
+
+void main(void)
+{
+
+ mat4 RotationMatrix;
+ // vec3 N = normalize(gl_Normal);
+ // normal = N;
+
+ vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
+
+ viewerdir = vec3(gl_ModelViewMatrixInverse[3]) - vec3(gl_Vertex);
+ lightdir = normalize(vec3(gl_ModelViewMatrixInverse * gl_LightSource[0].position));
+
+ waterTex4 = vec4( ecPosition.xzy, 0.0 );
+
+ vec4 t1 = vec4(0.0, osg_SimulationTime * 0.005217, 0.0, 0.0);
+ vec4 t2 = vec4(0.0, osg_SimulationTime * -0.0012, 0.0, 0.0);
+
+ float Angle;
+
+ float windFactor = sqrt(pow(abs(WindE),2)+pow(abs(WindN),2)) * 0.05;
+ if (WindN == 0.0 && WindE == 0.0) {
+ Angle = 0.0;
+ }else{
+ Angle = atan(-WindN, WindE) - atan(1.0);
+ }
+
+ rotationmatrix(Angle, RotationMatrix);
+ waterTex1 = gl_MultiTexCoord0 * RotationMatrix - t1 * windFactor;
+
+ rotationmatrix(Angle, RotationMatrix);
+ waterTex2 = gl_MultiTexCoord0 * RotationMatrix - t2 * windFactor;
+
+// fog_Func(fogType);
+ gl_Position = ftransform();
+
+
+
+// here start computations for the haze layer
+
+
+ float yprime;
+ float lightArg;
+ float intensity;
+ float vertex_alt;
+ float scattering;
+
+ // 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);
+
+
+// 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);
+ scattering = 0.5 + 0.5 * ground_scattering + 0.5* (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
+
+ // branch dependent on daytime
+
+if (terminator < 1000000.0) // the full, sunrise and sunset computation
+{
+
+
+ // 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));
+ vec3 lightHorizon = normalize(vec3(lightdir.x,lightdir.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;
+
+ specular_light.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
+ specular_light.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
+ specular_light.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
+
+ specular_light = specular_light * scattering;
+
+ // correct ambient light intensity and hue before sunrise
+ if (earthShade < 0.5)
+ {
+ intensity = length(specular_light.rgb);
+ specular_light.xyz = intensity * normalize(mix(specular_light.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
+ }
+
+ // directional scattering for low sun
+ if (lightArg < 5.0)
+ //{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
+ {mie_angle = (0.5 * dot(normalize(relPos), lightdir) ) + 0.5;}
+ else
+ {mie_angle = 1.0;}
+
+
+
+
+
+// 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)
+ {specular_light = vec3 (1.0, 1.0, 1.0);}
+ else
+ {
+
+ lightArg = (terminator/100000.0 - 10.0)/20.0;
+ specular_light.b = 0.78 + lightArg * 0.21;
+ specular_light.g = 0.907 + lightArg * 0.091;
+ specular_light.r = 0.904 + lightArg * 0.092;
+ }
+
+ specular_light = specular_light * scattering;
+
+ yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
+
+}
+
+
+
+}
diff --git a/gui/dialogs/local_weather_environment.xml b/gui/dialogs/local_weather_environment.xml
new file mode 100644
index 000000000..4836a4456
--- /dev/null
+++ b/gui/dialogs/local_weather_environment.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+ local_weather_environment
+ 400
+ 210
+ false
+
+
+ 5
+ 180
+
+
+
+
+
+ 5
+ 150
+
+
+
+
+ 120
+ 150
+
+
+
+
+ 190
+ 150
+ 90
+ 20
+ 0.0
+ 7500.0
+ /environment/mysnow-level-m
+
+ dialog-apply
+
+
+
+
+ 290
+ 150
+
+
+
+
+
+ 340
+ 150
+
+ %.fm
+ true
+ /environment/mysnow-level-m
+
+
+
+
+ 5
+ 120
+
+
+
+
+ 120
+ 120
+
+
+
+
+ 190
+ 120
+ 90
+ 20
+ 0.0
+ 0.7
+ /environment/surface/dust-cover-factor
+
+ dialog-apply
+
+
+
+
+ 290
+ 120
+
+
+
+
+
+ 5
+ 90
+
+
+
+
+ 120
+ 90
+
+
+
+
+ 190
+ 90
+ 90
+ 20
+ 0.0
+ 12.0
+ /environment/fog-structure
+
+ dialog-apply
+
+
+
+
+ 290
+ 90
+
+
+
+
+
+ 10
+ 10
+
+
+
+
+
+
+
+
+
+
diff --git a/gui/dialogs/local_weather_tiles.xml b/gui/dialogs/local_weather_tiles.xml
index 9863855c4..a9c5bc0ef 100644
--- a/gui/dialogs/local_weather_tiles.xml
+++ b/gui/dialogs/local_weather_tiles.xml
@@ -6,20 +6,20 @@
local_weather_tiles
470
- 385
+ 410
false
5
- 355
+ 380
10
- 330
+ 355
280
25
true
@@ -53,7 +53,7 @@
300
- 330
+ 355
@@ -61,7 +61,7 @@
390
- 330
+ 355
50
25
/local-weather/tmp/tile-alt-offset-ft
@@ -70,13 +70,13 @@
5
- 295
+ 320
67
- 295
+ 320
40
25
/local-weather/tmp/tile-orientation-deg
@@ -84,13 +84,13 @@
105
- 295
+ 320
125
- 295
+ 320
30
25
/local-weather/tmp/windspeed-kt
@@ -100,7 +100,7 @@
157
- 295
+ 320
@@ -108,7 +108,7 @@
225
- 295
+ 320
50
20
0.0
@@ -123,14 +123,14 @@
275
- 295
+ 320
333
- 295
+ 320
50
20
0.0
@@ -143,14 +143,14 @@
380
- 295
+ 320
410
- 295
+ 320
50
20
0.0
@@ -166,14 +166,14 @@
5
- 265
+ 290
150
- 265
+ 290
140
25
true
@@ -191,7 +191,7 @@
300
- 265
+ 290
@@ -199,7 +199,7 @@
390
- 265
+ 290
50
25
/local-weather/config/temperature-offset-degc
@@ -208,13 +208,13 @@
5
- 235
+ 260
150
- 235
+ 260
140
25
true
@@ -231,7 +231,7 @@
10
- 205
+ 230
15
15
@@ -279,7 +279,7 @@
150
- 205
+ 230
15
15
@@ -291,7 +291,7 @@
290
- 205
+ 230
15
15
@@ -303,7 +303,7 @@
10
- 180
+ 205
15
15
@@ -315,7 +315,7 @@
150
- 180
+ 205
15
15
@@ -328,19 +328,19 @@
5
- 150
+ 175
160
- 150
+ 175
230
- 150
+ 175
90
20
0.3
@@ -353,26 +353,26 @@
330
- 150
+ 175
5
- 125
+ 150
160
- 125
+ 150
230
- 125
+ 150
90
20
0.1
@@ -385,10 +385,41 @@
330
- 125
+ 150
+
+ 5
+ 125
+
+
+
+
+ 160
+ 125
+
+
+
+
+ 230
+ 125
+ 90
+ 20
+ 0.0
+ 1.0
+ /environment/air-pollution-norm
+
+ dialog-apply
+
+
+
+
+ 330
+ 125
+
+
+
5
@@ -527,7 +558,7 @@
+
+