1
0
Fork 0

Terrain Haze v1.3

This commit is contained in:
Flightgear Development 2012-04-26 13:03:51 +03:00
parent 9e0cedf568
commit 2b972341b3
25 changed files with 3325 additions and 451 deletions

View file

@ -17,6 +17,7 @@
<technique n="8"> <technique n="8">
<predicate> <predicate>
<and> <and>
<property>/sim/rendering/shader-effects</property>
<property>/sim/rendering/shaders/skydome</property> <property>/sim/rendering/shaders/skydome</property>
<or> <or>
<less-equal> <less-equal>

View file

@ -30,6 +30,13 @@
<!-- float, signed-integer, integer --> <!-- float, signed-integer, integer -->
<internal-format>normalized</internal-format> <internal-format>normalized</internal-format>
</texture> </texture>
<texture n="6">
<image>Textures.high/Terrain/snow3.dds</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<transparent>false</transparent> <transparent>false</transparent>
<render-bin> <render-bin>
<bin-number>0</bin-number> <bin-number>0</bin-number>
@ -40,14 +47,420 @@
<avisibility><use>/environment/visibility-m</use></avisibility> <avisibility><use>/environment/visibility-m</use></avisibility>
<lthickness><use>/environment/ground-haze-thickness-m</use></lthickness> <lthickness><use>/environment/ground-haze-thickness-m</use></lthickness>
<scattering><use>/rendering/scene/scattering</use></scattering> <scattering><use>/rendering/scene/scattering</use></scattering>
<ground_scattering><use>/environment/surface/scattering</use></ground_scattering>
<terminator><use>/environment/terminator-relative-position-m</use></terminator> <terminator><use>/environment/terminator-relative-position-m</use></terminator>
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt> <terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<overcast><use>/rendering/scene/overcast</use></overcast> <overcast><use>/rendering/scene/overcast</use></overcast>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt> <eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<mysnow_level><use>/environment/mysnow-level-m</use></mysnow_level>
<dust_cover_factor><use>/environment/surface/dust-cover-factor</use></dust_cover_factor>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype> <fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>
</parameters> </parameters>
<!-- put techniques at a "high" index to allow derived effects to <!-- put techniques at a "high" index to allow derived effects to
insert their own techniques first. --> insert their own techniques first. -->
<technique n="4">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<less-equal>
<value type="float">4.0</value>
<float-property>/sim/rendering/shaders/landmass</float-property>
</less-equal>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<alpha-test><use>transparent</use></alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number>-1</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<image><use>texture[0]/image</use></image>
<filter><use>texture[0]/filter</use></filter>
<wrap-s><use>texture[0]/wrap-s</use></wrap-s>
<wrap-t><use>texture[0]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>
<!--<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>-->
<program>
<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
<vertex-shader n="1">Shaders/default.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/terrain-nocolor.frag</fragment-shader>
</program>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<color-mask type="vec4d">0 0 0 0</color-mask>
</pass>
<pass>
<lighting>true</lighting>
<material>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend><use>transparent</use></blend>
<alpha-test><use>transparent</use></alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number><use>render-bin/bin-number</use></bin-number>
<bin-name><use>render-bin/bin-name</use></bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<image><use>texture[0]/image</use></image>
<filter><use>texture[0]/filter</use></filter>
<wrap-s><use>texture[0]/wrap-s</use></wrap-s>
<wrap-t><use>texture[0]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>
<texture-unit>
<unit>6</unit>
<image><use>texture[6]/image</use></image>
<filter><use>texture[6]/filter</use></filter>
<wrap-s><use>texture[6]/wrap-s</use></wrap-s>
<wrap-t><use>texture[6]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[6]/internal-format</use>
</internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/terrain-haze-detailed.vert</vertex-shader>
<fragment-shader>Shaders/terrain-haze-detailed.frag</fragment-shader>
</program>
<uniform>
<name>visibility</name>
<type>float</type>
<value><use>visibility</use></value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value><use>avisibility</use></value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value><use>lthickness</use></value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value><use>scattering</use></value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value><use>terminator</use></value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>mysnowlevel</name>
<type>float</type>
<value> <use>mysnow_level</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value> <use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value> <use>fogstructure</use></value>
</uniform>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>NoiseTex</name>
<type>sampler-3d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>snow_texture</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<depth>
<function>lequal</function>
<write-mask type="bool">false</write-mask>
</depth>
</pass>
</technique>
<technique n="4">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<less-equal>
<value type="float">4.0</value>
<float-property>/sim/rendering/shaders/landmass</float-property>
</less-equal>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<alpha-test><use>transparent</use></alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number>-1</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<image><use>texture[0]/image</use></image>
<filter><use>texture[0]/filter</use></filter>
<wrap-s><use>texture[0]/wrap-s</use></wrap-s>
<wrap-t><use>texture[0]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>
<!--<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>-->
<program>
<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
<vertex-shader n="1">Shaders/default.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/terrain-nocolor.frag</fragment-shader>
</program>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<color-mask type="vec4d">0 0 0 0</color-mask>
</pass>
<pass>
<lighting>true</lighting>
<material>
<ambient><use>material/ambient</use></ambient>
<diffuse><use>material/diffuse</use></diffuse>
<specular><use>material/specular</use></specular>
<emissive><use>material/emissive</use></emissive>
<shininess><use>material/shininess</use></shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend><use>transparent</use></blend>
<alpha-test><use>transparent</use></alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number><use>render-bin/bin-number</use></bin-number>
<bin-name><use>render-bin/bin-name</use></bin-name>
</render-bin>
<texture-unit>
<unit>0</unit>
<image><use>texture[0]/image</use></image>
<filter><use>texture[0]/filter</use></filter>
<wrap-s><use>texture[0]/wrap-s</use></wrap-s>
<wrap-t><use>texture[0]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>
<texture-unit>
<unit>6</unit>
<image><use>texture[6]/image</use></image>
<filter><use>texture[6]/filter</use></filter>
<wrap-s><use>texture[6]/wrap-s</use></wrap-s>
<wrap-t><use>texture[6]/wrap-t</use></wrap-t>
<internal-format>
<use>texture[6]/internal-format</use>
</internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/terrain-haze-detailed.vert</vertex-shader>
<fragment-shader>Shaders/terrain-haze-detailed.frag</fragment-shader>
</program>
<uniform>
<name>visibility</name>
<type>float</type>
<value><use>visibility</use></value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value><use>avisibility</use></value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value><use>lthickness</use></value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value><use>scattering</use></value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value><use>terminator</use></value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>mysnowlevel</name>
<type>float</type>
<value> <use>mysnow_level</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value> <use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value> <use>fogstructure</use></value>
</uniform>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>NoiseTex</name>
<type>sampler-3d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>snow_texture</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<depth>
<function>lequal</function>
<write-mask type="bool">false</write-mask>
</depth>
</pass>
</technique>
<technique n="5"> <technique n="5">
<predicate> <predicate>
<and> <and>
@ -158,6 +571,11 @@
<type>float</type> <type>float</type>
<value><use>scattering</use></value> <value><use>scattering</use></value>
</uniform> </uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform> <uniform>
<name>terminator</name> <name>terminator</name>
<type>float</type> <type>float</type>

View file

@ -109,26 +109,443 @@
</WaveDAngle> </WaveDAngle>
<!-- fog include --> <!-- fog include -->
<visibility> <visibility><use>/environment/ground-visibility-m</use></visibility>
<use>/environment/ground-visibility-m</use> <avisibility><use>/environment/visibility-m</use></avisibility>
</visibility> <lthickness><use>/environment/ground-haze-thickness-m</use></lthickness>
<avisibility> <scattering><use>/rendering/scene/scattering</use></scattering>
<use>/environment/visibility-m</use> <ground_scattering><use>/environment/surface/scattering</use></ground_scattering>
</avisibility> <terminator><use>/environment/terminator-relative-position-m</use></terminator>
<lthickness> <terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<use>/environment/ground-haze-thickness-m</use> <overcast><use>/rendering/scene/overcast</use></overcast>
</lthickness> <eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<scattering>
<use>/rendering/scene/scattering</use>
</scattering>
<terminator>
<use>/environment/terminator-relative-position-m</use>
</terminator>
<fogtype> <fogtype>
<use>/sim/rendering/shaders/skydome</use> <use>/sim/rendering/shaders/skydome</use>
</fogtype> </fogtype>
<!-- sea colors -->
<sea_r><use>/environment/sea/color_r</use></sea_r>
<sea_g><use>/environment/sea/color_g</use></sea_g>
<sea_b><use>/environment/sea/color_b</use></sea_b>
<!-- END fog include --> <!-- END fog include -->
</parameters> </parameters>
<technique n="3">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<less-equal>
<value type="float">4.0</value>
<float-property>/sim/rendering/shaders/water</float-property>
</less-equal>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend>
<use>transparent</use>
</blend>
<alpha-test>
<use>transparent</use>
</alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number>
<use>render-bin/bin-number</use>
</bin-number>
<bin-name>
<use>render-bin/bin-name</use>
</bin-name>
</render-bin>
<!--<texture-unit>
<unit>0</unit>
<image>
<use>texture[0]/image</use>
</image>
<filter>
<use>texture[0]/filter</use>
</filter>
<wrap-s>
<use>texture[0]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[0]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>-->
<!--<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>-->
<texture-unit>
<unit>2</unit>
<image>
<use>texture[2]/image</use>
</image>
<filter>
<use>texture[2]/filter</use>
</filter>
<wrap-s>
<use>texture[2]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[2]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[2]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>3</unit>
<image>
<use>texture[3]/image</use>
</image>
<filter>
<use>texture[3]/filter</use>
</filter>
<wrap-s>
<use>texture[3]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[3]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[3]/internal-format</use>
</internal-format>
</texture-unit>
<!--<texture-unit>
<unit>4</unit>
<image>
<use>texture[4]/image</use>
</image>
<filter>
<use>texture[4]/filter</use>
</filter>
<wrap-s>
<use>texture[4]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[4]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[4]/internal-format</use>
</internal-format>
</texture-unit>-->
<texture-unit>
<unit>5</unit>
<image>
<use>texture[5]/image</use>
</image>
<filter>
<use>texture[5]/filter</use>
</filter>
<wrap-s>
<use>texture[5]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[5]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[5]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>6</unit>
<image>
<use>texture[6]/image</use>
</image>
<filter>
<use>texture[6]/filter</use>
</filter>
<wrap-s>
<use>texture[6]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[6]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[6]/internal-format</use>
</internal-format>
</texture-unit>
<program>
<!-- <vertex-shader>Shaders/include_fog.vert</vertex-shader> -->
<vertex-shader>Shaders/water_lightfield.vert</vertex-shader>
<!--<fragment-shader>Shaders/include_fog.frag</fragment-shader>-->
<fragment-shader>Shaders/water_lightfield.frag</fragment-shader>
</program>
<!--<uniform>
<name>water_reflection</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>-->
<!--<uniform>
<name>Noise</name>
<type>sampler-3d</type>
<value type="int">1</value>
</uniform>-->
<uniform>
<name>water_normalmap</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>water_dudvmap</name>
<type>sampler-2d</type>
<value type="int">3</value>
</uniform>
<!--<uniform>
<name>water_reflection_grey</name>
<type>sampler-2d</type>
<value type="int">4</value>
</uniform>-->
<uniform>
<name>sea_foam</name>
<type>sampler-2d</type>
<value type="int">5</value>
</uniform>
<uniform>
<name>perlin_normalmap</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>saturation</name>
<type>float</type>
<!--<value>0.4</value>-->
<value><use>saturation</use></value>
</uniform>
<!--<uniform>
<name>CloudCover0</name>
<type>float</type>
<value>
<use>cloud-cover[0]</use>
</value>
</uniform>
<uniform>
<name>CloudCover1</name>
<type>float</type>
<value>
<use>cloud-cover[1]</use>
</value>
</uniform>
<uniform>
<name>CloudCover2</name>
<type>float</type>
<value>
<use>cloud-cover[2]</use>
</value>
</uniform>
<uniform>
<name>CloudCover3</name>
<type>float</type>
<value>
<use>cloud-cover[3]</use>
</value>
</uniform>
<uniform>
<name>CloudCover4</name>
<type>float</type>
<value>
<use>cloud-cover[4]</use>
</value>
</uniform>
<uniform>
<name>Status</name>
<type>int</type>
<value>
<use>status</use>
</value>
</uniform>-->
<!--<uniform>
<name>Overcast</name>
<type>float</type>
<value>
<use>overcast</use>
</value>
</uniform>-->
<uniform>
<name>WindE</name>
<type>float</type>
<value>
<use>windE</use>
</value>
</uniform>
<uniform>
<name>WindN</name>
<type>float</type>
<value>
<use>windN</use>
</value>
</uniform>
<!-- uniform> unused?
<name>WindFrom</name>
<type>float</type>
<value>
<use>wind-from</use>
</value>
</uniform-->
<uniform>
<name>WaveFreq</name>
<type>float</type>
<value>
<use>WaveFreq</use>
</value>
</uniform>
<uniform>
<name>WaveAmp</name>
<type>float</type>
<value>
<use>WaveAmp</use>
</value>
</uniform>
<uniform>
<name>WaveSharp</name>
<type>float</type>
<value>
<use>WaveSharp</use>
</value>
</uniform>
<uniform>
<name>WaveAngle</name>
<type>float</type>
<value>
<use>WaveAngle</use>
</value>
</uniform>
<uniform>
<name>WaveFactor</name>
<type>float</type>
<value>
<use>WaveFactor</use>
</value>
</uniform>
<uniform>
<name>WaveDAngle</name>
<type>float</type>
<value>
<use>WaveDAngle</use>
</value>
</uniform>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<!-- sea colors -->
<uniform>
<name>sea_r</name>
<type>float</type>
<value><use>sea_r</use></value>
</uniform>
<uniform>
<name>sea_g</name>
<type>float</type>
<value><use>sea_g</use></value>
</uniform>
<uniform>
<name>sea_b</name>
<type>float</type>
<value><use>sea_b</use></value>
</uniform>
<!--<uniform>
<name>fogType</name>
<type>int</type>
<value>
<use>fogtype</use>
</value>
</uniform>-->
<!-- END fog include -->
</pass>
</technique>
<technique n="8"> <technique n="8">
<predicate> <predicate>
<and> <and>
@ -742,7 +1159,6 @@
<value> <value>
<use>status</use> <use>status</use>
</value> </value>
<!--<value type="int">0</value> -->
</uniform> </uniform>
<uniform> <uniform>
<name>Overcast</name> <name>Overcast</name>

View file

@ -333,12 +333,22 @@
<config> <config>
<wind-filter-time type="double">0.05</wind-filter-time> <wind-filter-time type="double">0.05</wind-filter-time>
</config> </config>
<color_r type="double" userarchive="n">0.148</color_r>
<color_g type="double" userarchive="n">0.27</color_g>
<color_b type="double" userarchive="n">0.3</color_b>
</sea> </sea>
<!-- definitions for the scattering skydome shader --> <!-- definitions for the scattering skydome shader -->
<ground-visibility-m type="double" userarchive="n">16000.0</ground-visibility-m> <ground-visibility-m type="double" userarchive="n">16000.0</ground-visibility-m>
<air-pollution-norm type="double" userarchive="n">0.0</air-pollution-norm>
<ground-haze-thickness-m type="double" userarchive="n">2000.0</ground-haze-thickness-m> <ground-haze-thickness-m type="double" userarchive="n">2000.0</ground-haze-thickness-m>
<terminator-relative-position-m type="double" userarchive="n">1000000.0</terminator-relative-position-m> <terminator-relative-position-m type="double" userarchive="n">1000000.0</terminator-relative-position-m>
<mean-terrain-elevation-m type="double" userarchive="n">0.0</mean-terrain-elevation-m> <mean-terrain-elevation-m type="double" userarchive="n">0.0</mean-terrain-elevation-m>
<mysnow-level-m type="double" userarchive="n">3200.0</mysnow-level-m>
<fog-structure type="double" userarchive="n">0.0</fog-structure>
<!-- definitions for the environment at surface interface -->
<surface>
<scattering type="double" userarchive="n">0.7</scattering>
<dust-cover-factor type="double" userarchive="n">0.0</dust-cover-factor>
</surface>
</PropertyList> </PropertyList>

View file

@ -410,7 +410,7 @@ else if (type == "Cumulus bottom"){
cloudAssembly.num_tex_y = 1; cloudAssembly.num_tex_y = 1;
#characterize the cloud #characterize the cloud
cloudAssembly.bottom_shade = 1.0; cloudAssembly.bottom_shade = 0.5;
cloudAssembly.n_sprites = 4; cloudAssembly.n_sprites = 4;
cloudAssembly.min_width = 600.0 * mult; cloudAssembly.min_width = 600.0 * mult;
cloudAssembly.max_width = 800.0 * mult; cloudAssembly.max_width = 800.0 * mult;
@ -452,7 +452,7 @@ else if (type == "Congestus bottom"){
cloudAssembly.num_tex_y = 1; cloudAssembly.num_tex_y = 1;
#characterize the cloud #characterize the cloud
cloudAssembly.bottom_shade = 0.7; cloudAssembly.bottom_shade = 0.5;
cloudAssembly.n_sprites = 4; cloudAssembly.n_sprites = 4;
cloudAssembly.min_width = 1100.0 * mult; cloudAssembly.min_width = 1100.0 * mult;
cloudAssembly.max_width = 1400.0 * mult; cloudAssembly.max_width = 1400.0 * mult;

View file

@ -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<ny; i=i+1)
{
und = und + 2.0 * (rand() -0.5) * und_strength;
append(und_array,und);
}
for (var i=0; i<ny; i=i+1)
{
var y = ymin + i * yoffset + 2.0 * (rand() -0.5) * 0.2 * yoffset;
for (var j=0; j<nx; j=j+1)
{
var y0 = y + y_var * 2.0 * (rand() -0.5);
var x = xmin + j * (xoffset + i * xinc) + x_var * 2.0 * (rand() -0.5) + und_array[i];
var lat = blat + m_to_lat * (y0 * math.cos(dir) - x * math.sin(dir));
var long = blong + m_to_lon * (x * math.cos(dir) + y0 * math.sin(dir));
var alt = balt + alt_var * 2 * (rand() - 0.5);
flag = 0;
var rn = 6.0 * rand();
if (((j<jlow) or (j>(nx-jlow-1))) and ((i<ilow) or (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<jlow) or (j>(nx-jlow-1)) or (i<ilow) 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<ny; i=i+1)
{
und = und + 2.0 * (rand() -0.5) * und_strength;
append(und_array,und);
}
for (var i=0; i<nx; i=i+1)
{
spacing = spacing + 2.0 * (rand() -0.5) * 0.5 * xoffset;
append(spacing_array,spacing);
}
for (var i=0; i<ny; i=i+1)
{
var y = ymin + i * yoffset;
var xshift = 2.0 * (rand() -0.5) * 0.5 * xoffset;
x_var = 0.0; xshift = 0.0;
for (var j=0; j<nx; j=j+1)
{
var y0 = y + y_var * 2.0 * (rand() -0.5);
var x = xmin + j * (xoffset + i * xinc) + x_var * 2.0 * (rand() -0.5) + spacing_array[j] + und_array[i];
var lat = blat + m_to_lat * (y0 * math.cos(dir) - x * math.sin(dir));
var lon = blon + m_to_lon * (x * math.cos(dir) + y0 * math.sin(dir));
var alt = balt + alt_var * 2 * (rand() - 0.5);
flag = 0;
var strength = 0.0;
var rn = 6.0 * rand();
if (((j<jlow) or (j>(nx-jlow-1))) and ((i<ilow) or (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<jlow) or (j>(nx-jlow-1)) or (i<ilow) 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<n)
{
var x = rx * (2.0 * rand() - 1.0);
var y = ry * (2.0 * rand() - 1.0);
var alt = balt + bthick * rand() + 0.8 * alt_offset;
var res = (x*x)/(rx*rx) + (y*y)/(ry*ry);
if (res < 1.0)
{
var lat = blat + m_to_lat * (y * math.cos(phi) - x * math.sin(phi));
var lon = blon + m_to_lon * (x * math.cos(phi) + y * math.sin(phi));
if (res > ((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<m)
{
var alpha = rand() * 2.0 * math.pi;
x = 0.8 * (1.0 - edge) * (1.0-edge) * rx * math.cos(alpha);
y = 0.8 * (1.0 - edge) * (1.0-edge) * ry * math.sin(alpha);
lat = blat + m_to_lat * (y * math.cos(phi) - x * math.sin(phi));
lon = blon + m_to_lon * (x * math.cos(phi) + y * math.sin(phi));
path = "Models/Weather/rain1.xml";
if (contains(cloud_vertical_size_map,type)) {var alt_shift = cloud_vertical_size_map[type];}
else {var alt_shift = 0.0;}
if (thread_flag == 1)
{create_cloud_vec(path, lat, lon,balt +0.5*bthick+ alt_shift, 0.0);}
else
{compat_layer.create_cloud(path, lat, lon, balt + 0.5 * bthick + alt_shift, 0.0);}
i = i + 1;
} # end while
} # end if (rainflag ==1)
}

View file

@ -183,6 +183,8 @@ if (local_weather.hardcoded_clouds_flag == 1)
} }
} }
@ -756,11 +758,13 @@ if (local_weather.dynamics_flag == 1)
########################################################### ###########################################################
# place a model # place a model
########################################################### ###########################################################
var place_model = func(path, lat, lon, alt, heading) { var place_model = func(path, lat, lon, alt, heading, pitch, yaw) {
@ -776,6 +780,8 @@ model.getNode("latitude-deg", 1).setValue(lat);
model.getNode("longitude-deg", 1).setValue(lon); model.getNode("longitude-deg", 1).setValue(lon);
model.getNode("elevation-ft", 1).setValue(alt); model.getNode("elevation-ft", 1).setValue(alt);
model.getNode("heading-deg", 1).setValue(heading); model.getNode("heading-deg", 1).setValue(heading);
model.getNode("pitch-deg", 1).setValue(pitch);
model.getNode("roll-deg", 1).setValue(yaw);
model.getNode("load", 1).remove(); model.getNode("load", 1).remove();
@ -784,7 +790,6 @@ model.getNode("load", 1).remove();
########################################################### ###########################################################
# place a single cloud using hard-coded system # place a single cloud using hard-coded system
########################################################### ###########################################################
@ -799,6 +804,11 @@ cloud_index = cloud_index + 1;
c.index = tile_counter; c.index = tile_counter;
c.cloud_index = cloud_index; c.cloud_index = cloud_index;
# light must be such that the top of a cloud cannot be darker than the bottom
if (c.bottom_shade > c.top_shade) {c.bottom_shade = c.top_shade;}
c.middle_shade = c.top_shade;
# write the actual cloud into the scenery # 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, "max-sprite-height-m": c.max_height,
"num-sprites": c.n_sprites, "num-sprites": c.n_sprites,
"min-bottom-lighting-factor": c.bottom_shade, "min-bottom-lighting-factor": c.bottom_shade,
"min-middle-lighting-factor": 0.9, "min-middle-lighting-factor": c.middle_shade,
"min-top-lighting-factor": 1.0, "min-top-lighting-factor": c.top_shade,
"min-shade-lighting-factor": c.bottom_shade, "min-shade-lighting-factor": c.bottom_shade,
"texture": c.texture_sheet, "texture": c.texture_sheet,
"num-textures-x": c.num_tex_x, "num-textures-x": c.num_tex_x,

View file

@ -34,15 +34,13 @@
# create_detailed_cumulus_cloud to place multiple cloudlets into a box based on a size parameter # 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 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_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 # cumulus_loop to place 25 Cumulus clouds each frame
# create_cumulus to place a convective cloud system based on terrain coverage # 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 # 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 # cumulus_exclusion_layer to create a layer with 'holes' left for thunderstorm placement
# create_rise_clouds to create a barrier cloud system # create_rise_clouds to create a barrier cloud system
# create_streak to create a cloud streak # 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_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) # create_cloudbox to create a sophisticated cumulus cloud with different textures (experimental)
# terrain_presampling_start to initialize terrain presampling # terrain_presampling_start to initialize terrain presampling
@ -640,29 +638,65 @@ if (vis > max_vis_range)
if (scattering_shader_flag == 1) if (scattering_shader_flag == 1)
{ {
var rayleigh = 0.0003 ; #var rayleigh = 0.0003 ;
var mie = 0.003; #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 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; rayleigh = 0.0003 - 0.0001 * vis_factor;
mie = 0.004 - altitude/30000.0 * 0.001; mie = 0.005 - vis_factor * 0.002;
}
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) else if (altitude < 85000.0)
{ {
rayleigh = 0.0002 - (altitude-60000.0)/25000.0 * 0.0001; rayleigh = (0.0003 - 0.0001 * vis_factor) - (altitude-36000.0)/49000.0 * 0.0001;
mie = 0.002; mie = 0.005 - vis_factor * 0.002 - (altitude-36000.0)/49000.0 * 0.002;
} }
else 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 # otherwise compute normal skydome shader parameters
@ -727,6 +761,8 @@ local_weather.setScattering(scatt);
local_weather.setOvercast(ovcst); local_weather.setOvercast(ovcst);
# now check if an effect volume writes the property and set only if not # now check if an effect volume writes the property and set only if not
flag = getprop("local-weather/effect-volumes/number-active-vis"); flag = getprop("local-weather/effect-volumes/number-active-vis");
@ -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-from-heading-deg",winddir);
setprop("/environment/config/boundary/entry[0]/wind-speed-kt",windspeed_ground); 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 # 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);} 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.lat = lat;
local_weather.cloudAssembly.lon = long; local_weather.cloudAssembly.lon = long;
local_weather.cloudAssembly.alt = alt; local_weather.cloudAssembly.alt = alt;
local_weather.cloudAssembly.top_shade = top_shade;
#print(lat," ",long, " ", alt); #print(lat," ",long, " ", alt);
@ -2564,158 +2606,10 @@ for (var i=0; i<ny; i=i+1)
} }
###########################################################
# 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";
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<ny; i=i+1)
{
und = und + 2.0 * (rand() -0.5) * und_strength;
append(und_array,und);
}
for (var i=0; i<ny; i=i+1)
{
var y = ymin + i * yoffset;
for (var j=0; j<nx; j=j+1)
{
var y0 = y + y_var * 2.0 * (rand() -0.5);
var x = xmin + j * (xoffset + i * xinc) + x_var * 2.0 * (rand() -0.5) + und_array[i];
var lat = blat + m_to_lat * (y0 * math.cos(dir) - x * math.sin(dir));
var long = blong + m_to_lon * (x * math.cos(dir) + y0 * math.sin(dir));
var alt = balt + alt_var * 2 * (rand() - 0.5);
flag = 0;
var rn = 6.0 * rand();
if (((j<jlow) or (j>(nx-jlow-1))) and ((i<ilow) or (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<jlow) or (j>(nx-jlow-1)) or (i<ilow) 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<n)
{
var x = rx * (2.0 * rand() - 1.0);
var y = ry * (2.0 * rand() - 1.0);
var alt = balt + bthick * rand() + 0.8 * alt_offset;
var res = (x*x)/(rx*rx) + (y*y)/(ry*ry);
if (res < 1.0)
{
var lat = blat + m_to_lat * (y * math.cos(phi) - x * math.sin(phi));
var lon = blon + m_to_lon * (x * math.cos(phi) + y * math.sin(phi));
if (res > ((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<m)
{
var alpha = rand() * 2.0 * math.pi;
x = 0.8 * (1.0 - edge) * (1.0-edge) * rx * math.cos(alpha);
y = 0.8 * (1.0 - edge) * (1.0-edge) * ry * math.sin(alpha);
lat = blat + m_to_lat * (y * math.cos(phi) - x * math.sin(phi));
lon = blon + m_to_lon * (x * math.cos(phi) + y * math.sin(phi));
path = "Models/Weather/rain1.xml";
if (contains(cloud_vertical_size_map,type)) {var alt_shift = cloud_vertical_size_map[type];}
else {var alt_shift = 0.0;}
if (thread_flag == 1)
{create_cloud_vec(path, lat, lon,balt +0.5*bthick+ alt_shift, 0.0);}
else
{compat_layer.create_cloud(path, lat, lon, balt + 0.5 * bthick + alt_shift, 0.0);}
i = i + 1;
} # end while
} # end if (rainflag ==1)
}
########################################################### ###########################################################
@ -4176,7 +4070,9 @@ if (buffer_flag == 1)
} }
} }
# start the sea color loop
local_weather.init_sea_colors();
# weather_tile_management.watchdog_loop(); # weather_tile_management.watchdog_loop();
@ -4274,7 +4170,9 @@ setlistener(lw~"config/aux-max-vis-range-m", func {max_vis_range = math.exp(getp
setlistener(lw~"config/temperature-offset-degc", func {temperature_offset = getprop(lw~"config/temperature-offset-degc");}); setlistener(lw~"config/temperature-offset-degc", func {temperature_offset = getprop(lw~"config/temperature-offset-degc");});
setlistener("/sim/rendering/shaders/skydome", func {scattering_shader_flag = getprop("/sim/rendering/shaders/skydome"); }); setlistener("/environment/air-pollution-norm", func {air_pollution_norm = getprop("/environment/air-pollution-norm");});
setlistener("/sim/rendering/shaders/skydome", func {scattering_shader_flag = getprop("/sim/rendering/shaders/skydome"); if (scattering_shader_flag ==1) {setprop("/sim/rendering/minimum-sky-visibility",0.0);} else {setprop("/sim/rendering/minimum-sky-visibility",1000.0);} });
} }
@ -4312,7 +4210,8 @@ presampling_flag = 0;
#create_cumulonimbus_cloud(lat, lon, 6000.0, 2.5); #create_cumulonimbus_cloud(lat, lon, 6000.0, 2.5);
local_weather.place_model("Models/Weather/cloudsphere.ac",lat, lon, alt-10000.0, 0.0); earthview.place_earth_model("Models/Astro/earth.xml",lat, lon, 0.0, 0.0, 0.0, 0.0);
earthview.place_earth_model("Models/Astro/cloudsphere.xml",lat, lon, 0.0, 0.0, 0.0, 0.0);
#setprop("/environment/terrain/area[0]/input/latitude-deg", lat ); #setprop("/environment/terrain/area[0]/input/latitude-deg", lat );
#setprop("/environment/terrain/area[0]/input/longitude-deg", lon ); #setprop("/environment/terrain/area[0]/input/longitude-deg", lon );
@ -4680,6 +4579,10 @@ var convective_size_bias = 0.0;
var cumulus_efficiency_factor = 1.0; var cumulus_efficiency_factor = 1.0;
var cloud_mean_altitude = 0.0; var cloud_mean_altitude = 0.0;
# global keeping track of lighting
var top_shade = 1.0;
# globals keeping track of the lifetime when building a Cumulus from individual cloudlets # globals keeping track of the lifetime when building a Cumulus from individual cloudlets
var cloud_fractional_lifetime = 0.0; var cloud_fractional_lifetime = 0.0;
@ -4714,6 +4617,7 @@ var ground_haze_factor = 1.0;
var max_vis_range = 120000.0; var max_vis_range = 120000.0;
var temperature_offset = 0.0; var temperature_offset = 0.0;
var current_mean_alt = 0.0; var current_mean_alt = 0.0;
var air_pollution_norm = 0.0;
# globals for framerate controlled cloud management # globals for framerate controlled cloud management

View file

@ -0,0 +1,96 @@
#################################################################
# object classes
#################################################################
var seaColorPoint = {
new: func (lat, lon, weight, deep_r, deep_g, deep_b) {
var s = { parents: [seaColorPoint] };
s.lat = lat;
s.lon = lon;
s.weight = weight;
s.r = deep_r;
s.g = deep_g;
s.b = deep_b;
return s;
},
};
#################################################################
# functions
#################################################################
var init_sea_colors = func {
var viewpos = geo.aircraft_position();
# St. Tropez
var s = seaColorPoint.new(43.20, 6.47, 1.0,0.03, 0.22, 0.46);
var ppos = geo.Coord.new();
ppos.set_latlon(s.lat,s.lon,0.0);
s.distance = viewpos.distance_to(ppos);
append(interpolation_vector,s);
# St. Maarten
s = seaColorPoint.new(18.03, -63.11, 1.0,0.08, 0.40, 0.425,0.66);
var ppos = geo.Coord.new();
ppos.set_latlon(s.lat,s.lon,0.0);
s.distance = viewpos.distance_to(ppos);
append(interpolation_vector,s);
ivector_size = size(interpolation_vector);
sea_color_loop(0);
}
var sea_color_loop = func (index) {
if (local_weather.local_weather_running_flag == 0) {return;}
if (index > (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 = [];

View file

@ -54,6 +54,10 @@ var dir_index = getprop(lw~"tiles/tmp/dir-index");
local_weather.assemble_effect_array(); local_weather.assemble_effect_array();
# reset lighting
local_weather.top_shade = 1.0;
if (local_weather.debug_output_flag == 1) if (local_weather.debug_output_flag == 1)
{print("Finished setting up tile type ",current_code, " in direction ",dir_index);} {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); #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_2_8_altocumulus_streaks(blat, blon, 12000+alt_offset, alpha) ;
#create_6_8_stratus(blat, blon, 3000+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_tstratus_patches(blat, blon, 5000+alt_offset, alpha) ;
#create_4_8_sstratus_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_cirrostratus_patches(blat, blon, 5000+alt_offset, alpha) ;
#create_4_8_cirrocumulus_streaks(blat, blon, 10000.0 + 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_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_nimbus_rain(blat, blon, 3000.0, alpha, 0.3) ;
#create_8_8_tstratus(blat, blon, 5000+alt_offset, alpha); #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, 30000.0, alpha);
#create_2_8_cirrus(blat, blon, 20000.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 #store convective altitude and strength
@ -191,6 +200,9 @@ var alt = spread * 400;
var strength = 0.0; 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(); var rn = rand();
if (rand() < small_scale_persistence) if (rand() < small_scale_persistence)
@ -198,9 +210,9 @@ if (rand() < small_scale_persistence)
else else
{rnd_store = rn;} {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 # cloud scenario 1: weak cumulus development and blue thermals
@ -220,7 +232,7 @@ if (rn > 0.833)
# and specify the atmosphere # 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); 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 # cloud scenario 2: some Cirrocumulus patches
@ -234,7 +246,7 @@ else if (rn > 0.666)
# and specify the atmosphere # 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); 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 # 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); 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 # cloud scenario 4: Cirrostratus undulatus streak
@ -259,7 +271,7 @@ else if (rn > 0.333)
# and specify the atmosphere # 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); 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 # cloud scenario 5: Cirrus
@ -274,13 +286,33 @@ else if (rn > 0.166)
# and specify the atmosphere # 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); 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 # cloud scenario 6: strong Cirrus cover
create_4_8_cirrus(blat, blon, alt + alt_offset + 35000.0, alpha); 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); 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 # store convective altitude and strength
@ -347,7 +379,7 @@ else
# rn = 0.1; # rn = 0.1;
if (rn > 0.8) if (rn > 0.875)
{ {
# cloud scenario 1: possible Cirrus over Cumulus # cloud scenario 1: possible Cirrus over Cumulus
strength = 0.2 + rand() * 0.4; 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); 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 # 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); 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 # 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); 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 # cloud scenario 4: Cirrostratus undulatus over weak Cumulus
@ -416,7 +448,7 @@ else if (rn > 0.2)
# and specify the atmosphere # 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); 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 # cloud scenario 5: some scattered Altocumuli over Cumulus
@ -430,6 +462,43 @@ else if (rn > 0.0)
# and specify the atmosphere # 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); 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 # store convective altitude and strength
@ -488,13 +557,17 @@ var strength = 0.0;
var rn = rand(); var rn = rand();
if (rand() < small_scale_persistence) if (rand() < small_scale_persistence)
{rn = rnd_store;} {rn = rnd_store;}
else else
{rnd_store = rn;} {rnd_store = rn;}
if (rn > 0.888) # rn = 0.05;
if (rn > 0.9)
{ {
# cloud scenario 1: Altocumulus patch over weak Cumulus # cloud scenario 1: Altocumulus patch over weak Cumulus
strength = 0.1 + rand() * 0.1; 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); 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 # cloud scenario 2: Altocumulus streaks
strength = 0.15 + rand() * 0.2; 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); 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 # 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); 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 # 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); 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 # 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); 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 # cloud scenario 6: Cirrocumulus sheets
@ -590,7 +663,7 @@ else if (rn > 0.333)
# and specify the atmosphere # 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); 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 # 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); 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 # 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); 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 # cloud scenario 9: Cumulus, Altocumulus and Cirrus
@ -630,7 +703,16 @@ else if (rn > 0.0)
# and specify the atmosphere # 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); 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 # store convective altitude and strength
@ -700,8 +782,10 @@ if (rand() < small_scale_persistence)
else else
{rnd_store = rn;} {rnd_store = rn;}
# rn = 0.05;
if (rn > 0.857)
if (rn > 0.875)
{ {
# cloud scenario 1: low Stratocumulus, thin streaks above # 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); 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 # cloud scenario 2: weak Cumulus, Stratus undulatus above
@ -730,7 +814,7 @@ else if (rn > 0.714)
# and specify the atmosphere # 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); 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 # cloud scenario 3: Stratocumulus banks with patches above
@ -742,7 +826,7 @@ else if (rn > 0.571)
# and specify the atmosphere # 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); 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 # cloud scenario 4: structured Stratus
@ -753,7 +837,7 @@ else if (rn > 0.428)
# and specify the atmosphere # 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); 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 # cloud scenario 5: Stratus blending with Cumulus with Cirrocumulus above
@ -767,7 +851,7 @@ else if (rn > 0.285)
# and specify the atmosphere # 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); 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 # cloud scenario 6: small Stratocumulus banks
@ -781,7 +865,7 @@ else if (rn > 0.142)
# and specify the atmosphere # 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); 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 # cloud scenario 7: blended structured and unstructured Stratiform clouds
@ -793,6 +877,19 @@ else
# and specify the atmosphere # 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); 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 alt = spread * 400.0;
var strength = 0.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(); var rn = rand();
if (rand() < small_scale_persistence) if (rand() < small_scale_persistence)
@ -1093,7 +1193,7 @@ else
if (rn > 0.5) if (rn > 0.5)
{ {
# cloud scenario 1: strong Cumulus development # 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); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
# and specify the atmosphere # and specify the atmosphere
@ -1104,7 +1204,7 @@ else if (rn > 0.0)
{ {
# cloud scenario 2: Cirrocumulus sheets over Cumulus # 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); local_weather.create_cumosys(blat,blon, alt + alt_offset, get_n(strength), 20000.0);
for (var i = 0; i < 2; i = i + 1) for (var i = 0; i < 2; i = i + 1)
@ -2293,19 +2393,23 @@ for (var i = n; i <n_layers; i=i+1)
if (altitude < 14000.0) if (altitude < 14000.0)
{ {
var rn = rand(); var rn = rand();
if (rn > 0.66) if (rn > 0.75)
{create_2_8_tstratus(blat, blon, altitude+metar_alt_offset, alpha);} {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);} {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);} {create_2_8_alttstratus(blat, blon, altitude+metar_alt_offset, alpha);}
} }
else else
{ {
var rn = rand(); 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);} {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);} {create_2_8_alttstratus(blat, blon, altitude+metar_alt_offset, alpha);}
} }
@ -2627,7 +2731,7 @@ if (rain > 0.1)
} }
else 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); 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 create_4_8_cirrus = func (lat, lon, alt, alpha) {
var phi = alpha * math.pi/180.0; 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 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; 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) { 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 tri = 1.5 + rand();
var beta = rand() * math.pi; 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, 8000.0, 4500.0, beta, 10.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, 8500.0, 5000.0, beta, 15.0, 0.25, 0, 0.0);
} }
} }

View file

@ -7,9 +7,8 @@ void main(void)
{ {
vec4 base = texture2D( baseTexture, gl_TexCoord[0].st); vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);
vec4 finalColor = base * gl_Color; 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.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)); gl_FragColor.a = mix(0.0, finalColor.a, 1.0 - 0.5 * (1.0 - fogFactor));
} }

View file

@ -2,6 +2,7 @@
#version 120 #version 120
varying float fogFactor; varying float fogFactor;
//varying float MieFactor;
varying vec3 hazeColor; varying vec3 hazeColor;
uniform float range; // From /sim/rendering/clouds3d-vis-range 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)); 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) void main(void)
{ {
@ -104,6 +111,8 @@ void main(void)
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz; vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0)); vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction, corrected for altitude // 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 // the altitude correction is clamped to reasonable values, sometimes altitude isn't parsed correctly, leading
// to overbright or overdark clouds // to overbright or overdark clouds
@ -146,7 +155,6 @@ void main(void)
//fogFactor = clamp(fogFactor, 0.0, 1.0); //fogFactor = clamp(fogFactor, 0.0, 1.0);
// haze of ground haze shader is slightly bluish // 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 = light_diffuse.xyz;
hazeColor.x = hazeColor.x * 0.83; hazeColor.x = hazeColor.x * 0.83;
hazeColor.y = hazeColor.y * 0.9; 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 = intensity * normalize(mix(hazeColor, 2.0* vec3 (0.55, 0.6, 0.8), (1.0 - smoothstep(0.3,0.8,scattering))));
hazeColor = hazeColor * earthShade; hazeColor = hazeColor * earthShade;
gl_FrontColor.xyz = gl_FrontColor.xyz * earthShade; gl_FrontColor.xyz = gl_FrontColor.xyz * earthShade;
gl_BackColor = gl_FrontColor;
// 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;
} }

View file

@ -80,13 +80,20 @@ void main()
// if (color.y > 0.8) color.y = 0.8 + 0.8* log(color.y/0.8); // if (color.y > 0.8) color.y = 0.8 + 0.8* log(color.y/0.8);
// if (color.z > 0.8) color.z = 0.8 + 0.8* log(color.z/0.8); // 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 // 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)); //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)); //else color = mix (color, black, smoothstep(0.2+cthorizon,-0.2+cthorizon, cthorizon));
@ -101,10 +108,10 @@ float delta_zv;
float costheta = ct; 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 // 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 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 // combined intensity reduction by cloud shading and fog self-shading, corrected for Weber-Fechner perception law
float eqColorFactor; //float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(avisibility, 1.5 * avisibility, -alt/costheta);
eqColorFactor = 1.0 - 0.1 * delta_zv/vis - (1.0 -scattering);
float eqColorFactor = 1.0 - 0.1 * delta_zv/vis - (1.0 -scattering);
// there's always residual intensity, we should never be driven to zero // there's always residual intensity, we should never be driven to zero

View file

@ -43,7 +43,8 @@ const float fSamples = float(nSamples);
uniform float rK = 0.0003; //0.00015; uniform float rK = 0.0003; //0.00015;
uniform float mK = 0.003; //0.0025; uniform float mK = 0.003; //0.0025;
uniform float density = 0.5; //1.0 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 mieK = vec3(mK);
vec3 sunIntensity = 10.0*vec3(120.0, 125.0, 130.0); vec3 sunIntensity = 10.0*vec3(120.0, 125.0, 130.0);
@ -235,7 +236,7 @@ void main()
{ {
if (ct < 0.0) 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); yprime = yprime -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
} }
else // the only haze we see looking up is overcast, assume its altitude else // the only haze we see looking up is overcast, assume its altitude

View file

@ -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);
}

View file

@ -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;
}

View file

@ -25,6 +25,7 @@ varying float mie_angle;
uniform float visibility; uniform float visibility;
uniform float avisibility; uniform float avisibility;
uniform float scattering; uniform float scattering;
//uniform float ground_scattering;
uniform float terminator; uniform float terminator;
uniform float terrain_alt; uniform float terrain_alt;
uniform float hazeLayerAltitude; uniform float hazeLayerAltitude;
@ -157,8 +158,7 @@ if (delta_z > 0.0) // we're inside the layer
if (ct < 0.0) // we look down if (ct < 0.0) // we look down
{ {
distance_in_layer = dist; distance_in_layer = dist;
//lambda = visibility; vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude; delta_zv = delta_z - vAltitude;
} }
else // we may look through upper layer edge 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; H = dist * ct;
if (H > delta_z) {distance_in_layer = dist/H * delta_z;} if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
else {distance_in_layer = dist;} else {distance_in_layer = dist;}
//lambda = visibility;
vAltitude = min(distance_in_layer,visibility) * ct; vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude; delta_zv = delta_z - vAltitude;
} }
@ -198,6 +197,7 @@ transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor; float eqColorFactor;
//float scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, relPos.z + eye_alt);
if (visibility < avisibility) if (visibility < avisibility)
{ {
@ -214,6 +214,7 @@ else
} }
transmission = fog_func(transmission_arg); transmission = fog_func(transmission_arg);
// there's always residual intensity, we should never be driven to zero // 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 // Mie-like factor
if (lightArg < 5.0) if (lightArg < 10.0)
{intensity = length(hazeColor); {intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt)); 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)) ); 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)) );

View file

@ -38,7 +38,8 @@ uniform float terrain_alt;
uniform float avisibility; uniform float avisibility;
uniform float visibility; uniform float visibility;
uniform float overcast; 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? // 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 lightArg;
float intensity; float intensity;
float vertex_alt; float vertex_alt;
float scattering;
// this code is copied from default.vert // this code is copied from default.vert
@ -101,12 +103,15 @@ void main()
// is later computed in the fragment shader again // is later computed in the fragment shader again
float dist = length(relPos); 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 // branch dependent on daytime
if (terminator < 1000000.0) // the full, sunrise and sunset computation 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 // 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; lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun // directional scattering for low sun
if (lightArg < 5.0) if (lightArg < 10.0)
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;} {mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else else
{mie_angle = 1.0;} {mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 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.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.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; light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude); yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
} }

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -0,0 +1,157 @@
<?xml version="1.0"?>
<PropertyList>
<name>local_weather_environment</name>
<width>400</width>
<height>210</height>
<modal>false</modal>
<text>
<x>5</x>
<y>180</y>
<label>Environment parameters (only used by detailed shaders)</label>
</text>
<text>
<x>5</x>
<y>150</y>
<label>Snow line:</label>
</text>
<text>
<x>120</x>
<y>150</y>
<label>0 m </label>
</text>
<slider>
<x>190</x>
<y>150</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>7500.0</max>
<property>/environment/mysnow-level-m</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>290</x>
<y>150</y>
<label>7500 m</label>
</text>
<text>
<x>340</x>
<y>150</y>
<label>12345678</label>
<format>%.fm</format>
<live>true</live>
<property>/environment/mysnow-level-m</property>
</text>
<text>
<x>5</x>
<y>120</y>
<label>Terrain dust cover:</label>
</text>
<text>
<x>120</x>
<y>120</y>
<label>none </label>
</text>
<slider>
<x>190</x>
<y>120</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>0.7</max>
<property>/environment/surface/dust-cover-factor</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>290</x>
<y>120</y>
<label>dusty</label>
</text>
<text>
<x>5</x>
<y>90</y>
<label>Fog properties:</label>
</text>
<text>
<x>120</x>
<y>90</y>
<label>smooth </label>
</text>
<slider>
<x>190</x>
<y>90</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>12.0</max>
<property>/environment/fog-structure</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>290</x>
<y>90</y>
<label>structured</label>
</text>
<group>
<x>10</x>
<y>10</y>
<button>
<x>0</x>
<y>0</y>
<legend>OK</legend>
<!--<default>true</default>-->
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<x>265</x>
<y>0</y>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
</PropertyList>

View file

@ -6,20 +6,20 @@
<name>local_weather_tiles</name> <name>local_weather_tiles</name>
<width>470</width> <width>470</width>
<height>385</height> <height>410</height>
<modal>false</modal> <modal>false</modal>
<text> <text>
<x>5</x> <x>5</x>
<y>355</y> <y>380</y>
<label>Select initial weather scenario tile</label> <label>Select initial weather scenario tile</label>
</text> </text>
<combo> <combo>
<x>10</x> <x>10</x>
<y>330</y> <y>355</y>
<width>280</width> <width>280</width>
<height>25</height> <height>25</height>
<live>true</live> <live>true</live>
@ -53,7 +53,7 @@
<text> <text>
<x>300</x> <x>300</x>
<y>330</y> <y>355</y>
<label>alt. offset (ft)</label> <label>alt. offset (ft)</label>
</text> </text>
@ -61,7 +61,7 @@
<input> <input>
<x>390</x> <x>390</x>
<y>330</y> <y>355</y>
<width>50</width> <width>50</width>
<height>25</height> <height>25</height>
<property>/local-weather/tmp/tile-alt-offset-ft</property> <property>/local-weather/tmp/tile-alt-offset-ft</property>
@ -70,13 +70,13 @@
<text> <text>
<x>5</x> <x>5</x>
<y>295</y> <y>320</y>
<label>wind deg</label> <label>wind deg</label>
</text> </text>
<input> <input>
<x>67</x> <x>67</x>
<y>295</y> <y>320</y>
<width>40</width> <width>40</width>
<height>25</height> <height>25</height>
<property>/local-weather/tmp/tile-orientation-deg</property> <property>/local-weather/tmp/tile-orientation-deg</property>
@ -84,13 +84,13 @@
<text> <text>
<x>105</x> <x>105</x>
<y>295</y> <y>320</y>
<label>kt</label> <label>kt</label>
</text> </text>
<input> <input>
<x>125</x> <x>125</x>
<y>295</y> <y>320</y>
<width>30</width> <width>30</width>
<height>25</height> <height>25</height>
<property>/local-weather/tmp/windspeed-kt</property> <property>/local-weather/tmp/windspeed-kt</property>
@ -100,7 +100,7 @@
<text> <text>
<x>157</x> <x>157</x>
<y>295</y> <y>320</y>
<label>gust freq.</label> <label>gust freq.</label>
</text> </text>
@ -108,7 +108,7 @@
<slider> <slider>
<x>225</x> <x>225</x>
<y>295</y> <y>320</y>
<width>50</width> <width>50</width>
<height>20</height> <height>20</height>
<min>0.0</min> <min>0.0</min>
@ -123,14 +123,14 @@
<text> <text>
<x>275</x> <x>275</x>
<y>295</y> <y>320</y>
<label>strength</label> <label>strength</label>
</text> </text>
<slider> <slider>
<x>333</x> <x>333</x>
<y>295</y> <y>320</y>
<width>50</width> <width>50</width>
<height>20</height> <height>20</height>
<min>0.0</min> <min>0.0</min>
@ -143,14 +143,14 @@
<text> <text>
<x>380</x> <x>380</x>
<y>295</y> <y>320</y>
<label>dir.</label> <label>dir.</label>
</text> </text>
<slider> <slider>
<x>410</x> <x>410</x>
<y>295</y> <y>320</y>
<width>50</width> <width>50</width>
<height>20</height> <height>20</height>
<min>0.0</min> <min>0.0</min>
@ -166,14 +166,14 @@
<text> <text>
<x>5</x> <x>5</x>
<y>265</y> <y>290</y>
<label>wind model</label> <label>wind model</label>
</text> </text>
<combo> <combo>
<x>150</x> <x>150</x>
<y>265</y> <y>290</y>
<width>140</width> <width>140</width>
<height>25</height> <height>25</height>
<live>true</live> <live>true</live>
@ -191,7 +191,7 @@
<text> <text>
<x>300</x> <x>300</x>
<y>265</y> <y>290</y>
<label>T offset (C)</label> <label>T offset (C)</label>
</text> </text>
@ -199,7 +199,7 @@
<input> <input>
<x>390</x> <x>390</x>
<y>265</y> <y>290</y>
<width>50</width> <width>50</width>
<height>25</height> <height>25</height>
<property>/local-weather/config/temperature-offset-degc</property> <property>/local-weather/config/temperature-offset-degc</property>
@ -208,13 +208,13 @@
<text> <text>
<x>5</x> <x>5</x>
<y>235</y> <y>260</y>
<label>tile selection mode</label> <label>tile selection mode</label>
</text> </text>
<combo> <combo>
<x>150</x> <x>150</x>
<y>235</y> <y>260</y>
<width>140</width> <width>140</width>
<height>25</height> <height>25</height>
<live>true</live> <live>true</live>
@ -231,7 +231,7 @@
<checkbox> <checkbox>
<x>10</x> <x>10</x>
<y>205</y> <y>230</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>debug output</label> <label>debug output</label>
@ -279,7 +279,7 @@
<checkbox> <checkbox>
<x>150</x> <x>150</x>
<y>205</y> <y>230</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>terrain effects</label> <label>terrain effects</label>
@ -291,7 +291,7 @@
<checkbox> <checkbox>
<x>290</x> <x>290</x>
<y>205</y> <y>230</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>realistic visibility</label> <label>realistic visibility</label>
@ -303,7 +303,7 @@
<checkbox> <checkbox>
<x>10</x> <x>10</x>
<y>180</y> <y>205</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>generate thermals</label> <label>generate thermals</label>
@ -315,7 +315,7 @@
<checkbox> <checkbox>
<x>150</x> <x>150</x>
<y>180</y> <y>205</y>
<width>15</width> <width>15</width>
<height>15</height> <height>15</height>
<label>terrain presampling</label> <label>terrain presampling</label>
@ -328,19 +328,19 @@
<text> <text>
<x>5</x> <x>5</x>
<y>150</y> <y>175</y>
<label>Thermal properties:</label> <label>Thermal properties:</label>
</text> </text>
<text> <text>
<x>160</x> <x>160</x>
<y>150</y> <y>175</y>
<label>rough day</label> <label>rough day</label>
</text> </text>
<slider> <slider>
<x>230</x> <x>230</x>
<y>150</y> <y>175</y>
<width>90</width> <width>90</width>
<height>20</height> <height>20</height>
<min>0.3</min> <min>0.3</min>
@ -353,26 +353,26 @@
<text> <text>
<x>330</x> <x>330</x>
<y>150</y> <y>175</y>
<label>low convection</label> <label>low convection</label>
</text> </text>
<text> <text>
<x>5</x> <x>5</x>
<y>125</y> <y>150</y>
<label>Ground haze:</label> <label>Ground haze:</label>
</text> </text>
<text> <text>
<x>160</x> <x>160</x>
<y>125</y> <y>150</y>
<label>thick</label> <label>thick</label>
</text> </text>
<slider> <slider>
<x>230</x> <x>230</x>
<y>125</y> <y>150</y>
<width>90</width> <width>90</width>
<height>20</height> <height>20</height>
<min>0.1</min> <min>0.1</min>
@ -385,10 +385,41 @@
<text> <text>
<x>330</x> <x>330</x>
<y>125</y> <y>150</y>
<label>thin</label> <label>thin</label>
</text> </text>
<text>
<x>5</x>
<y>125</y>
<label>Air pollution:</label>
</text>
<text>
<x>160</x>
<y>125</y>
<label>clean</label>
</text>
<slider>
<x>230</x>
<y>125</y>
<width>90</width>
<height>20</height>
<min>0.0</min>
<max>1.0</max>
<property>/environment/air-pollution-norm</property>
<binding>
<command>dialog-apply</command>
</binding>
</slider>
<text>
<x>330</x>
<y>125</y>
<label>smog</label>
</text>
<text> <text>
<x>5</x> <x>5</x>
@ -527,7 +558,7 @@
<button> <button>
<x>45</x> <x>40</x>
<y>0</y> <y>0</y>
<legend>Clear / End</legend> <legend>Clear / End</legend>
<!--<default>true</default>--> <!--<default>true</default>-->
@ -539,7 +570,7 @@
</button> </button>
<button> <button>
<x>135</x> <x>125</x>
<y>0</y> <y>0</y>
<legend>Close</legend> <legend>Close</legend>
<!--<equal>true</equal>--> <!--<equal>true</equal>-->
@ -550,9 +581,9 @@
</button> </button>
<button> <button>
<x>200</x> <x>180</x>
<y>0</y> <y>0</y>
<legend>Show winds</legend> <legend>Winds</legend>
<!--<equal>true</equal>--> <!--<equal>true</equal>-->
<binding> <binding>
<command>dialog-show</command> <command>dialog-show</command>
@ -563,8 +594,22 @@
</binding> </binding>
</button> </button>
<button>
<x>235</x>
<y>0</y>
<legend>Advanced</legend>
<!--<equal>true</equal>-->
<binding>
<command>dialog-show</command>
<dialog-name>local_weather_environment</dialog-name>
</binding>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<button> <button>
<x>290</x> <x>330</x>
<y>0</y> <y>0</y>
<legend>Basic Weather --></legend> <legend>Basic Weather --></legend>
<default>false</default> <default>false</default>