1
0
Fork 0

Merge branch 'next' into proj-3d

This commit is contained in:
fly 2022-02-18 01:16:05 +01:00
commit 121755d651
96 changed files with 33667 additions and 26085 deletions

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,7 @@
<PropertyList>
<scenario>
<name>Carrier: R99 - Foch (LFTH)</name>
<description>This scenario spawns the Foch aircraft carrier (Clemenceau-class) in the Mediterranean off Toulon.</description>
<description>This scenario spawns the Foch aircraft carrier (Clemenceau-class) in the Mediterranean off Toulon (near LFTH).</description>
<entry>
<type>carrier</type>
<name>Foch</name>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 333 KiB

View file

@ -1,49 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<!--
Note:
To be able to see the glossy effect the shininess value for the color of the
affected model parts must be somewhere high, at least 100 and preferable 128:
https://learnopengl.com/Lighting/Materials
<name>Fuselagereflect</name>
<inherits-from>Effects/reflect</inherits-from>
Parameters:
* Boolean to enable or disable the reflection.
Civilian aircraft are usually glossy but military aircraft are not.
sim/model/civilian
* Floating point value to specify the reflection factor.
The range is between -1.0 and 0.0
sim/model/livery/shininess
* Floating point value to specify the Fresnel factor.
The range is between 0.0 and 1.0
sim/model/livery/fresnel
These parameters can all be defined within a livery configuration file:
<PropertyList>
<sim>
<model>
<civilian type="bool">true</civilian>
<livery>
<name type="string">Factory Demonstrator</name>
<texture>Liveries/factory.png</texture>
<shininess type="float">-0.5</shininess>
<fresnel type="float">0.7</fresnel>
</livery>
</model>
</sim>
</PropertyList>
Usage:
Add one of the following examples to your model configuration file.
* Minimal configuration
<effect>
<name>Effects/normalmap-reflection</name>
<inherits-from>Aircraft/Generic/Effects/Fuselagereflect</inherits-from>
<object-name>fuselage</object-name>
<object-name>wing</object-name>
</effect>
* Adding a normal-map:
<effect>
<name>Effects/normalmap-reflection</name>
<inherits-from>Aircraft/Generic/Effects/Fuselagereflect</inherits-from>
<object-name>fuselage</object-name>
<object-name>wing</object-name>
<parameters>
<texture n="2">
<image>Aircraft/AircraftName/Models/normalmap.png</image>
</texture>
</parameters>
</effect>
Further reading:
https://wiki.flightgear.org/ALS_technical_notes
-->
<PropertyList>
<name>Aircraft/Generic/Effects/Fuselagereflect</name>
<inherits-from>Effects/model-combined-deferred</inherits-from>
<parameters>
<rain-enabled type="int"> 2 </rain-enabled>
<normalmap-enabled type="int"> 1 </normalmap-enabled>
<normalmap-dds type="int"> 0 </normalmap-dds>
<normalmap-tiling type="float"> 1.0 </normalmap-tiling>
<lightmap-enabled type="int"> 0 </lightmap-enabled>
<ambient-correction type="float"> 0.1 </ambient-correction>
<reflection-enabled type="int"><use>sim/model/civilian</use></reflection-enabled>
<reflection-type type="int"> 1 </reflection-type>
<reflection-dynamic type="int"> 1 </reflection-dynamic>
<reflection-rainbow type="float"> 0.0 </reflection-rainbow>
<reflection-noise type="float"> 0.0 </reflection-noise>
<reflection-fresnel-factor type="float"> 1.0 </reflection-fresnel-factor>
<reflection-correction type="float"><use>sim/model/livery/shininess</use></reflection-correction>
<reflection-fresnel type="float"><use>sim/model/livery/fresnel</use></reflection-fresnel>
<texture n="2">
<image>Aircraft/Generic/Effects/null_bumpspec.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n= "5" >
<type>cubemap</type>
<images>
<positive-x>Aircraft/Generic/Effects/CubeMaps/real.blue-sky/fair-sky_px.png</positive-x>
<negative-x>Aircraft/Generic/Effects/CubeMaps/real.blue-sky/fair-sky_nx.png</negative-x>
<positive-y>Aircraft/Generic/Effects/CubeMaps/real.blue-sky/fair-sky_py.png</positive-y>
<negative-y>Aircraft/Generic/Effects/CubeMaps/real.blue-sky/fair-sky_ny.png</negative-y>
<positive-z>Aircraft/Generic/Effects/CubeMaps/real.blue-sky/fair-sky_pz.png</positive-z>
<negative-z>Aircraft/Generic/Effects/CubeMaps/real.blue-sky/fair-sky_nz.png</negative-z>
<positive-x>Aircraft/Generic/Effects/CubeMaps/buildings/N.png</positive-x>
<negative-x>Aircraft/Generic/Effects/CubeMaps/buildings/S.png</negative-x>
<positive-y>Aircraft/Generic/Effects/CubeMaps/buildings/W.png</positive-y>
<negative-y>Aircraft/Generic/Effects/CubeMaps/buildings/E.png</negative-y>
<positive-z>Aircraft/Generic/Effects/CubeMaps/buildings/U.png</positive-z>
<negative-z>Aircraft/Generic/Effects/CubeMaps/buildings/D.png</negative-z>
</images>
</texture>
<texture n="6">
<image>Aircraft/Generic/Effects/Rainbow.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
</texture>
<texture n="7">
<image>Aircraft/Generic/Effects/FresnelLookUp.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="8">
<image>Aircraft/Generic/Effects/greymap.png</image>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<rendering-hint>transparent</rendering-hint>
<shade-model>smooth</shade-model>
<rainbowiness type="double">0.1</rainbowiness>
<fresneliness type="double">0.1</fresneliness>
<noisiness type="double">0.1</noisiness>
<refl_correction type="double">-0.2</refl_correction>
<ambient_correction type="double">0.1</ambient_correction>
<reflect_map type="double">0</reflect_map>
</parameters>
<generate>
<tangent type="int">6</tangent>
<binormal type="int">7</binormal>
</generate>
<technique n="4">
<pass>
<program>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
</program>
</pass>
</technique>
<technique n="7">
<pass>
<program>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
</program>
</pass>
</technique>
<technique n="9">
<pass>
<program>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
</program>
</pass>
</technique>
</PropertyList>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 102 B

24
Aircraft/Generic/light.ac Normal file
View file

@ -0,0 +1,24 @@
AC3Db
MATERIAL "DefaultWhite" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0.5 0.5 0.5 shi 64 trans 0
MATERIAL "DefaultWhite.001" rgb 1 1 1 amb 0.2 0.2 0.2 emis 0 0 0 spec 0.025 0.025 0.025 shi 50 trans 0.1
OBJECT world
kids 1
OBJECT poly
name "light"
data 8
Mesh.001
crease 30.000000
numvert 4
-2e-06 -1 -1
0 1 -1
0 -1 1
2e-06 1 1
numsurf 1
SURF 0x20
mat 1
refs 4
1 0.0 0.0
0 0.0 0.0
2 0.0 0.0
3 0.0 0.0
kids 0

View file

@ -0,0 +1,153 @@
<?xml version="1.0"?>
<PropertyList>
<path>light.ac</path>
<nopreview/>
<params>
<power-source>/controls/lighting/nav-lights</power-source>
<name>pointlight</name>
<x-m>0</x-m>
<y-m>0</y-m>
<z-m>0</z-m>
<direction>
<x/>
<y/>
<z/>
</direction>
<ambient>
<r>0.5</r>
<g>0.5</g>
<b>0.4</b>
</ambient>
<specular>
<r>1.0</r>
<g>1.0</g>
<b>1.0</b>
</specular>
<attenuation>
<c>1.0</c>
<l>0.7</l>
<q>1.1</q>
</attenuation>
<inner-angle>0.75</inner-angle>
<outer-angle>0.85</outer-angle>
<zero-angle>0.9</zero-angle>
<outer-gain>0.1</outer-gain>
<dist-scale>1.5</dist-scale>
<range-m>50</range-m>
</params>
<animation>
<type>scale</type>
<x-offset>0.175</x-offset>
<y-offset>0.175</y-offset>
<z-offset>0.175</z-offset>
</animation>
<animation>
<type>dist-scale</type>
<object-name>light</object-name>
<interpolation>
<entry>
<ind>0</ind>
<dep alias="/params/dist-scale"/>
</entry>
<entry>
<ind>300</ind>
<dep>4</dep>
</entry>
<entry>
<ind>1500</ind>
<dep>8</dep>
</entry>
</interpolation>
</animation>
<animation>
<type>noshadow</type>
<object-name>light</object-name>
</animation>
<animation>
<type>select</type>
<object-name>light</object-name>
<condition>
<property alias="/params/power-source"/>
</condition>
</animation>
<effect>
<name>Effects/pointlight</name>
<object-name>light</object-name>
<inherits-from>Effects/procedural-light</inherits-from>
<parameters>
<texture n="0">
<type>white</type>
</texture>
<light_color_base_r alias="/params/ambient/r"/>
<light_color_base_g alias="/params/ambient/g"/>
<light_color_base_b alias="/params/ambient/b"/>
<light_color_center_r alias="/params/specular/r"/>
<light_color_center_g alias="/params/specular/g"/>
<light_color_center_b alias="/params/specular/b"/>
<intensity_scale>1.0</intensity_scale>
<pointing_x alias="/params/direction/x"/>
<pointing_y alias="/params/direction/y"/>
<pointing_z alias="/params/direction/z"/>
<is_directional type="bool">false</is_directional>
<is_strobe type="bool">false</is_strobe>
<inner_angle alias="/params/inner-angle"/>
<outer_angle alias="/params/outer-angle"/>
<zero_angle alias="/params/zero-angle"/>
<outer_gain alias="/params/outer-gain"/>
<visibility><use>/environment/ground-visibility-m</use></visibility>
<avisibility><use>/environment/visibility-m</use></avisibility>
<lthickness><use>/environment/ground-haze-thickness-m</use></lthickness>
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<terminator><use>/environment/terminator-relative-position-m</use></terminator>
</parameters>
</effect>
<light>
<name alias="/params/name"/>
<type>point</type>
<position>
<x alias="/params/x-m"/>
<y alias="/params/y-m"/>
<z alias="/params/z-m"/>
</position>
<direction>
<pointing_x alias="/params/direction/x"/>
<pointing_y alias="/params/direction/y"/>
<pointing_z alias="/params/direction/z"/>
</direction>
<ambient>
<r alias="/params/ambient/r"/>
<g alias="/params/ambient/g"/>
<b alias="/params/ambient/b"/>
<a>1.0</a>
</ambient>
<diffuse>
<r alias="/params/specular/r"/>
<g alias="/params/specular/g"/>
<b alias="/params/specular/b"/>
<a>1.0</a>
</diffuse>
<specular>
<r alias="/params/specular/r"/>
<g alias="/params/specular/g"/>
<b alias="/params/specular/b"/>
<a>1.0</a>
</specular>
<attenuation>
<c alias="/params/attenuation/c"/>
<l alias="/params/attenuation/l"/>
<q alias="/params/attenuation/q"/>
</attenuation>
<range-m alias="/params/range-m"/>
<dim-factor><property alias="/params/power-source"/></dim-factor>
</light>
</PropertyList>

View file

@ -0,0 +1,157 @@
<?xml version="1.0"?>
<PropertyList>
<path>light.ac</path>
<nopreview/>
<params>
<power-source>/controls/lighting/nav-lights</power-source>
<name>spotlight</name>
<x-m>0</x-m>
<y-m>0</y-m>
<z-m>0</z-m>
<direction>
<x/>
<y/>
<z/>
</direction>
<ambient>
<r>0.5</r>
<g>0.5</g>
<b>0.4</b>
</ambient>
<specular>
<r>1.0</r>
<g>1.0</g>
<b>1.0</b>
</specular>
<attenuation>
<c>1.0</c>
<l>0.7</l>
<q>1.1</q>
</attenuation>
<inner-angle>0.75</inner-angle>
<outer-angle>0.85</outer-angle>
<zero-angle>0.9</zero-angle>
<outer-gain>0.1</outer-gain>
<spot-cutoff>80</spot-cutoff>
<spot-exponent>0.5</spot-exponent>
<dist-scale>1.5</dist-scale>
<range-m>50</range-m>
</params>
<animation>
<type>scale</type>
<x-offset>0.175</x-offset>
<y-offset>0.175</y-offset>
<z-offset>0.175</z-offset>
</animation>
<animation>
<type>dist-scale</type>
<object-name>light</object-name>
<interpolation>
<entry>
<ind>0</ind>
<dep alias="/params/dist-scale"/>
</entry>
<entry>
<ind>300</ind>
<dep>4</dep>
</entry>
<entry>
<ind>1500</ind>
<dep>8</dep>
</entry>
</interpolation>
</animation>
<animation>
<type>noshadow</type>
<object-name>light</object-name>
</animation>
<animation>
<type>select</type>
<object-name>light</object-name>
<condition>
<property alias="/params/power-source"/>
</condition>
</animation>
<effect>
<name>Effects/spotlight</name>
<object-name>light</object-name>
<inherits-from>Effects/procedural-light</inherits-from>
<parameters>
<texture n="0">
<type>white</type>
</texture>
<light_color_base_r alias="/params/ambient/r"/>
<light_color_base_g alias="/params/ambient/g"/>
<light_color_base_b alias="/params/ambient/b"/>
<light_color_center_r alias="/params/specular/r"/>
<light_color_center_g alias="/params/specular/g"/>
<light_color_center_b alias="/params/specular/b"/>
<intensity_scale>1.0</intensity_scale>
<pointing_x alias="/params/direction/x"/>
<pointing_y alias="/params/direction/y"/>
<pointing_z alias="/params/direction/z"/>
<is_directional type="bool">true</is_directional>
<is_strobe type="bool">false</is_strobe>
<inner_angle alias="/params/inner-angle"/>
<outer_angle alias="/params/outer-angle"/>
<zero_angle alias="/params/zero-angle"/>
<outer_gain alias="/params/outer-gain"/>
<visibility><use>/environment/ground-visibility-m</use></visibility>
<avisibility><use>/environment/visibility-m</use></avisibility>
<lthickness><use>/environment/ground-haze-thickness-m</use></lthickness>
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<terminator><use>/environment/terminator-relative-position-m</use></terminator>
</parameters>
</effect>
<light>
<name alias="/params/name"/>
<type>spot</type>
<position>
<x alias="/params/x-m"/>
<y alias="/params/y-m"/>
<z alias="/params/z-m"/>
</position>
<direction>
<pointing_x alias="/params/direction/x"/>
<pointing_y alias="/params/direction/y"/>
<pointing_z alias="/params/direction/z"/>
</direction>
<ambient>
<r alias="/params/ambient/r"/>
<g alias="/params/ambient/g"/>
<b alias="/params/ambient/b"/>
<a>1.0</a>
</ambient>
<diffuse>
<r alias="/params/specular/r"/>
<g alias="/params/specular/g"/>
<b alias="/params/specular/b"/>
<a>1.0</a>
</diffuse>
<specular>
<r alias="/params/specular/r"/>
<g alias="/params/specular/g"/>
<b alias="/params/specular/b"/>
<a>1.0</a>
</specular>
<attenuation>
<c alias="/params/attenuation/c"/>
<l alias="/params/attenuation/l"/>
<q alias="/params/attenuation/q"/>
</attenuation>
<spot-cutoff alias="/params/spot-cutoff"/>
<spot-exponent alias="/params/spot-exponent"/>
<range-m alias="/params/range-m"/>
<dim-factor><property alias="/params/power-source"/></dim-factor>
</light>
</PropertyList>

View file

@ -172,7 +172,8 @@
<button>
<legend>ATC Services in range</legend>
<binding>
<command>ATC-freq-search</command>
<command>dialog-show</command>
<dialog-name>atc-freq-search</dialog-name>
</binding>
</button>
</group>

View file

@ -172,7 +172,8 @@
<button>
<legend>ATC Services in range</legend>
<binding>
<command>ATC-freq-search</command>
<command>dialog-show</command>
<dialog-name>atc-freq-search</dialog-name>
</binding>
</button>
</group>

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 KiB

After

Width:  |  Height:  |  Size: 518 KiB

168
Effects/galaxy.eff Normal file
View file

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/galaxy</name>
<parameters>
<display_xsize><use>/sim/startup/xsize</use></display_xsize>
<display_ysize><use>/sim/startup/ysize</use></display_ysize>
<use_filtering><use>/sim/rendering/als-filters/use-filtering</use></use_filtering>
<gamma><use>/sim/rendering/als-filters/gamma</use></gamma>
<brightness><use>/sim/rendering/als-filters/brightness</use></brightness>
<use_night_vision><use>/sim/rendering/als-filters/use-night-vision</use></use_night_vision>
<use_IR_vision><use>/sim/rendering/als-filters/use-IR-vision</use></use_IR_vision>
<!--use_CCTV_vision><use>/sim/rendering/als-filters/use-CCTV-vision</use></use_CCTV_vision-->
<fact_grey><use>/sim/rendering/als-filters/grey-factor</use></fact_grey>
<fact_black><use>/sim/rendering/als-filters/black-factor</use></fact_black>
<delta_T>-50.0</delta_T>
<moonlight><use>/environment/moonlight</use></moonlight>
<darksky_magnitude><use>/environment/darksky-brightness-magnitude</use></darksky_magnitude>
<galaxy_magnitude><use>/environment/galaxy-bulge-brightness-magnitude</use></galaxy_magnitude>
<atmosphere_top><use>/environment/atmosphere/altitude-troposphere-top</use></atmosphere_top>
<eye_altitude_m><use>/sim/rendering/eye-altitude-m</use></eye_altitude_m>
</parameters>
<technique n="10">
<predicate>
<and>
<property>/sim/rendering/shader-effects</property>
<less-equal>
<value type="float">3.0</value>
<float-property>/sim/rendering/shaders/quality-level</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>
<program>
<vertex-shader>Shaders/galaxy.vert</vertex-shader>
<vertex-shader>Shaders/filters-ALS.vert</vertex-shader>
<fragment-shader>Shaders/galaxy.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/filters-ALS.frag</fragment-shader>
</program>
<uniform>
<name>milkyway</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>gamma</name>
<type>float</type>
<value><use>gamma</use></value>
</uniform>
<uniform>
<name>brightness</name>
<type>float</type>
<value><use>brightness</use></value>
</uniform>
<uniform>
<name>use_filtering</name>
<type>bool</type>
<value><use>use_filtering</use></value>
</uniform>
<uniform>
<name>use_night_vision</name>
<type>bool</type>
<value><use>use_night_vision</use></value>
</uniform>
<uniform>
<name>delta_T</name>
<type>float</type>
<value><use>delta_T</use></value>
</uniform>
<uniform>
<name>fact_grey</name>
<type>float</type>
<value><use>fact_grey</use></value>
</uniform>
<uniform>
<name>fact_black</name>
<type>float</type>
<value><use>fact_black</use></value>
</uniform>
<uniform>
<name>use_IR_vision</name>
<type>bool</type>
<value><use>use_IR_vision</use></value>
</uniform>
<!--
<uniform>
<name>use_CCTV_vision</name>
<type>bool</type>
<value><use>use_CCTV_vision</use></value>
</uniform>
-->
<uniform>
<name>field_of_view</name>
<type>float</type>
<value><use>view_fov</use></value>
</uniform>
<uniform>
<name>display_xsize</name>
<type>int</type>
<value><use>display_xsize</use></value>
</uniform>
<uniform>
<name>display_ysize</name>
<type>int</type>
<value><use>display_ysize</use></value>
</uniform>
<uniform>
<name>moonlight</name>
<type>float</type>
<value><use>moonlight</use></value>
</uniform>
<uniform>
<name>mudarksky</name>
<type>float</type>
<value><use>darksky_magnitude</use></value>
</uniform>
<uniform>
<name>mugxybulge</name>
<type>float</type>
<value><use>galaxy_magnitude</use></value>
</uniform>
<uniform>
<name>altitude</name>
<type>float</type>
<value><use>eye_altitude_m</use></value>
</uniform>
<uniform>
<name>atmosphere_top</name>
<type>float</type>
<value><use>atmosphere_top</use></value>
</uniform>
</pass>
</technique>
<!-- minimal technique -->
<technique n="11">
</technique>
<technique n="109">
<scheme>hdr-geometry</scheme>
</technique>
</PropertyList>

32
Effects/marker-pin.eff Normal file
View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/marker-pin</name>
<parameters>
</parameters>
<technique>
<predicate>
<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>
</predicate>
<pass>
<cull-face>back</cull-face>
<!-- <rendering-hint>transparent</rendering-hint> -->
<program>
<vertex-shader>Shaders/marker-pin.vert</vertex-shader>
<fragment-shader>Shaders/marker-pin.frag</fragment-shader>
</program>
</pass>
</technique>
</PropertyList>

View file

@ -5,5 +5,5 @@ It's kept for backwards compatibility and should not be used on new projects.
-->
<PropertyList>
<name>Effects/model-combined-transparent</name>
<inherits-from>Effects/model-transparent</inherits-from>
<inherits-from>Effects/model-combined</inherits-from>
</PropertyList>

967
Effects/ws30-overlay.eff Normal file
View file

@ -0,0 +1,967 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<!--
WS30 terrain overlay effect. There are 2 passes over the terrain.
The 1st pass is a normal ALS ultra shaders pass from ws30.eff.
This pass should be kept up to date with ws30.eff.
The 2nd pass uses geometry shaders to add smaller scale volumetric detail with
simplified lighting. The fragment shader used for the 2nd pass is the same as WS2 currently.
-->
<name>Effects/ws30-overlay</name>
<inherits-from>Effects/ws30</inherits-from>
<parameters>
<texture n="20">
<!-- <image>Textures/Terrain/void.png</image> temp. -->
<image>Textures/Terrain/mixedforest-hires.png</image> <!-- testing -->
<type>2d</type>
<filter>nearest-mipmap-nearest</filter>
<mag-filter>nearest</mag-filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="21">
<!-- <image>Textures/Terrain/void.png</image> temp. -->
<image>Textures/Terrain/grass_hires.png</image> <!-- testing -->
<type>2d</type>
<filter>nearest-mipmap-nearest</filter>
<mag-filter>nearest</mag-filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<max_overlay_height>1.5</max_overlay_height>
<overlay_scale>1.0</overlay_scale>
<overlay_brightness_top>1.0</overlay_brightness_top>
<overlay_brightness_bottom>0.5</overlay_brightness_bottom>
<overlay_hardness>0.5</overlay_hardness>
<overlay_secondary_hardness>0.5</overlay_secondary_hardness>
<overlay_density>0.5</overlay_density>
<overlay_steepness_factor>0.8</overlay_steepness_factor>
<overlay_secondary_density>0.5</overlay_secondary_density> <!-- Testing: should be 0.0 -->
<overlay_autumn_flag>0</overlay_autumn_flag>
<overlay_secondary_flag>1</overlay_secondary_flag> <!-- Testing: was 0 -->
</parameters>
<technique n="4">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<and>
<less-equal>
<value type="float">6.0</value>
<float-property>/sim/rendering/shaders/landmass</float-property>
</less-equal>
<less-equal>
<value type="float">6.0</value>
<float-property>/sim/rendering/shaders/transition</float-property>
</less-equal>
<less-equal>
<value type="float">1.0</value>
<float-property>/sim/rendering/shaders/vegetation-effects</float-property>
</less-equal>
</and>
<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>
<extension-supported>GL_EXT_geometry_shader4</extension-supported>
</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>
<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 0 direct from VPBBuilder.cxx -->
<texture-unit>
<unit>1</unit>
<image><use>texture[1]/image</use></image>
<filter>nearest-mipmap-nearest</filter>
<mag-filter>nearest-mipmap-nearest</mag-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>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>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/ws30-ALS-ultra.vert</vertex-shader>
<vertex-shader>Shaders/filters-ALS.vert</vertex-shader>
<vertex-shader>Shaders/shadows-include.vert</vertex-shader>
<fragment-shader>Shaders/ws30-ALS-ultra.frag</fragment-shader>
<fragment-shader>Shaders/ws30-ALS-landclass-search-functions.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
<fragment-shader>Shaders/secondary_lights.frag</fragment-shader>
<fragment-shader>Shaders/filters-ALS.frag</fragment-shader>
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
</program>
<uniform>
<name>quality_level</name>
<type>int</type>
<value><use>quality_level</use></value>
</uniform>
<uniform>
<name>grain_strength</name>
<type>float</type>
<value><use>grain_strength</use></value>
</uniform>
<uniform>
<name>intrinsic_wetness</name>
<type>float</type>
<value><use>intrinsic_wetness</use></value>
</uniform>
<uniform>
<name>transition_model</name>
<type>float</type>
<value><use>transition_model</use></value>
</uniform>
<uniform>
<name>hires_overlay_bias</name>
<type>float</type>
<value><use>hires_overlay_bias</use></value>
</uniform>
<uniform>
<name>dot_density</name>
<type>float</type>
<value><use>dot_density</use></value>
</uniform>
<uniform>
<name>dot_size</name>
<type>float</type>
<value><use>dot_size</use></value>
</uniform>
<uniform>
<name>dust_resistance</name>
<type>float</type>
<value><use>dust_resistance</use></value>
</uniform>
<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>eye_lat</name>
<type>float</type>
<value><use>eye_lat</use></value>
</uniform>
<uniform>
<name>eye_lon</name>
<type>float</type>
<value><use>eye_lon</use></value>
</uniform>
<uniform>
<name>snowlevel</name>
<type>float</type>
<value><use>snow_level</use></value>
</uniform>
<uniform>
<name>snow_thickness_factor</name>
<type>float</type>
<value><use>snow_thickness_factor</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value><use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>lichen_cover_factor</name>
<type>float</type>
<value> <use>lichen_cover_factor</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>
<value><use>wetness</use></value>
</uniform>
<uniform>
<name>fogstructure</name>
<type>float</type>
<value><use>fogstructure</use></value>
</uniform>
<uniform>
<name>cloud_self_shading</name>
<type>float</type>
<value><use>cloud_self_shading</use></value>
</uniform>
<uniform>
<name>moonlight</name>
<type>float</type>
<value><use>moonlight</use></value>
</uniform>
<uniform>
<name>season</name>
<type>float</type>
<value><use>season</use></value>
</uniform>
<uniform>
<name>air_pollution</name>
<type>float</type>
<value><use>air_pollution</use></value>
</uniform>
<!-- secondary lights -->
<uniform>
<name>view_pitch_offset</name>
<type>float</type>
<value><use>view_pitch_offset</use></value>
</uniform>
<uniform>
<name>view_heading_offset</name>
<type>float</type>
<value><use>view_heading_offset</use></value>
</uniform>
<uniform>
<name>field_of_view</name>
<type>float</type>
<value><use>view_fov</use></value>
</uniform>
<uniform>
<name>landing_light1_offset</name>
<type>float</type>
<value><use>landing_light1_offset</use></value>
</uniform>
<uniform>
<name>landing_light2_offset</name>
<type>float</type>
<value><use>landing_light2_offset</use></value>
</uniform>
<uniform>
<name>landing_light3_offset</name>
<type>float</type>
<value><use>landing_light3_offset</use></value>
</uniform>
<!-- filtering -->
<uniform>
<name>gamma</name>
<type>float</type>
<value><use>gamma</use></value>
</uniform>
<uniform>
<name>brightness</name>
<type>float</type>
<value><use>brightness</use></value>
</uniform>
<uniform>
<name>use_night_vision</name>
<type>bool</type>
<value><use>use_night_vision</use></value>
</uniform>
<uniform>
<name>use_IR_vision</name>
<type>bool</type>
<value><use>use_IR_vision</use></value>
</uniform>
<uniform>
<name>use_filtering</name>
<type>bool</type>
<value><use>use_filtering</use></value>
</uniform>
<uniform>
<name>delta_T</name>
<type>float</type>
<value><use>delta_T</use></value>
</uniform>
<uniform>
<name>fact_grey</name>
<type>float</type>
<value><use>fact_grey</use></value>
</uniform>
<uniform>
<name>fact_black</name>
<type>float</type>
<value><use>fact_black</use></value>
</uniform>
<!-- cloud shadows -->
<uniform>
<name>cloudpos1_x</name>
<type>float</type>
<value><use>cloudpos1_x</use></value>
</uniform>
<uniform>
<name>cloudpos1_y</name>
<type>float</type>
<value><use>cloudpos1_y</use></value>
</uniform>
<uniform>
<name>cloudpos2_x</name>
<type>float</type>
<value><use>cloudpos2_x</use></value>
</uniform>
<uniform>
<name>cloudpos2_y</name>
<type>float</type>
<value><use>cloudpos2_y</use></value>
</uniform>
<uniform>
<name>cloudpos3_x</name>
<type>float</type>
<value><use>cloudpos3_x</use></value>
</uniform>
<uniform>
<name>cloudpos3_y</name>
<type>float</type>
<value><use>cloudpos3_y</use></value>
</uniform>
<uniform>
<name>cloudpos4_x</name>
<type>float</type>
<value><use>cloudpos4_x</use></value>
</uniform>
<uniform>
<name>cloudpos4_y</name>
<type>float</type>
<value><use>cloudpos4_y</use></value>
</uniform>
<uniform>
<name>cloudpos5_x</name>
<type>float</type>
<value><use>cloudpos5_x</use></value>
</uniform>
<uniform>
<name>cloudpos5_y</name>
<type>float</type>
<value><use>cloudpos5_y</use></value>
</uniform>
<uniform>
<name>cloudpos6_x</name>
<type>float</type>
<value><use>cloudpos6_x</use></value>
</uniform>
<uniform>
<name>cloudpos6_y</name>
<type>float</type>
<value><use>cloudpos6_y</use></value>
</uniform>
<uniform>
<name>cloudpos7_x</name>
<type>float</type>
<value><use>cloudpos7_x</use></value>
</uniform>
<uniform>
<name>cloudpos7_y</name>
<type>float</type>
<value><use>cloudpos7_y</use></value>
</uniform>
<uniform>
<name>cloudpos8_x</name>
<type>float</type>
<value><use>cloudpos8_x</use></value>
</uniform>
<uniform>
<name>cloudpos8_y</name>
<type>float</type>
<value><use>cloudpos8_y</use></value>
</uniform>
<uniform>
<name>cloudpos9_x</name>
<type>float</type>
<value><use>cloudpos9_x</use></value>
</uniform>
<uniform>
<name>cloudpos9_y</name>
<type>float</type>
<value><use>cloudpos9_y</use></value>
</uniform>
<uniform>
<name>cloudpos10_x</name>
<type>float</type>
<value><use>cloudpos10_x</use></value>
</uniform>
<uniform>
<name>cloudpos10_y</name>
<type>float</type>
<value><use>cloudpos10_y</use></value>
</uniform>
<uniform>
<name>cloudpos11_x</name>
<type>float</type>
<value><use>cloudpos11_x</use></value>
</uniform>
<uniform>
<name>cloudpos11_y</name>
<type>float</type>
<value><use>cloudpos11_y</use></value>
</uniform>
<uniform>
<name>cloudpos12_x</name>
<type>float</type>
<value><use>cloudpos12_x</use></value>
</uniform>
<uniform>
<name>cloudpos12_y</name>
<type>float</type>
<value><use>cloudpos12_y</use></value>
</uniform>
<uniform>
<name>cloudpos13_x</name>
<type>float</type>
<value><use>cloudpos13_x</use></value>
</uniform>
<uniform>
<name>cloudpos13_y</name>
<type>float</type>
<value><use>cloudpos13_y</use></value>
</uniform>
<uniform>
<name>cloudpos14_x</name>
<type>float</type>
<value><use>cloudpos14_x</use></value>
</uniform>
<uniform>
<name>cloudpos14_y</name>
<type>float</type>
<value><use>cloudpos14_y</use></value>
</uniform>
<uniform>
<name>cloudpos15_x</name>
<type>float</type>
<value><use>cloudpos15_x</use></value>
</uniform>
<uniform>
<name>cloudpos15_y</name>
<type>float</type>
<value><use>cloudpos15_y</use></value>
</uniform>
<uniform>
<name>cloudpos16_x</name>
<type>float</type>
<value><use>cloudpos16_x</use></value>
</uniform>
<uniform>
<name>cloudpos16_y</name>
<type>float</type>
<value><use>cloudpos16_y</use></value>
</uniform>
<uniform>
<name>cloudpos17_x</name>
<type>float</type>
<value><use>cloudpos17_x</use></value>
</uniform>
<uniform>
<name>cloudpos17_y</name>
<type>float</type>
<value><use>cloudpos17_y</use></value>
</uniform>
<uniform>
<name>cloudpos18_x</name>
<type>float</type>
<value><use>cloudpos18_x</use></value>
</uniform>
<uniform>
<name>cloudpos18_y</name>
<type>float</type>
<value><use>cloudpos18_y</use></value>
</uniform>
<uniform>
<name>cloudpos19_x</name>
<type>float</type>
<value><use>cloudpos19_x</use></value>
</uniform>
<uniform>
<name>cloudpos19_y</name>
<type>float</type>
<value><use>cloudpos19_y</use></value>
</uniform>
<uniform>
<name>cloudpos20_x</name>
<type>float</type>
<value><use>cloudpos20_x</use></value>
</uniform>
<uniform>
<name>cloudpos20_y</name>
<type>float</type>
<value><use>cloudpos20_y</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>
<name>use_searchlight</name>
<type>int</type>
<value> <use>use_searchlight</use></value>
</uniform>
<uniform>
<name>use_landing_light</name>
<type>int</type>
<value> <use>use_landing_light</use></value>
</uniform>
<uniform>
<name>use_alt_landing_light</name>
<type>int</type>
<value> <use>use_alt_landing_light</use></value>
</uniform>
<uniform>
<name>display_xsize</name>
<type>int</type>
<value><use>display_xsize</use></value>
</uniform>
<uniform>
<name>display_ysize</name>
<type>int</type>
<value><use>display_ysize</use></value>
</uniform>
<uniform>
<name>wind_effects</name>
<type>int</type>
<value><use>wind_effects</use></value>
</uniform>
<uniform>
<name>cloud_shadow_flag</name>
<type>int</type>
<value><use>cloud_shadow_flag</use></value>
</uniform>
<uniform>
<name>rock_strata</name>
<type>int</type>
<value><use>rock_strata</use></value>
</uniform>
<uniform>
<name>raise_vertex</name>
<type>bool</type>
<value> <use>raise_vertex</use></value>
</uniform>
<uniform>
<name>landclass</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>textureArray</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>perlin</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>swatch_size</name>
<type>int</type>
<!--
Testing: hardcoded placeholder to allow noise to be calculated while looking up textures
<value><use>xsize</use></value>
-->
<value>2000</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value>
<!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<!-- BEGIN shadows include -->
<uniform>
<name>shadow_tex</name>
<type>sampler-2d</type>
<value type="int">10</value>
</uniform>
<uniform>
<name>shadows_enabled</name>
<type>bool</type>
<value>
<use>shadows_enabled</use>
</value>
</uniform>
<uniform>
<name>sun_atlas_size</name>
<type>int</type>
<value>
<use>sun_atlas_size</use>
</value>
</uniform>
<!-- END shadows include -->
</pass>
<pass n="2">
<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>
<!--<alpha-to-coverage>true</alpha-to-coverage>-->
<cull-face>back</cull-face>
<!--<render-bin>
<bin-number>111</bin-number>
<bin-name>DepthSortedBin</bin-name>
</render-bin>-->
<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>7</unit>
<type><use>texture[20]/type</use></type>
<image><use>texture[20]/image</use></image>
<filter><use>texture[20]/filter</use></filter>
<mag-filter><use>texture[20]/mag-filter</use></mag-filter>
<wrap-s><use>texture[20]/wrap-s</use></wrap-s>
<wrap-t><use>texture[20]/wrap-t</use></wrap-t>
<internal-format><use>texture[20]/internal-format</use></internal-format>
</texture-unit>
<texture-unit>
<unit>8</unit>
<type><use>texture[21]/type</use></type>
<image><use>texture[21]/image</use></image>
<filter><use>texture[21]/filter</use></filter>
<mag-filter><use>texture[21]/mag-filter</use></mag-filter>
<wrap-s><use>texture[21]/wrap-s</use></wrap-s>
<wrap-t><use>texture[21]/wrap-t</use></wrap-t>
<internal-format><use>texture[21]/internal-format</use></internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/ws30-overlay-ALS.vert</vertex-shader>
<geometry-shader>Shaders/ws30-overlay-ALS.geom</geometry-shader>
<fragment-shader>Shaders/terrain-overlay-ALS.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/filters-ALS.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
<geometry-vertices-out type="int">96</geometry-vertices-out>
<geometry-input-type>triangles</geometry-input-type>
<geometry-output-type>triangle-strip</geometry-output-type>
</program>
<uniform>
<name>overlayPrimaryTex</name>
<type>sampler-2d</type>
<value type="int">7</value>
</uniform>
<uniform>
<name>overlaySecondaryTex</name>
<type>sampler-2d</type>
<value type="int">8</value>
</uniform>
<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>scattering</name>
<type>float</type>
<value><use>scattering</use></value>
</uniform>
<uniform>
<name>overlay_bias</name>
<type>float</type>
<value><use>overlay_bias</use></value>
</uniform>
<uniform>
<name>overlay_max_height</name>
<type>float</type>
<value><use>max_overlay_height</use></value>
</uniform>
<uniform>
<name>overlay_hardness</name>
<type>float</type>
<value><use>overlay_hardness</use></value>
</uniform>
<uniform>
<name>overlay_secondary_hardness</name>
<type>float</type>
<value><use>overlay_secondary_hardness</use></value>
</uniform>
<uniform>
<name>overlay_density</name>
<type>float</type>
<value><use>overlay_density</use></value>
</uniform>
<uniform>
<name>overlay_secondary_density</name>
<type>float</type>
<value><use>overlay_secondary_density</use></value>
</uniform>
<uniform>
<name>overlay_scale</name>
<type>float</type>
<value><use>overlay_scale</use></value>
</uniform>
<uniform>
<name>overlay_brightness_top</name>
<type>float</type>
<value><use>overlay_brightness_top</use></value>
</uniform>
<uniform>
<name>overlay_brightness_bottom</name>
<type>float</type>
<value><use>overlay_brightness_bottom</use></value>
</uniform>
<uniform>
<name>overlay_steepness_factor</name>
<type>float</type>
<value><use>overlay_steepness_factor</use></value>
</uniform>
<uniform>
<name>season</name>
<type>float</type>
<value><use>season</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value><use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>
<value><use>wetness</use></value>
</uniform>
<uniform>
<name>snowlevel</name>
<type>float</type>
<value><use>snow_level</use></value>
</uniform>
<uniform>
<name>snow_thickness_factor</name>
<type>float</type>
<value><use>snow_thickness_factor</use></value>
</uniform>
<!-- cloud shadows -->
<uniform>
<name>cloudpos_n_x</name>
<type>float</type>
<value><use>cloudpos_n_x</use></value>
</uniform>
<uniform>
<name>cloudpos_n_y</name>
<type>float</type>
<value><use>cloudpos_n_y</use></value>
</uniform>
<!-- filtering -->
<uniform>
<name>gamma</name>
<type>float</type>
<value><use>gamma</use></value>
</uniform>
<uniform>
<name>brightness</name>
<type>float</type>
<value><use>brightness</use></value>
</uniform>
<uniform>
<name>use_night_vision</name>
<type>bool</type>
<value><use>use_night_vision</use></value>
</uniform>
<uniform>
<name>use_IR_vision</name>
<type>bool</type>
<value><use>use_IR_vision</use></value>
</uniform>
<uniform>
<name>use_filtering</name>
<type>bool</type>
<value><use>use_filtering</use></value>
</uniform>
<uniform>
<name>delta_T</name>
<type>float</type>
<value><use>delta_T</use></value>
</uniform>
<uniform>
<name>fact_grey</name>
<type>float</type>
<value><use>fact_grey</use></value>
</uniform>
<uniform>
<name>fact_black</name>
<type>float</type>
<value><use>fact_black</use></value>
</uniform>
<uniform>
<name>display_xsize</name>
<type>int</type>
<value><use>display_xsize</use></value>
</uniform>
<uniform>
<name>display_ysize</name>
<type>int</type>
<value><use>display_ysize</use></value>
</uniform>
<uniform>
<name>overlay_autumn_flag</name>
<type>int</type>
<value><use>overlay_autumn_flag</use></value>
</uniform>
<uniform>
<name>overlay_secondary_flag</name>
<type>int</type>
<value><use>overlay_secondary_flag</use></value>
</uniform>
<uniform>
<name>cloud_shadow_flag</name>
<type>int</type>
<value><use>cloud_shadow_flag</use></value>
</uniform>
<!-- BEGIN shadows include -->
<uniform>
<name>shadow_tex</name>
<type>sampler-2d</type>
<value type="int">10</value>
</uniform>
<uniform>
<name>shadows_enabled</name>
<type>bool</type>
<value>
<use>shadows_enabled</use>
</value>
</uniform>
<uniform>
<name>sun_atlas_size</name>
<type>int</type>
<value>
<use>sun_atlas_size</use>
</value>
</uniform>
<!-- END shadows include -->
<blend>
<active>true</active>
<source>src-alpha</source>
<destination>one-minus-src-alpha</destination>
</blend>
<depth>
<write-mask>false</write-mask>
</depth>
</pass>
</technique>
</PropertyList>

20
Effects/ws30-railway.eff Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/ws30-railway</name>
<inherits-from>Effects/terrain-default</inherits-from>
<parameters>
<speed-factor>0.8</speed-factor>
<base-density>0.25</base-density>
</parameters>
<technique n="3">
<!-- Disable the ultra technique as it doesn't work in WS30-->
<predicate n="0">
<and>
<equal>
<value type="float">2.0</value>
<value type="float">1.0</value>
</equal>
</and>
</predicate>
</technique>
</PropertyList>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/ws30-road-high</name>
<inherits-from>Effects/ws30-road</inherits-from>
<parameters>
<speed-factor>1.2</speed-factor>
<base-density>3.0</base-density>
</parameters>
</PropertyList>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/ws30-road-mid</name>
<inherits-from>Effects/ws30-road</inherits-from>
<parameters>
<speed-factor>0.8</speed-factor>
<base-density>0.25</base-density>
</parameters>
</PropertyList>

813
Effects/ws30-road.eff Normal file
View file

@ -0,0 +1,813 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/ws30-road</name>
<inherits-from>Effects/terrain-default</inherits-from>
<parameters>
<material>
<ambient type="vec4d">
0.2 .2 0.2 1.0
</ambient>
<diffuse type="vec4d">
.8 .8 .8 1.0
</diffuse>
<specular type="vec4d">
0.0 0.0 0.0 1.0
</specular>
<emissive type="vec4d">
0.0 0.0 0.0 1.0
</emissive>
<shininess>1.2</shininess>
<color-mode>diffuse</color-mode>
</material>
<texture n="2">
<image>Textures/osm2city/roads_LM.png</image>
<type>2d</type>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="8">
<image>Textures/Cars/cars.png</image>
<type>2d</type>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<texture n="9">
<image>Textures/Cars/cars-metadata.png</image>
<type>2d</type>
<filter>linear-mipmap-linear</filter>
<wrap-s>repeat</wrap-s>
<wrap-t>repeat</wrap-t>
<internal-format>normalized</internal-format>
</texture>
<grain-texture-enabled type="int">0</grain-texture-enabled>
<grain-magnification type="float">50</grain-magnification>
<lightmap-enabled type="int">1</lightmap-enabled>
<normalmap-enabled>0</normalmap-enabled>
<lightmap-color type="vec3d" n="0"> 0.941 0.682 0.086 </lightmap-color>
<snow_level><use>/environment/snow-level-m</use></snow_level>
<snow_thickness_factor><use>/environment/surface/snow-thickness-factor</use></snow_thickness_factor>
<road-traffic-enabled><use>/sim/rendering/osm/road-traffic-enabled</use></road-traffic-enabled>
<road-traffic-density><use>/sim/rendering/osm/road-traffic-density</use></road-traffic-density>
<road-traffic-direction><use>/sim/rendering/osm/road-traffic-direction</use></road-traffic-direction>
<road-traffic-variation><use>/sim/rendering/osm/road-traffic-daily-variation</use></road-traffic-variation>
<road-light-factor><use>/environment/lightmap-factor</use></road-light-factor>
</parameters>
<generate>
<tangent type="int">6</tangent>
<binormal type="int">7</binormal>
</generate>
<technique n="3">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<property>/sim/rendering/shaders/model</property>
<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>
<active>
<use>material/active</use>
</active>
<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>
<use>material/color-mode</use>
</color-mode>
</material>
<blend>
<active>
<use>blend/active</use>
</active>
<source>
<use>blend/source</use>
</source>
<destination>
<use>blend/destination</use>
</destination>
</blend>
<shade-model>
<use>shade-model</use>
</shade-model>
<cull-face>
<use>cull-face</use>
</cull-face>
<rendering-hint>
<use>rendering-hint</use>
</rendering-hint>
<blend>
<use>transparent</use>
</blend>
<alpha-test>
<use>transparent</use>
</alpha-test>
<render-bin>
<bin-number>
<use>render-bin/bin-number</use>
</bin-number>
<bin-name>
<use>render-bin/bin-name</use>
</bin-name>
</render-bin>
<!-- Diffuse texture unit-->
<texture-unit>
<unit>0</unit>
<image>
<use>texture[0]/image</use>
</image>
<type>
<use>texture[0]/type</use>
</type>
<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>
<!-- Car Metadata texture unit-->
<texture-unit>
<unit>1</unit>
<image>
<use>texture[9]/image</use>
</image>
<type>
<use>texture[9]/type</use>
</type>
<filter>
<use>texture[9]/filter</use>
</filter>
<wrap-s>
<use>texture[9]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[9]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[9]/internal-format</use>
</internal-format>
</texture-unit>
<!-- Car shape texture unit-->
<texture-unit>
<unit>3</unit>
<image>
<use>texture[8]/image</use>
</image>
<type>
<use>texture[8]/type</use>
</type>
<filter>
<use>texture[8]/filter</use>
</filter>
<wrap-s>
<use>texture[8]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[8]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[8]/internal-format</use>
</internal-format>
</texture-unit>
<vertex-program-two-side>
<use>vertex-program-two-side</use>
</vertex-program-two-side>
<program>
<vertex-shader>Shaders/ws30-ALS-ultra.vert</vertex-shader>
<vertex-shader>Shaders/filters-ALS.vert</vertex-shader>
<vertex-shader>Shaders/shadows-include.vert</vertex-shader>
<fragment-shader>Shaders/road-ALS-ultra.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
<fragment-shader>Shaders/secondary_lights.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/filters-ALS.frag</fragment-shader>
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
<attribute>
<name>orthophotoTexCoord</name>
<index>14</index>
</attribute>
</program>
<uniform>
<name>BaseTex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>CarMetaTex</name>
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>NormalTex</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>CarTex</name>
<type>sampler-2d</type>
<value type="int">3</value>
</uniform>
<!-- road traffic -->
<uniform>
<name>road_traffic_enabled</name>
<type>int</type>
<value>
<use>road-traffic-enabled</use>
</value>
</uniform>
<uniform>
<name>road_traffic_density</name>
<type>float</type>
<value>
<use>road-traffic-density</use>
</value>
</uniform>
<uniform>
<name>road_traffic_variation</name>
<type>float</type>
<value>
<use>road-traffic-variation</use>
</value>
</uniform>
<uniform>
<name>road_traffic_direction</name>
<type>int</type>
<value>
<use>road-traffic-direction</use>
</value>
</uniform>
<!-- road illumination -->
<uniform>
<name>streetlight_color</name>
<type>float-vec3</type>
<value>
<use>lightmap-color</use>
</value>
</uniform>
<uniform>
<name>streetlight_factor</name>
<type>float</type>
<value>
<use>road-light-factor</use>
</value>
</uniform>
<!-- use a grain texture map-->
<uniform>
<name>grain_texture_enabled</name>
<type>int</type>
<value>
<use>grain-texture-enabled</use>
</value>
</uniform>
<uniform>
<name>grain_magnification</name>
<type>float</type>
<value>
<use>grain-magnification</use>
</value>
</uniform>
<!-- simulate wetness, snow and rain-->
<uniform>
<name>rain_enabled</name>
<type>int</type>
<value>
<use>rain-enabled</use>
</value>
</uniform>
<uniform>
<name>snowlevel</name>
<type>float</type>
<value><use>snow_level</use></value>
</uniform>
<uniform>
<name>snow_thickness_factor</name>
<type>float</type>
<value><use>snow_thickness_factor</use></value>
</uniform>
<!-- set the amount of ambient light correction 0.0 - 1.0 -->
<uniform>
<name>amb_correction</name>
<type>float</type>
<value>
<use>ambient-correction</use>
</value>
</uniform>
<uniform>
<name>hdg</name>
<type>float</type>
<value>
<use>model-hdg</use>
</value>
</uniform>
<uniform>
<name>pitch</name>
<type>float</type>
<value>
<use>model-pitch</use>
</value>
</uniform>
<uniform>
<name>roll</name>
<type>float</type>
<value>
<use>model-roll</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>terminator</name>
<type>float</type>
<value>
<use>terminator</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>cloud_self_shading</name>
<type>float</type>
<value><use>cloud_self_shading</use></value>
</uniform>
<uniform>
<name>moonlight</name>
<type>float</type>
<value><use>moonlight</use></value>
</uniform>
<uniform>
<name>air_pollution</name>
<type>float</type>
<value><use>air_pollution</use></value>
</uniform>
<uniform>
<name>rain_norm</name>
<type>float</type>
<value><use>rnorm</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>
<value><use>wetness</use></value>
</uniform>
<uniform>
<name>view_pitch_offset</name>
<type>float</type>
<value><use>view_pitch_offset</use></value>
</uniform>
<uniform>
<name>view_heading_offset</name>
<type>float</type>
<value><use>view_heading_offset</use></value>
</uniform>
<uniform>
<name>field_of_view</name>
<type>float</type>
<value><use>view_fov</use></value>
</uniform>
<uniform>
<name>landing_light1_offset</name>
<type>float</type>
<value><use>landing_light1_offset</use></value>
</uniform>
<uniform>
<name>landing_light2_offset</name>
<type>float</type>
<value><use>landing_light2_offset</use></value>
</uniform>
<uniform>
<name>landing_light3_offset</name>
<type>float</type>
<value><use>landing_light3_offset</use></value>
</uniform>
<uniform>
<name>gamma</name>
<type>float</type>
<value><use>gamma</use></value>
</uniform>
<uniform>
<name>brightness</name>
<type>float</type>
<value><use>brightness</use></value>
</uniform>
<uniform>
<name>use_filtering</name>
<type>bool</type>
<value><use>use_filtering</use></value>
</uniform>
<uniform>
<name>use_night_vision</name>
<type>bool</type>
<value><use>use_night_vision</use></value>
</uniform>
<uniform>
<name>use_IR_vision</name>
<type>bool</type>
<value><use>use_IR_vision</use></value>
</uniform>
<uniform>
<name>delta_T</name>
<type>float</type>
<value><use>delta_T</use></value>
</uniform>
<uniform>
<name>fact_grey</name>
<type>float</type>
<value><use>fact_grey</use></value>
</uniform>
<uniform>
<name>fact_black</name>
<type>float</type>
<value><use>fact_black</use></value>
</uniform>
<!-- cloud shadows -->
<uniform>
<name>cloudpos1_x</name>
<type>float</type>
<value><use>cloudpos1_x</use></value>
</uniform>
<uniform>
<name>cloudpos1_y</name>
<type>float</type>
<value><use>cloudpos1_y</use></value>
</uniform>
<uniform>
<name>cloudpos2_x</name>
<type>float</type>
<value><use>cloudpos2_x</use></value>
</uniform>
<uniform>
<name>cloudpos2_y</name>
<type>float</type>
<value><use>cloudpos2_y</use></value>
</uniform>
<uniform>
<name>cloudpos3_x</name>
<type>float</type>
<value><use>cloudpos3_x</use></value>
</uniform>
<uniform>
<name>cloudpos3_y</name>
<type>float</type>
<value><use>cloudpos3_y</use></value>
</uniform>
<uniform>
<name>cloudpos4_x</name>
<type>float</type>
<value><use>cloudpos4_x</use></value>
</uniform>
<uniform>
<name>cloudpos4_y</name>
<type>float</type>
<value><use>cloudpos4_y</use></value>
</uniform>
<uniform>
<name>cloudpos5_x</name>
<type>float</type>
<value><use>cloudpos5_x</use></value>
</uniform>
<uniform>
<name>cloudpos5_y</name>
<type>float</type>
<value><use>cloudpos5_y</use></value>
</uniform>
<uniform>
<name>cloudpos6_x</name>
<type>float</type>
<value><use>cloudpos6_x</use></value>
</uniform>
<uniform>
<name>cloudpos6_y</name>
<type>float</type>
<value><use>cloudpos6_y</use></value>
</uniform>
<uniform>
<name>cloudpos7_x</name>
<type>float</type>
<value><use>cloudpos7_x</use></value>
</uniform>
<uniform>
<name>cloudpos7_y</name>
<type>float</type>
<value><use>cloudpos7_y</use></value>
</uniform>
<uniform>
<name>cloudpos8_x</name>
<type>float</type>
<value><use>cloudpos8_x</use></value>
</uniform>
<uniform>
<name>cloudpos8_y</name>
<type>float</type>
<value><use>cloudpos8_y</use></value>
</uniform>
<uniform>
<name>cloudpos9_x</name>
<type>float</type>
<value><use>cloudpos9_x</use></value>
</uniform>
<uniform>
<name>cloudpos9_y</name>
<type>float</type>
<value><use>cloudpos9_y</use></value>
</uniform>
<uniform>
<name>cloudpos10_x</name>
<type>float</type>
<value><use>cloudpos10_x</use></value>
</uniform>
<uniform>
<name>cloudpos10_y</name>
<type>float</type>
<value><use>cloudpos10_y</use></value>
</uniform>
<uniform>
<name>cloudpos11_x</name>
<type>float</type>
<value><use>cloudpos11_x</use></value>
</uniform>
<uniform>
<name>cloudpos11_y</name>
<type>float</type>
<value><use>cloudpos11_y</use></value>
</uniform>
<uniform>
<name>cloudpos12_x</name>
<type>float</type>
<value><use>cloudpos12_x</use></value>
</uniform>
<uniform>
<name>cloudpos12_y</name>
<type>float</type>
<value><use>cloudpos12_y</use></value>
</uniform>
<uniform>
<name>cloudpos13_x</name>
<type>float</type>
<value><use>cloudpos13_x</use></value>
</uniform>
<uniform>
<name>cloudpos13_y</name>
<type>float</type>
<value><use>cloudpos13_y</use></value>
</uniform>
<uniform>
<name>cloudpos14_x</name>
<type>float</type>
<value><use>cloudpos14_x</use></value>
</uniform>
<uniform>
<name>cloudpos14_y</name>
<type>float</type>
<value><use>cloudpos14_y</use></value>
</uniform>
<uniform>
<name>cloudpos15_x</name>
<type>float</type>
<value><use>cloudpos15_x</use></value>
</uniform>
<uniform>
<name>cloudpos15_y</name>
<type>float</type>
<value><use>cloudpos15_y</use></value>
</uniform>
<uniform>
<name>cloudpos16_x</name>
<type>float</type>
<value><use>cloudpos16_x</use></value>
</uniform>
<uniform>
<name>cloudpos16_y</name>
<type>float</type>
<value><use>cloudpos16_y</use></value>
</uniform>
<uniform>
<name>cloudpos17_x</name>
<type>float</type>
<value><use>cloudpos17_x</use></value>
</uniform>
<uniform>
<name>cloudpos17_y</name>
<type>float</type>
<value><use>cloudpos17_y</use></value>
</uniform>
<uniform>
<name>cloudpos18_x</name>
<type>float</type>
<value><use>cloudpos18_x</use></value>
</uniform>
<uniform>
<name>cloudpos18_y</name>
<type>float</type>
<value><use>cloudpos18_y</use></value>
</uniform>
<uniform>
<name>cloudpos19_x</name>
<type>float</type>
<value><use>cloudpos19_x</use></value>
</uniform>
<uniform>
<name>cloudpos19_y</name>
<type>float</type>
<value><use>cloudpos19_y</use></value>
</uniform>
<uniform>
<name>cloudpos20_x</name>
<type>float</type>
<value><use>cloudpos20_x</use></value>
</uniform>
<uniform>
<name>cloudpos20_y</name>
<type>float</type>
<value><use>cloudpos20_y</use></value>
</uniform>
<uniform>
<name>cloud_shadow_flag</name>
<type>int</type>
<value><use>cloud_shadow_flag</use></value>
</uniform>
<uniform>
<name>use_searchlight</name>
<type>int</type>
<value><use>use_searchlight</use></value>
</uniform>
<uniform>
<name>use_landing_light</name>
<type>int</type>
<value><use>use_landing_light</use></value>
</uniform>
<uniform>
<name>use_alt_landing_light</name>
<type>int</type>
<value><use>use_alt_landing_light</use></value>
</uniform>
<uniform>
<name>display_xsize</name>
<type>int</type>
<value><use>display_xsize</use></value>
</uniform>
<uniform>
<name>display_ysize</name>
<type>int</type>
<value><use>display_ysize</use></value>
</uniform>
<!-- BEGIN shadows include -->
<uniform>
<name>shadow_tex</name>
<type>sampler-2d</type>
<value type="int">10</value>
</uniform>
<uniform>
<name>shadows_enabled</name>
<type>bool</type>
<value>
<use>shadows_enabled</use>
</value>
</uniform>
<uniform>
<name>sun_atlas_size</name>
<type>int</type>
<value>
<use>sun_atlas_size</use>
</value>
</uniform>
<!-- END shadows include -->
</pass>
</technique>
</PropertyList>

View file

@ -107,6 +107,16 @@
<wind_effects><use>/sim/rendering/shaders/wind-effects</use></wind_effects>
<windE><use>/environment/sea/surface/wind-from-east-fps</use></windE>
<windN><use>/environment/sea/surface/wind-from-north-fps</use></windN>
<WaveFreq><use>/environment/wave/freq</use></WaveFreq>
<WaveAmp><use>/environment/wave/amp</use></WaveAmp>
<WaveSharp><use>/environment/wave/sharp</use></WaveSharp>
<WaveAngle><use>/environment/wave/angle</use></WaveAngle>
<WaveFactor><use>/environment/wave/factor</use></WaveFactor>
<WaveDAngle><use>/environment/wave/dangle</use></WaveDAngle>
<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>
<saturation><use>/rendering/scene/saturation</use></saturation>
<display_xsize><use>/sim/startup/xsize</use></display_xsize>
<display_ysize><use>/sim/startup/ysize</use></display_ysize>
<!--
@ -182,7 +192,11 @@
insert their own techniques first. -->
<!-- ALS ultra shaders -->
<!--
ALS ultra shaders. The 1st pass of ws30-overlay.eff is a copy of
this pass, and changes should be made there as well.
-->
<technique n="5">
<predicate>
<and>
@ -285,6 +299,7 @@
<vertex-shader>Shaders/shadows-include.vert</vertex-shader>
<fragment-shader>Shaders/ws30-ALS-ultra.frag</fragment-shader>
<fragment-shader>Shaders/ws30-ALS-landclass-search-functions.frag</fragment-shader>
<fragment-shader>Shaders/ws30-water.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/cloud-shadowfunc.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
@ -293,6 +308,11 @@
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
</program>
<uniform>
<name>quality_level</name>
<type>int</type>
<value><use>quality_level</use></value>
</uniform>
<uniform>
<name>visibility</name>
<type>float</type>
@ -672,6 +692,11 @@
<value><use>cloudpos20_y</use></value>
</uniform>
<uniform>
<name>saturation</name>
<type>float</type>
<value><use>saturation</use></value>
</uniform>
<uniform>
<name>WindE</name>
<type>float</type>
<value><use>windE</use></value>
@ -682,6 +707,75 @@
<value><use>windN</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>
<!-- 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>ocean_flag</name>
<type>int</type>
<value><use>ocean_flag</use></value>
</uniform>
<uniform>
<name>use_searchlight</name>
<type>int</type>
<value> <use>use_searchlight</use></value>
@ -882,6 +976,7 @@
<vertex-shader>Shaders/shadows-include.vert</vertex-shader>
<fragment-shader>Shaders/ws30-ALS-detailed.frag</fragment-shader>
<fragment-shader>Shaders/ws30-ALS-landclass-search-functions.frag</fragment-shader>
<fragment-shader>Shaders/ws30-water.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
<fragment-shader>Shaders/filters-ALS.frag</fragment-shader>
@ -983,7 +1078,94 @@
<type>float</type>
<value><use>season</use></value>
</uniform>
<!-- filtering -->
<uniform>
<name>saturation</name>
<type>float</type>
<value><use>saturation</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>
<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>
<!-- 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>ocean_flag</name>
<type>int</type>
<value><use>ocean_flag</use></value>
</uniform> <!-- filtering -->
<uniform>
<name>gamma</name>
<type>float</type>
@ -1182,12 +1364,23 @@
<vertex-shader>Shaders/shadows-include.vert</vertex-shader>
<fragment-shader>Shaders/ws30-ALS.frag</fragment-shader>
<fragment-shader>Shaders/ws30-ALS-landclass-search-functions.frag</fragment-shader>
<fragment-shader>Shaders/ws30-water.frag</fragment-shader>
<fragment-shader>Shaders/hazes.frag</fragment-shader>
<fragment-shader>Shaders/noise.frag</fragment-shader>
<fragment-shader>Shaders/filters-ALS.frag</fragment-shader>
<fragment-shader>Shaders/shadows-include.frag</fragment-shader>
<fragment-shader>Shaders/clustered-include.frag</fragment-shader>
</program>
<uniform>
<name>tquality_level</name>
<type>int</type>
<value><use>tquality_level</use></value>
</uniform>
<uniform>
<name>cloud_self_shading</name>
<type>float</type>
<value><use>cloud_self_shading</use></value>
</uniform>
<uniform>
<name>visibility</name>
<type>float</type>
@ -1248,6 +1441,94 @@
<type>float</type>
<value><use>air_pollution</use></value>
</uniform>
<uniform>
<name>saturation</name>
<type>float</type>
<value><use>saturation</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>
<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>
<!-- 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>ocean_flag</name>
<type>int</type>
<value><use>ocean_flag</use></value>
</uniform>
<!-- filtering -->
<uniform>
<name>gamma</name>

View file

@ -486,6 +486,7 @@
<wetness-set type="double" userarchive="y">0.0</wetness-set>
<wetness type="double" userarchive="n">0.0</wetness>
<snow-thickness-factor type="double" userarchive="y">1.0</snow-thickness-factor>
<ice-cover type="bool" userarchive="n">false</ice-cover>
<delta-T-soil type="double" userarchive="n">0.0</delta-T-soil>
<delta-T-vegetation type="double" userarchive="n">0.0</delta-T-vegetation>
<delta-T-rock type="double" userarchive="n">0.0</delta-T-rock>
@ -531,5 +532,7 @@
<!-- definitions for vocanic activity -->
<volcanoes include="volcanoes.xml"/>
<star-magnitude-cutoff type="float">4.5</star-magnitude-cutoff>
<darksky-brightness-magnitude type="float">22.0</darksky-brightness-magnitude>
<galaxy-bulge-brightness-magnitude type="float">20.3</galaxy-bulge-brightness-magnitude>
</PropertyList>

View file

@ -6,9 +6,13 @@ Download: http://koeppen-geiger.vu-wien.ac.at/Rcode/Map_KG-Global.zip
World terrain elevation data:
https://visibleearth.nasa.gov/images/73934/topography
Total precipitations per annum, over land:
https://commons.wikimedia.org/wiki/File:World_precip_annual.png
The red channel of the image contans the Köppen-Geiger code.
The green channel of the image contains the world elevation map.
The blue channel of the image contains annual precipitation.
ASICII
CODE description

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 MiB

After

Width:  |  Height:  |  Size: 2.3 MiB

View file

@ -635,7 +635,7 @@
<material n="3002">
<name>ws30Road</name>
<texture>osm2city/roads.png</texture>
<!-- <effect>Effects/terrain-default</effect> -->
<effect>Effects/ws30-road-mid</effect>
<line-feature-tex-x0>0.25</line-feature-tex-x0>
<line-feature-tex-x1>0.375</line-feature-tex-x1>
<line-feature-offset-m>0.75</line-feature-offset-m>
@ -663,7 +663,7 @@
<material n="3003">
<name>ws30Freeway</name>
<texture>osm2city/roads.png</texture>
<effect>Effects/terrain-default</effect>
<effect>Effects/ws30-road-high</effect>
<line-feature-tex-x0>0.625</line-feature-tex-x0>
<line-feature-tex-x1>0.75</line-feature-tex-x1>
<line-feature-offset-m>1.0</line-feature-offset-m>
@ -725,7 +725,7 @@
<material n="3005">
<name>ws30Railway</name>
<texture>osm2city/roads.png</texture>
<effect>Effects/terrain-default</effect>
<effect>Effects/ws30-railway</effect>
<line-feature-tex-x0>0</line-feature-tex-x0>
<line-feature-tex-x1>0.125</line-feature-tex-x1>
<line-feature-offset-m>0.5</line-feature-offset-m>

View file

@ -278,7 +278,13 @@
<name>Estuary</name>
<name>Watercourse</name>
<name>Saline</name>
<texture-set>
<texture>Terrain/water-lake.png</texture>
<texture n="10">Terrain/frozen_lake.png</texture>
</texture-set>
<parameters>
<ice_cover><use>/environment/surface/ice-cover</use></ice_cover>
</parameters>
<xsize>400</xsize>
<ysize>400</ysize>
<ambient>
@ -300,7 +306,7 @@
<a>1.0</a>
</specular>
<shininess>1.2</shininess>
<solid>0</solid>
<solid><property>/environment/surface/ice-cover</property></solid>
<rolling-friction>1.5</rolling-friction>
<bumpiness>0.6</bumpiness>
</material>

View file

@ -185,6 +185,7 @@
<parameters>
<rotation_flag>0</rotation_flag>
<rotation_scale>8000.0</rotation_scale>
<edge-hardness>0.5</edge-hardness>
</parameters>
<xsize>2000</xsize>
<ysize>2000</ysize>
@ -250,6 +251,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>15.0</tree-height-m>
<tree-width-m>10.0</tree-width-m>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -271,6 +275,7 @@
<urban_blend>1</urban_blend>
<blend_bias>0.2</blend_bias>
<hires_overlay_bias>-1.0</hires_overlay_bias>
<edge-hardness>0.8</edge-hardness>
</parameters>
<xsize>1024</xsize>
<ysize>1024</ysize>
@ -331,6 +336,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>15.0</tree-height-m>
<tree-width-m>10.0</tree-width-m>
<parameters>
<edge-hardness>0.9</edge-hardness>
</parameters>
</material>
<material>
@ -408,6 +416,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.1</edge-hardness>
</parameters>
</material>
<material>
@ -434,6 +445,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.1</edge-hardness>
</parameters>
</material>
<material>
@ -516,6 +530,7 @@
<overlay_autumn_flag>1</overlay_autumn_flag>
<overlay_brightness_top>1.4</overlay_brightness_top>
<overlay_brightness_bottom>0.6</overlay_brightness_bottom>
<edge-hardness>0.8</edge-hardness>
</parameters>
<xsize>2000</xsize>
<ysize>2000</ysize>
@ -550,6 +565,7 @@
<overlay_autumn_flag>1</overlay_autumn_flag>
<overlay_brightness_top>1.4</overlay_brightness_top>
<overlay_brightness_bottom>0.6</overlay_brightness_bottom>
<edge-hardness>0.8</edge-hardness>
</parameters>
<xsize>2000</xsize>
<ysize>2000</ysize>

View file

@ -96,6 +96,9 @@
<tree-width-m>15.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>1</bumpiness>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -115,6 +118,9 @@
<tree-width-m>15.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>0.85</bumpiness>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -133,6 +139,9 @@
<tree-width-m>15.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>0.95</bumpiness>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -152,6 +161,9 @@
<tree-width-m>18.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>1</bumpiness>
<parameters>
<edge-hardness>0.9</edge-hardness>
</parameters>
</material>
<material>
@ -169,6 +181,9 @@
<tree-width-m>15.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>1</bumpiness>
<parameters>
<edge-hardness>0.9</edge-hardness>
</parameters>
</material>
<material>
@ -185,6 +200,9 @@
<tree-width-m>8.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>1</bumpiness>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -291,6 +309,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>25.0</tree-height-m>
<tree-width-m>15.0</tree-width-m>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -312,6 +333,9 @@
<a>1.0</a>
</emissive>
<object-group include="Materials/base/industrial-buildings.xml"/>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -339,6 +363,9 @@
<a>1.0</a>
</emissive>
<object-group include="Materials/base/industrial-buildings.xml"/>
<parameters>
<edge-hardness>0.9</edge-hardness>
</parameters>
</material>
<!-- default town US style -->
@ -370,6 +397,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>12.0</tree-height-m>
<tree-width-m>7.0</tree-width-m>
<parameters>
<edge-hardness>0.7</edge-hardness>
</parameters>
</material>
<material>
@ -389,6 +419,9 @@
<name>Ocean</name>
<effect>Effects/water</effect>
<texture>Terrain/water.png</texture>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -420,6 +453,9 @@
<solid>0</solid>
<rolling-friction>1.5</rolling-friction>
<bumpiness>0.6</bumpiness>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -431,7 +467,14 @@
<name>Estuary</name>
<name>Watercourse</name>
<name>Saline</name>
<texture-set>
<texture>Terrain/water-lake.png</texture>
<texture n="10">Terrain/frozen_lake.png</texture>
</texture-set>
<parameters>
<ice_cover><use>/environment/surface/ice-cover</use></ice_cover>
<edge-hardness>0.8</edge-hardness>
</parameters>
<xsize>400</xsize>
<ysize>400</ysize>
<ambient>
@ -453,7 +496,7 @@
<a>1.0</a>
</specular>
<shininess>1.2</shininess>
<solid>0</solid>
<solid><property>/environment/surface/ice-cover</property></solid>
<rolling-friction>1.5</rolling-friction>
<bumpiness>0.6</bumpiness>
</material>
@ -670,6 +713,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.7</edge-hardness>
</parameters>
</material>
<!-- default US style irrigated crops -->
@ -701,6 +747,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -730,6 +779,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
<material>
@ -854,6 +906,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.7</edge-hardness>
</parameters>
</material>
<material>
@ -876,6 +931,9 @@
<tree-varieties>8</tree-varieties>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
<parameters>
<edge-hardness>0.8</edge-hardness>
</parameters>
</material>
</PropertyList>

View file

@ -5,7 +5,7 @@ var parents = [SVGSymbol];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var svg_path = "Nasal/canvas/map/Images/boeingAirplane.svg";
var svg_path = "Nasal/canvas/map/Images/outlinedAirplane.svg";
var element_id = "airplane";
# Rotate with the main aircraft.

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="87.8438"
height="108.844"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="boeingAirplane.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.9598"
inkscape:cx="19.8149"
inkscape:cy="54.088"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1366"
inkscape:window-height="716"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 2"
inkscape:groupmode="layer"
id="layer2"
transform="translate(-364.652,-344.745)">
<g
id="airplane"
transform="translate(320.73272,291.98516)"
inkscape:label="#g3781">
<path
id="path3783-7"
d="M 29.126,102.65 29.2323,93.5433 35.3622,85.2874 34.6535,58.0039 2.12598,76.3228 1.98425,65.9764 35.185,35.5394 35.3976,15.0945 42.378,2.01969 50.563,15.5197 50.315,35.4685 85.8543,65.6575 85.748,75.0118 52.3701,56.9409 52.0157,86.2441 58.748,93.6496 58.6417,103.5 44.0787,95.4921 z"
style="fill:none;stroke:#797979;stroke-width:13.0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
</g>
</g>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-364.652,-344.745)">
<g
id="airplane"
transform="translate(320.73272,291.98516)"
inkscape:label="#g3781">
<path
id="path3783"
d="M 29.126,102.65 29.2323,93.5433 35.3622,85.2874 34.6535,58.0039 2.12598,76.3228 1.98425,65.9764 35.185,35.5394 35.3976,15.0945 42.378,2.01969 50.563,15.5197 50.315,35.4685 85.8543,65.6575 85.748,75.0118 52.3701,56.9409 52.0157,86.2441 58.748,93.6496 58.6417,103.5 44.0787,95.4921 z"
style="fill:none;stroke:#ededed;stroke-width:5.0px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -25,7 +25,7 @@ var new = func(layer) {
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(l,r) 0; # TODO: create model objects instead?
layer.searcher._equals = func(l,r) return (l == r);
append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ),
setlistener(layer.options.wp_num, func m.layer.update() ));

View file

@ -330,11 +330,20 @@ var tile_path = func(lat, lon) {
var put_model = func(path, c, arg...) {
call(_put_model, [path] ~ (isa(c, Coord) ? c.latlon() : [c]) ~ arg);
call(_put_model, [path, nil] ~ (isa(c, Coord) ? c.latlon() : [c]) ~ arg);
}
var put_marker = func(label, c, arg...) {
if (isa(c, Coord)) {
call(_put_marker, [label] ~ c.latlon() ~ arg);
}
else {
call(_put_marker, [label, c] ~ arg);
}
}
var _put_model = func(path, lat, lon, elev_m = nil, hdg = 0, pitch = 0, roll = 0) {
var _put_model = func(path, label, lat, lon, elev_m = nil, hdg = 0, pitch = 0, roll = 0) {
if (elev_m == nil)
elev_m = elevation(lat, lon);
if (elev_m == nil)
@ -346,6 +355,42 @@ var _put_model = func(path, lat, lon, elev_m = nil, hdg = 0, pitch = 0, roll = 0
return props.globals.getNode(n.getNode("property").getValue());
}
var _put_marker = func(label, lat, lon, elev = nil, color = nil, text_height_m = 1, pin_height_m = 1000, pin_tip_height_m = 0) {
params = {
"internal-model": "marker",
"heading-deg": 0, "pitch-deg": 0, "roll-deg": 0,
"marker": {
"text": label,
"color": color,
"size": text_height_m,
"height": pin_height_m,
"tip-height": pin_tip_height_m,
},
};
if (isnum(lat)) {
params['latitude-deg'] = lat;
}
elsif (isscalar(lat)) {
params['latitude-deg-prop'] = lat;
}
if (isnum(lon)) {
params['longitude-deg'] = lon;
}
elsif (isscalar(lon)) {
params['longitude-deg-prop'] = lon;
}
if (isnum(elev)) {
params['elevation-ft'] = elev;
}
elsif (isscalar(elev)) {
params['elevation-ft-prop'] = elev;
}
if (color == nil)
color = [1, 1, 1];
fgcommand("add-model", var n = props.Node.new(params));
return props.globals.getNode(n.getNode("property").getValue());
}
var elevation = func(lat, lon, maxalt = 10000) {
var d = geodinfo(lat, lon, maxalt);

View file

@ -56,4 +56,5 @@ geo.nas <- view.nas
<file>multiplayer.nas</file>
<file>geo.nas</file>
<file>view.nas</file>
<file>markerpins.nas</file>
</PropertyList>

215
Nasal/markerpins.nas Normal file
View file

@ -0,0 +1,215 @@
var pin_update_timer = nil;
var navPins = {};
var poiPins = {};
var trafficPins = {};
var trafficAddListener = nil;
var trafficRemoveListener = nil;
var enabled = {
master: 0,
airports: 0,
navaids: 0,
fixes: 0,
pois: 0,
traffic: 0,
};
var update_pins = func () {
var navs = [];
if (enabled.master) {
if (enabled.airports) {
airports = findAirportsWithinRange(50);
navs = navs ~ airports;
}
if (enabled.navaids) {
navaids = findNavaidsWithinRange(50, "vor") ~
findNavaidsWithinRange(50, "ndb") ~
findNavaidsWithinRange(20, "ils") ~
findNavaidsWithinRange(20, "loc");
navs = navs ~ navaids;
}
if (enabled.fixes) {
# navaids = findNavaidsWithinRange(50, "fix");
# navs = navs ~ navaids;
}
if (enabled.pois) {
navaids = findNavaidsWithinRange(50, "city") ~
findNavaidsWithinRange(15, "town") ~
findNavaidsWithinRange(5, "village");
navs = navs ~ navaids;
}
}
foreach (var k; keys(navPins)) {
navPins[k].alive = 0;
}
foreach (var nav; navs) {
var pin = navPins[nav.id];
if (pin == nil) {
var color = [1, 1, 1];
var height = 600;
var fsize = 128;
var elevation = nav.elevation;
if (elevation == nil or elevation == 0) {
elevation = geo.elevation(nav.lat, nav.lon);
}
if (elevation == nil) {
continue;
}
elevation = elevation * M2FT;
if (ghosttype(nav) == "airport") {
color = [1, 0, 0];
fsize = 256;
height = 1200;
}
else {
if (nav.type == "VOR") {
color = [0, 0.5, 1];
fsize = 160;
height = 900;
}
elsif (nav.type == "NDB") {
color = [0.5, 0.25, 0];
fsize = 128;
height = 700;
}
elsif (nav.type == "LOC" or nav.type == "ILS") {
color = [0, 1, 1];
fsize = 32;
height = 50;
}
elsif (nav.type == "FIX") {
color = [1, 1, 0];
fsize = 64;
height = 900;
}
elsif (nav.type == "city") {
color = [1, 1, 1];
fsize = 256;
height = 600;
}
elsif (nav.type == "town") {
color = [1, 1, 1];
fsize = 128;
height = 300;
}
elsif (nav.type == "village") {
color = [1, 1, 1];
fsize = 64;
height = 150;
}
}
pin = {
marker: geo.put_marker(nav.id, nav.lat, nav.lon, elevation, color, fsize, height),
};
navPins[nav.id] = pin;
}
navPins[nav.id].alive = 1;
}
foreach (var k; keys(navPins)) {
if (!navPins[k].alive) {
navPins[k].marker.remove();
delete(navPins, k);
}
}
};
var toggleTrafficPins = func (node) {
if (node.getBoolValue()) {
# turn on
print("Traffic pins on");
var modelsNode = props.getNode('/ai/models');
var nodes = modelsNode.getChildren('multiplayer') ~
modelsNode.getChildren('swift') ~
modelsNode.getChildren('aircraft');
foreach (var k; keys(trafficPins)) {
trafficPins[k].alive = 0;
}
var addTraffic = func (node, retry=3) {
var nodeID = node.getName() ~ ':' ~ node.getIndex();
var callsign = node.getValue('callsign');
printf("Adding traffic: %s [%s]", nodeID, node.getValue('callsign'));
if (callsign == nil) {
if (retry > 0) {
# try again in 1 second
settimer(func { addTraffic(node, retry-1); }, 1);
}
else {
printf("Giving up on %s", nodeID);
}
}
else {
var pin = trafficPins[nodeID];
if (pin == nil) {
var elev_prop = node.getPath() ~ '/position/altitude-ft';
var lat_prop = node.getPath() ~ '/position/latitude-deg';
var lon_prop = node.getPath() ~ '/position/longitude-deg';
pin = {
marker: geo.put_marker(callsign, lat_prop, lon_prop, elev_prop, [1,1,0], 10, 15, 5),
};
trafficPins[nodeID] = pin;
}
trafficPins[nodeID].alive = 1;
}
};
foreach (var node; nodes) {
if (node.getValue('valid')) {
addTraffic(node);
}
}
trafficRemoveListener = setlistener('/ai/models/model-removed', func(n) {
var path = n.getValue();
var node = props.getNode(path);
var nodeID = node.getName() ~ ':' ~ node.getIndex();
if (trafficPins[nodeID] != nil) {
trafficPins[nodeID].marker.remove();
delete(trafficPins, nodeID);
}
});
trafficAddListener = setlistener('/ai/models/model-added', func (n) {
var path = n.getValue();
var node = props.getNode(path);
addTraffic(node);
});
foreach (var k; keys(trafficPins)) {
if (!trafficPins[k].alive) {
trafficPins[l].marker.remove();
delete(trafficPins, k);
}
}
}
else {
# turn off
print("Traffic pins off");
if (trafficAddListener != nil) removelistener(trafficAddListener);
if (trafficRemoveListener != nil) removelistener(trafficRemoveListener);
foreach (var k; keys(trafficPins)) {
trafficPins[k].marker.remove();
}
trafficPins = {};
}
};
var fdm_init_listener = setlistener("/sim/signals/fdm-initialized", func {
removelistener(fdm_init_listener); # uninstall, so we are only called once
foreach (var k; ['master', 'airports', 'navaids', 'fixes', 'pois', 'traffic']) {
var path = '/sim/marker-pins/' ~ k;
var node = props.getNode(path);
if (node == nil) {
node = props.getNode(path, 1);
node.setBoolValue(0);
node.setAttribute('userarchive', 'y');
}
if (k == 'traffic') {
setlistener(path, toggleTrafficPins, 1, 0);
}
else {
setlistener(path, (func (key) { return func (p) { enabled[key] = p.getBoolValue(); }; })(k), 1, 0);
}
}
var timer = maketimer(1, update_pins);
timer.start();
});

View file

@ -195,12 +195,13 @@ var dialog = {
me.font = nil;
}
me.header = ["view", " callsign", " model", func dialog.dist_hdr, func dialog.alt_hdr ~ " ", "", " brg", "chat", "ignore" ~ " ", " code", "ver", "airport", " set"];
me.header = ["view", " callsign", " model", func dialog.dist_hdr, " ", func dialog.alt_hdr ~ " ", "", " brg", "chat", "ignore" ~ " ", " code", "ver", "airport", " set"];
me.columns = [
{ type: "checkbox", legend: "", property: "view", halign: "right", "pref-height": 14, "pref-width": 14, callback: "multiplayer.view_select", argprop: "callsign", },
{ type: "text", property: "callsign", format: " %s", label: "-----------", halign: "fill" },
{ type: "text", property: "model-short", format: " %s", label: "--------------", halign: "fill" },
{ type: "text", property: func dialog.dist_node, format:" %8.2f", label: "---------", halign: "right" },
{ type: "text", property: "distance_delta", format: "%s", label: "--", halign: "right" },
{ type: "text", property: func dialog.alt_node, format:" %7.0f", label: "---------", halign: "right" },
{ type: "text", property: "ascent_descent", format: "%s", label: "-", halign: "right" },
{ type: "text", property: "bearing-to", format: " %3.0f", label: "----", halign: "right" },
@ -290,6 +291,7 @@ var dialog = {
var row = 0;
var col = 0;
# First row is column headers.
foreach (var h; me.header) {
var w = content.addChild("text");
var l = typeof(h) == "func" ? h() : h;
@ -301,6 +303,7 @@ var dialog = {
}
row += 2;
var odd = 1;
# Add a row for each multiplayer aircraft.
foreach (var mp; model.list) {
var col = 0;
var color = me.fg[2];
@ -424,12 +427,20 @@ var dialog = {
else ascent_descent = '';
}
distance_delta_text = ' ';
var distance_km_old = n.getValue('distance-to-km');
if (distance_km_old != nil) {
var distance_delta = distance - distance_km_old * 1000;
if (distance_delta > 10) distance_delta_text = ' +';
if (distance_delta < -10) distance_delta_text = ' -';
}
n.setValues({
"model-short": n.getNode("model-installed").getValue() ? mp.model : "[" ~ mp.model ~ "]",
"set-loaded": set_loaded ? " *" : " ",
"bearing-to": self.course_to(ac),
"distance-to-km": distance / 1000.0,
"distance-to-nm": distance * M2NM,
"distance_delta": distance_delta_text,
"position/altitude-m": n.getNode("position/altitude-ft").getValue() * FT2M,
"ascent_descent": ascent_descent,
"controls/invisible": contains(ignore, mp.callsign),

202
Nasal/screenshot.nas Normal file
View file

@ -0,0 +1,202 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2009 by Torsten Renk
# Copyright (C) 2013 by penta
# Copyright (C) 2022 by Erik Hofman
#
# Based on:
# https://forum.flightgear.org/viewtopic.php?f=6&t=6380&p=53863#p53681
# https://forum.flightgear.org/viewtopic.php?f=19&t=7713&start=15#p180816
var rotatescreen = func(heading_deg, pitch_deg, roll_deg)
{
setprop("/sim/current-view/goal-heading-offset-deg", heading_deg);
setprop("/sim/current-view/heading-offset-deg", heading_deg);
setprop("/sim/current-view/goal-pitch-offset-deg", pitch_deg);
setprop("/sim/current-view/pitch-offset-deg", pitch_deg);
setprop("/sim/current-view/goal-roll-offset-deg", roll_deg);
setprop("/sim/current-view/roll-offset-deg", roll_deg);
}
var takescreen = func(heading_deg, pitch_deg)
{
print ("taking screen with heading= ", heading_deg, " and pitch= ", pitch_deg);
var success = fgcommand("screen-capture");
if (success)
{
print ("screen taken with heading= ", heading_deg, " and pitch= ", pitch_deg);
}
else
{
print("screen not taken");
}
}
var i=0;
var j=0;
var k=0;
var tick_time=3;
var width = getprop("/sim/startup/xsize");
var height = getprop("/sim/startup/ysize");
var menubarvalue=getprop("/sim/menubar/visibility");
var znearvalue=("sim/rendering/camera-group/znear");
var fovvalue=getprop("/sim/current-view/field-of-view");
var freezemvalue=getprop("/sim/freeze/master");
var freezecvalue=getprop("/sim/freeze/clock");
var headingvalue=getprop("/sim/current-view/heading-offset-deg");
var pitchvalue=getprop("/sim/current-view/pitch-offset-deg");
var rollvalue=getprop("/sim/current-view/roll-offset-deg");
var cube_screen_ticks = func()
{
if (i==0 or i==2)
{
roll_deg=0;
heading_deg=headingvalue;
if (i==0) pitch_deg=-90;
else pitch_deg=90;
}
else
{
pitch_deg=0;
heading_deg=headingvalue-90*j;
roll_deg = -270+j*90;
}
if (k==0)
{
k = 1;
rotatescreen(heading_deg, pitch_deg, roll_deg);
settimer(cube_screen_ticks, tick_time, tick_time);
}
elsif (k==1)
{
if (i<3)
{
k = 0;
takescreen(heading_deg, pitch_deg);
if (i==0 or i==2) {
i=i+1;
settimer(cube_screen_ticks, tick_time, tick_time);
}
else if (i==1)
{
if (j<3)
{
j=j+1;
settimer(cube_screen_ticks, tick_time, tick_time);
}
else {
i=i+1;
settimer(cube_screen_ticks, tick_time, tick_time);
}
}
}
else
{
setprop("/sim/menubar/visibility", menubarvalue);
setprop("/sim/current-view/field-of-view", fovvalue);
setprop("/sim/current-view/heading-offset-deg", headingvalue);
setprop("/sim/current-view/pitch-offset-deg", pitchvalue);
setprop("/sim/freeze/master", freezemvalue);
setprop("/sim/freeze/clock", freezecvalue);
}
}
}
var panorama_screen_ticks = func()
{
if (i==0) {
pitch_deg=-45;
} else {
pitch_deg=45;
}
heading_deg=j*(-90);
if (k==0)
{
k=1;
rotatescreen(heading_deg, pitch_deg, 0);
settimer(panorama_screen_ticks, tick_time, tick_time);
}
else if (k==1)
{
k=0;
takescreen(heading_deg, pitch_deg);
if (j!=3)
{
j=j+1;
settimer(panorama_screen_ticks, tick_time, tick_time);
}
else
{
if (i==0)
{
i=i+1;
j=0;
settimer(panorama_screen_ticks, tick_time, tick_time);
}
else
{
k=2;
settimer(panorama_screen_ticks, tick_time, tick_time);
}
}
}
else
{
setprop("/sim/menubar/visibility", menubarvalue);
setprop("/sim/current-view/field-of-view", fovvalue);
setprop("/sim/current-view/heading-offset-deg", headingvalue);
setprop("/sim/current-view/pitch-offset-deg", pitchvalue);
setprop("/sim/current-view/roll-offset-deg", rollvalue);
setprop("/sim/freeze/master", freezemvalue);
setprop("/sim/freeze/clock", freezecvalue);
}
}
var make_cubemap = func()
{
width = getprop("/sim/startup/xsize");
height = getprop("/sim/startup/ysize");
menubarvalue=getprop("/sim/menubar/visibility");
znearvalue=("sim/rendering/camera-group/znear");
fovvalue=getprop("/sim/current-view/field-of-view");
freezemvalue=getprop("/sim/freeze/master");
freezecvalue=getprop("/sim/freeze/clock");
headingvalue=getprop("/sim/current-view/heading-offset-deg");
pitchvalue=getprop("/sim/current-view/pitch-offset-deg");
rollvalue=getprop("/sim/current-view/roll-offset-deg");
setprop("/sim/menubar/visibility", 'false');
setprop("/sim/rendering/camera-group/znear",0.03);
setprop("/sim/current-view/field-of-view", 170);
setprop("/sim/freeze/master",'true');
setprop("/sim/freeze/clock",'true');
i=0;
j=0;
k=0;
cube_screen_ticks();
}
var make_panorama = func()
{
menubarvalue=getprop("/sim/menubar/visibility");
znearvalue=("sim/rendering/camera-group/znear");
fovvalue=getprop("/sim/current-view/field-of-view");
freezemvalue=getprop("/sim/freeze/master");
freezecvalue=getprop("/sim/freeze/clock");
headingvalue=getprop("/sim/current-view/heading-offset-deg");
pitchvalue=getprop("/sim/current-view/pitch-offset-deg");
rollvalue=getprop("/sim/current-view/roll-offset-deg");
setprop("/sim/menubar/visibility", 'false');
setprop("/sim/rendering/camera-group/znear",0.03);
setprop("/sim/current-view/field-of-view", 120);
setprop("/sim/freeze/master",'true');
setprop("/sim/freeze/clock",'true');
i=0;
j=0;
k=0;
panorama_screen_ticks();
}

218
Shaders/galaxy.frag Normal file
View file

@ -0,0 +1,218 @@
// -*-C++-*-
//
// Chris Ringeval (November 2021)
//
#version 120
varying vec3 eye2VertInEyeSpace;
varying vec3 eye2ZenithInEyeSpace;
varying vec3 eye2MoonInEyeSpace;
uniform sampler2D milkyway;
uniform float moonlight;
uniform float mudarksky;
uniform float altitude;
uniform float atmosphere_top;
uniform float fg_ZenithSkyBrightness;
uniform float mugxybulge;
// conversion factor to recover moon logI in lux
const float max_loglux = -0.504030345621;
const float min_loglux = -4.399646345620;
// conversion factor to recover moon logI in footcandle
const float luxtofootcandle = -1.0319696543787917;
// the log10 of Mie + Rayleight scattering function at minimum,
// i.e., for a Moon-Sky distance of 90 degrees
const float logf90 = 5.399285;
//extinction coefficient at Maunea Kea (2800m asl), in mag/airmass
const float k2800 = 0.172;
// cos(3pi/5), at asl 0m, any light source < -18 degrees above the horizon does
// not light-up atmosphere -> zenital angle > 108 degrees.
const float cosUnvisible = -0.309016994374947;
// D65 white multiplied by rhodopic response function and converted
// to linear sRGB is [-0.321, 0.656, 0.455], i.e. out of gammut. We
// desaturate along red to mimic night vision color blindness
// (see https://github.com/eatdust/spectroll)
const vec4 nightColor = vec4(0.0,0.977,0.776,1.0);
vec3 filter_combined (in vec3 color) ;
float log10(in float x){
return 0.434294481903252*log(x);
}
//Rayleight + Mie scattering in unit of the minimal scattering at
//90 degrees (const f90)
float scattering_angular_dependency(in float cosMoonSep) {
float fR = 0.913514*(1.06 + cosMoonSep*cosMoonSep);
float moonSepRad = acos(cosMoonSep);
float fM = 5.63268*pow(10.0,-moonSepRad*1.432394);
return fR + fM;
}
float airmass_angular_dependency(in float sineZenithDistanceSquare) {
return 1.0/sqrt(1.0 - 0.96*sineZenithDistanceSquare);
}
//log10 of the moon illuminance in footcandles
float log10_moon_illuminance_fc(in float Inorm){
return (max_loglux-min_loglux)*(Inorm-1.0) + max_loglux + luxtofootcandle ;
}
//in mag/arcsec^2 from flux in nano Lambert
float magnitude_from_lognL(in float logBnL){
return 26.3313 - 2.5*logBnL;
}
void main()
{
//unit vectors
vec3 uViewDir = normalize(eye2VertInEyeSpace);
vec3 uZenithDir = normalize(eye2ZenithInEyeSpace);
vec3 uMoonDir = normalize(eye2MoonInEyeSpace);
// the intrinsic sky brightness without the Moon at
// zenith set in simgear and propagated as uniform
float muzenithsky = fg_ZenithSkyBrightness;
vec4 fragColor;
// the galaxy is visible only if
if (muzenithsky >= mugxybulge) {
// texture look-up
vec4 texel = texture2D(milkyway, gl_TexCoord[0].st);
float cosZenithView = max(dot(uZenithDir,uViewDir),0.0);
float sineZenithDist2 = 1.0 - pow(cosZenithView,2);
float Xview = airmass_angular_dependency(sineZenithDist2);
float k = k2800 * max(0.0,(atmosphere_top - altitude)/(atmosphere_top - 2800.0));
// add angular dependence from scattering within the atmosphere
float musky = muzenithsky + k*(Xview-1.0);
// main effect: airglow coming from the van Rhijn layer (height 130km)
//
// https://ui.adsabs.harvard.edu/abs/1986PASP...98..364G/abstract
//
// We smoothstep airglow to zero while approaching 130km of altitude
musky = musky - 2.5*log10(0.4+0.6*Xview) * (1.0 - smoothstep(0.0,130000.0,altitude));
// Moon illumination of the atmosphere, we use the same model as in
// simgear (see moonpos.cxx), based on Publ. Astron. Soc. Pacif.
// 103(667), 1033-1039 (DOI: http://dx.doi.org/10.1086/132921).
//
// https://ui.adsabs.harvard.edu/abs/1991PASP..103.1033K/abstract
//
// The altitude damping effect is encoded in k and the moon
// scattering smoothly disappears with altitude as k->0. Only smoothstep added to
// smooth the moon rising effects
float cosZenithMoon = dot(uZenithDir,uMoonDir);
float dmumoon = 0.0;
// Include values under the horizon to smooth the Moon rising jumps effect
if (cosZenithMoon >= cosUnvisible) {
//however, we use the math only with sane input: cosZenithMoon >= 0
float sineZenithMoon2 = 1.0 - pow(max(cosZenithMoon,0.0),2.0);
float Xmoon = airmass_angular_dependency(sineZenithMoon2);
float cosMoonView = dot(uMoonDir,uViewDir);
float moon_logI = log10_moon_illuminance_fc(moonlight);
// log10(Bmoon) with Bmoon in nanoLambert
float logBnL = logf90 + log10(scattering_angular_dependency(cosMoonView)) \
+ moon_logI - 0.4*k*Xmoon + log10(1.0-pow(10.0,-0.4*k*Xview));
// sky brightness from the moon in mag/arcsec^2
float mumoon = magnitude_from_lognL(logBnL);
//relative flux w.r.t background
float Brel = pow(10.0,0.4*(musky-mumoon));
// artificial smoothing for the moon between -18 degrees and 0
Brel = Brel*smoothstep(cosUnvisible,0.0,cosZenithMoon);
dmumoon = - 2.5*log10(1.0 + Brel);
}
// final angle dependent sky brightness
musky = musky + dmumoon;
// we put the damping in the colors as to keep alpha channel to 1
// for the ALS filters to not being affected
fragColor.rgb = texel.rgb * nightColor.rgb * (musky-mugxybulge)/musky;
fragColor.a = 1.0;
//For debugging and testing, uncomment. The red shows sky low surface brightness
//fragColor.r = 8*(musky-mugxybulge)/musky;
}
else {
// galaxy is invisible, too much sky brightness, color the night sphere is black
fragColor = vec4(0.0,0.0,0.0,1.0);
}
fragColor.rgb = filter_combined(fragColor.rgb);
gl_FragColor = clamp(fragColor,0.0,1.0);
}

29
Shaders/galaxy.vert Normal file
View file

@ -0,0 +1,29 @@
// -*-C++-*-
//
// Chris Ringeval (Novermber 2021)
//
#version 120
uniform vec3 fg_CameraWorldUp;
uniform mat4 osg_ViewMatrix;
varying vec3 eye2VertInEyeSpace;
varying vec3 eye2ZenithInEyeSpace;
varying vec3 eye2MoonInEyeSpace;
uniform vec3 fg_MoonDirection;
void main()
{
eye2VertInEyeSpace = (gl_ModelViewMatrix * gl_Vertex - vec4(0.0,0.0,0.0,1.0)).xyz;
eye2ZenithInEyeSpace = (osg_ViewMatrix * vec4(fg_CameraWorldUp,0.0)).xyz;
eye2MoonInEyeSpace = fg_MoonDirection;
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}

View file

@ -2,102 +2,260 @@
#version 120
uniform float air_pollution;
uniform int quality_level;
uniform float fogstructure;
uniform float cloud_self_shading;
uniform float scattering;
uniform float terminator;
uniform float terrain_alt;
uniform float overcast;
uniform float eye_alt;
// standard ALS fog function with exp(-d/D) fading and cutoff at low altitude and exp(-d^2/D^2) at high altitude
const float terminator_width = 200000.0;
const float EarthRadius = 5800000.0;
varying vec3 relPos;
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 worldPos;
float Noise2D(in vec2 coord, in float wavelength);
vec3 filter_combined (in vec3 color) ;
float Noise3D(in vec3 coord, in float wavelength);
const float AtmosphericScaleHeight = 8500.0;
// Development tools:
// Reduce haze to almost zero, while preserving lighting. Useful for observing distant tiles.
// Keeps the calculation overhead. This can be used for profiling.
// Possible values: 0:Normal, 1:Reduced haze.
const int reduce_haze_without_removing_calculation_overhead = 0;
// standard ALS fog function with exp(-d/D) fading and cutoff at low altitude and exp(-d^2/D^2) at high altitude
float fog_func (in float targ, in float alt)
{
float fade_mix;
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
// 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 * smoothstep(0.04,0.06,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)
{
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
{
} else {
return exp(- targ * targ - pow(targ,4.0));
}
}
// altitude correction for exponential drop in atmosphere density
float alt_factor(in float eye_alt, in float vertex_alt)
{
float h0 = AtmosphericScaleHeight;
float h1 = min(eye_alt,vertex_alt);
float h2 = max(eye_alt,vertex_alt);
if ((h2-h1) < 200.0) // use a Taylor-expanded version
{
return 0.5 * (exp(-h2/h0) + exp(-h1/h0));
}
else
{
} else {
return h0/(h2-h1) * (exp(-h1/h0) - exp(-h2/h0));
}
}
// Rayleigh in-scatter function
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt)
{
float fade_length = avisibility * (2.5 - 2.2 * sqrt(air_pollution));
fade_length = fade_length / alt_factor(eye_alt, vertex_alt);
return 1.0-exp(-dist/max(15000.0,fade_length));
}
// Rayleigh out-scattering color shift
vec3 rayleigh_out_shift(in vec3 color, in float outscatter)
{
color.r = color.r * (1.0 - 0.4 * outscatter);
color.g = color.g * (1.0 - 0.8 * outscatter);
color.b = color.b * (1.0 - 1.6 * outscatter);
return color;
}
// the generalized logistic function used to compute lightcurves
float light_curve (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));
}
// the haze color function
vec3 get_hazeColor(in float lightArg)
{
vec3 hazeColor;
hazeColor.r = light_curve(lightArg, 8.305e-06, 0.161, 4.827-3.0 *air_pollution, 3.04e-05, 1.0);
hazeColor.g = light_curve(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
hazeColor.b = light_curve(lightArg, 1.330e-05, 0.264, 1.527+ 2.0*air_pollution, 1.08e-05, 1.0);
return hazeColor;
}
// Apply the ALS haze model to a given fragment
vec4 applyHaze(inout vec4 fragColor,
inout vec3 hazeColor,
in vec3 secondary_light,
in float ct,
in float hazeLayerAltitude,
in float visibility,
in float avisibility,
in float dist,
in float lightArg,
in float mie_angle)
{
float mvisibility = min(visibility,avisibility);
if (dist > 0.04 * mvisibility)
{
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
float intensity;
float eShade;
float delta_z = hazeLayerAltitude - eye_alt;
float effective_scattering = min(scattering, cloud_self_shading);
float yprime_alt = light_diffuse_comp.a;
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
vec3 lightDir = gl_LightSource[0].position.xyz;
vec3 n = normal;
n = normalize(n);
// 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,mvisibility) * 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;
}
}
if ((quality_level > 4) && (abs(delta_z) < 400.0)) {
float blur_thickness = 50.0;
float cphi = dot(vec3(0.0, 1.0, 0.0), relPos)/dist;
float ctlayer = delta_z/dist-0.01 + 0.02 * Noise2D(vec2(cphi,1.0),0.1) -0.01;
float ctblur = 0.035 ;
float blur_dist;
blur_dist = dist * (1.0-smoothstep(0.0,300.0,-delta_z)) * smoothstep(-400.0,-200.0, -delta_z);
blur_dist = blur_dist * smoothstep(ctlayer-4.0*ctblur, ctlayer-ctblur, ct) * (1.0-smoothstep(ctlayer+0.5*ctblur, ctlayer+ctblur, ct));
distance_in_layer = max(distance_in_layer, blur_dist);
}
// 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 (quality_level > 3) {
float noise_1500m = Noise3D(worldPos.xyz, 1500.0);
float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * mvisibility + 1.0 * mvisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
} else {
transmission_arg = transmission_arg + (distance_in_layer/mvisibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/mvisibility - (1.0 - effective_scattering);
transmission = fog_func(transmission_arg, eye_alt);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
// now dim the light for haze
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
// Mie-like factor
if (lightArg < 10.0) {
intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
intensity = length(hazeColor);
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
{
// high altitude desaturation of the haze color
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* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
// reduce haze intensity when looking at shaded surfaces, only in terminator region
float shadow = mix( min(1.0 + dot(n,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));
}
// don't let the light fade out too rapidly
lightArg = (terminator + 200000.0)/100000.0;
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
hazeColor.rgb *= eqColorFactor * eShade;
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
// Testing phase controls
if (reduce_haze_without_removing_calculation_overhead == 1)
{
transmission = 1.0 - (transmission/1000000.0);
}
// finally, mix fog in
if (quality_level > 4) {
float backscatter = 0.5* min(1.0,10000.0/(mvisibility*mvisibility));
fragColor.rgb = mix(hazeColor+secondary_light * backscatter , fragColor.rgb,transmission);
} else {
fragColor.rgb = mix(clamp(hazeColor,0.0,1.0) , clamp(fragColor.rgb,0.0,1.0),transmission);
}
} // end if (dist > 0.04 * mvisibility)
fragColor.rgb = filter_combined(fragColor.rgb);
return fragColor;
}

21
Shaders/marker-pin.frag Normal file
View file

@ -0,0 +1,21 @@
// -*-C++-*-
#version 120
uniform sampler2D texture;
void main()
{
vec4 color = gl_Color;
// vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
vec4 texel;
vec4 fragColor;
texel = texture2D(texture, gl_TexCoord[0].st);
fragColor.rgb = color.rgb;
fragColor.a = texel.a * color.a;
gl_FragColor = fragColor;
}

18
Shaders/marker-pin.vert Normal file
View file

@ -0,0 +1,18 @@
// -*-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.
#version 120
void main()
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}

View file

@ -563,7 +563,10 @@ void main(void)
// add ice
vec4 ice_texel = texture2D(ice_texture, vec2(waterTex2) * 0.2 );
vec2 ice_tex_pos;
if (ocean_flag == 0) ice_tex_pos = gl_TexCoord[0].st * 0.1;
else ice_tex_pos = vec2(waterTex2) * 0.2;
vec4 ice_texel = texture2D(ice_texture, ice_tex_pos);
float nSum = 0.5 * (noise_250m + noise_50m);
float mix_factor = smoothstep(1.0 - ice_cover, 1.04-ice_cover, nSum);

View file

@ -87,6 +87,7 @@ void main(void)
mat4 RotationMatrix;
gl_TexCoord[0] = gl_MultiTexCoord0;
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
rawPos = (osg_ViewMatrixInverse *gl_ModelViewMatrix * gl_Vertex).xyz;

View file

@ -22,6 +22,9 @@
// Possible values: 0:Normal, 1:Just the texture.
const int remove_haze_and_lighting = 0;
// Use built-in water shader. Use for testing impact of ws30-water.frag
const int water_shader = 1;
//
// End of test phase controls
//////////////////////////////////////////////////////////////////
@ -43,7 +46,8 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos;
// Testing code:
//vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
@ -91,6 +95,7 @@ uniform vec4 fg_specularArray[128];
uniform vec4 fg_textureLookup1[128];
uniform vec4 fg_textureLookup2[128];
uniform vec4 fg_materialParams1[128];
uniform vec4 fg_materialParams3[128];
uniform mat4 fg_zUpTransform;
uniform vec3 fg_modelOffset;
@ -143,38 +148,74 @@ vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
// From noise.frag
float rand2D(in vec2 co);
// These functions, and other function they depend on, are defined
// in ws30-ALS-landclass-search.frag.
// Create random landclasses without a texture lookup to stress test.
// Each square of square_size in m is assigned a random landclass value.
int get_random_landclass(in vec2 co, in vec2 tile_size);
// End Test-phase code
////////////////////////
// These functions, and other function they depend on, are defined
// in ws30-ALS-landclass-search.frag.
// Lookup a ground texture at a point based on the landclass at that point, without visible
// seams at coordinate discontinuities or at landclass boundaries where texture are switched.
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
// the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams.
// Texture types: 0: base texture, 1: grain texture, 2: gradient texture, 3 dot texture,
// 4: mix texture, 5: detail texture.
vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy);
vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec4 dFdx_and_dFdy);
// Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance.
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
// Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
// Create a mix factor weighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor
);
// End Test-phase code
////////////////////////
// Look up the texel of the specified texture type (e.g. grain or detail textures) for this fragment
// and any neighbor texels, then mix.
vec4 get_mixed_texel(in int texture_type, in vec2 g_texture_coord,
in int landclass_id, in int num_unique_neighbors,
in ivec4 neighbor_texel_landclass_ids, in vec4 neighbor_mix_factors,
in vec4 dFdx_and_dFdy
);
// Determine the texel and material parameters for a particular fragment,
// Taking into account photoscenery etc.
void get_material(in int landclass,
in vec2 ground_tex_coord,
in vec4 dxdy_gc,
out float mat_shininess,
out vec4 mat_ambient,
out vec4 mat_diffuse,
out vec4 mat_specular,
out vec4 dxdy,
out vec2 st
);
// Apply the ALS haze model to a specific fragment
vec4 applyHaze(inout vec4 fragColor,
inout vec3 hazeColor,
in vec3 secondary_light,
in float ct,
in float hazeLayerAltitude,
in float visibility,
in float avisibility,
in float dist,
in float lightArg,
in float mie_angle);
// Procedurally generate a water texel for this fragment
vec4 generateWaterTexel();
void main()
{
@ -191,6 +232,8 @@ float dist = length(relPos);
// angle of view vector with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
// Altitude of fragment above sea level
float msl_altitude = (relPos.z + eye_alt);
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
@ -208,6 +251,10 @@ float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
vec4 specular = vec4(0.0);
float intensity;
// Material/texel properties
float mat_shininess;
vec2 st;
vec4 mat_ambient, mat_diffuse, mat_specular, dxdy;
// get noise at different wavelengths
@ -270,88 +317,30 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
vec4 mfact;
const float landclass_texel_size_m = 25.0;
// Partial derivatives of s and t for this fragment,
// Partial derivatives of s and t of ground texture coords for this fragment,
// with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord);
vec2 dy = dFdy(tile_coord);
get_landclass_id(tile_coord, landclass_texel_size_m, dx, dy,
lc, lc_n, num_unique_neighbors, mfact);
// The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as
// defined in the regional definitions
float index = float(lc)/512.0;
vec4 index_n = vec4(lc_n)/512.0;
float mat_shininess = fg_dimensionsArray[lc].z;
vec4 mat_ambient = fg_ambientArray[lc];
vec4 mat_diffuse = fg_diffuseArray[lc];
vec4 mat_specular = fg_specularArray[lc];
vec2 st = gl_TexCoord[0].st;
// Testing code:
// Use rlc even when looking up textures to recreate the extra performance hit
// so any performance difference between the two is due to the texture lookup
// color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
// dFdx and dFdy are packed in a vec4 so multiplying everything
// to scale takes 1 instruction slot.
vec4 dxdy_gc = vec4(dFdx(ground_tex_coord) , dFdy(ground_tex_coord));
get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
get_material(lc, ground_tex_coord, dxdy_gc, mat_shininess, mat_ambient, mat_diffuse, mat_specular, dxdy, st);
if (fg_photoScenery) {
// In the photoscenery case we don't have landclass or materials available, so we
// just use constants for the material properties.
mat_ambient = vec4(0.2,0.2,0.2,1.0);
mat_diffuse = vec4(0.8,0.8,0.8,1.0);
mat_specular = vec4(0.0,0.0,0.0,1.0);
texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t));
} else {
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray.
mat_ambient = vec4(1.0,1.0,1.0,1.0);
mat_diffuse = vec4(1.0,1.0,1.0,1.0);
mat_specular = fg_specularArray[lc];
mat_shininess = fg_dimensionsArray[lc].z;
// Different textures have different have different dimensions.
vec2 atlas_dimensions = fg_dimensionsArray[lc].st;
vec2 atlas_scale = vec2(fg_tileWidth / atlas_dimensions.s, fg_tileHeight / atlas_dimensions.t );
st = atlas_scale * gl_TexCoord[0].st;
// Look up ground textures by indexing into the texture array.
// Different textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters
// Look up texture coordinates and scale of ground textures
// Landclass for this fragment
texel = lookup_ground_texture_array(tile_coord, lc, dx, dy);
// Mix texels - to work consistently it needs a more preceptual interpolation than mix()
if (num_unique_neighbors != 0)
{
// Closest neighbor landclass
vec4 texel_closest = lookup_ground_texture_array(tile_coord, lc_n[0], dx, dy);
// Neighbor contributions
vec4 texel_nc=texel_closest;
if (num_unique_neighbors > 1)
{
// 2nd Closest neighbor landclass
vec4 texel_2nd_closest = lookup_ground_texture_array(tile_coord, lc_n[1],
dx, dy);
texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]);
}
texel = mix(texel, texel_nc, mfact[0]);
}
// Lookup the base texture texel for this fragment and any neighbors, with mixing
texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
}
if ((water_shader == 1) && (fg_photoScenery == false) && fg_materialParams3[lc].x > 0.5) {
// This is a water fragment, so calculate the fragment color procedurally
fragColor = generateWaterTexel();
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, fragColor.rgb);
} else {
// Photoscenery or land fragment, so determine the shading and color normally
vec4 color = gl_Color * mat_ambient;
color.a = 1.0;
@ -359,6 +348,9 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
//vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
//texel = mix(texel, green, (mfact[2]));
//mix_texel = texel;
//detail_texel = texel;
vec4 t = texel;
int flag = 1;
int mix_flag = 1;
@ -378,7 +370,7 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
//float view_angle = abs(dot(normal, normalize(ecViewdir)));
if ((quality_level > 3)&&(rawPos.z +500.0 > snowlevel)) {
if ((quality_level > 3)&&(msl_altitude +500.0 > snowlevel)) {
float sfactor;
snow_texel = vec4 (0.95, 0.95, 0.95, 1.0) * (0.9 + 0.1* noise_500m + 0.1* (1.0 - noise_10m) );
snow_texel.r = snow_texel.r * (0.9 + 0.05 * (noise_10m + noise_5m));
@ -393,15 +385,19 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
noise_term = noise_term + 0.3 * (noise_5m -0.5) * (1.0 - smoothstep(1000.0 * sfactor, 3000.0 *sfactor, dist) );
}
snow_texel.a = snow_texel.a * 0.2+0.8* smoothstep(0.2,0.8, 0.3 +noise_term + snow_thickness_factor +0.0001*(rawPos.z -snowlevel) );
snow_texel.a = snow_texel.a * 0.2+0.8* smoothstep(0.2,0.8, 0.3 +noise_term + snow_thickness_factor +0.0001*(msl_altitude -snowlevel) );
}
if ((tquality_level > 2) && (mix_flag == 1))
{
// Mix texture is material texture 15, which is mapped to the b channel of fg_textureLookup1
int tex2 = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
//int tex2 = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
//mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
if (mix_texel.a < 0.1) { mix_flag = 0;}
//WS2: mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3); // temp
mix_texel = lookup_ground_texture_array(4, st * 1.3, lc, dxdy * 1.3);
if (mix_texel.a <0.1) {mix_flag = 0;}
}
@ -417,9 +413,13 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
}
// Detail texture is material texture 11, which is mapped to the g channel of fg_textureLookup1
int tex3 = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
detail_texel = texture(textureArray, vec3(stprime, tex3));
//int tex3 = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
//detail_texel = texture(textureArray, vec3(stprime, tex3));
if (detail_texel.a < 0.1) { flag = 0;}
//WS2: detail_texel = texture2D(detail_texture, stprime); // temp
vec4 dxdy_prime = vec4(dFdx(stprime), dFdy(stprime));
detail_texel = lookup_ground_texture_array(5, stprime, lc, dxdy_prime);
}
// texture preparation according to detail level
@ -505,18 +505,18 @@ if (quality_level > 3)
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
// mix snow
if (rawPos.z +500.0 > snowlevel)
if (msl_altitude +500.0 > snowlevel)
{
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
//texel = mix(texel, snow_texel, texel_snow_fraction);
texel = mix(texel, snow_texel, snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (rawPos.z)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
texel = mix(texel, snow_texel, snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (msl_altitude)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
}
}
else if (rawPos.z +500.0 > snowlevel)
else if (msl_altitude +500.0 > snowlevel)
{
float snow_alpha = 0.5+0.5* smoothstep(0.2,0.8, 0.3 + snow_thickness_factor +0.0001*(rawPos.z -snowlevel) );
float snow_alpha = 0.5+0.5* smoothstep(0.2,0.8, 0.3 + snow_thickness_factor +0.0001*(msl_altitude -snowlevel) );
// texel = vec4(dot(vec3(0.2989, 0.5870, 0.1140), texel.rgb));
texel = mix(texel, vec4(1.0), snow_alpha* smoothstep(snowlevel, snowlevel+200.0, (rawPos.z)));
texel = mix(texel, vec4(1.0), snow_alpha* smoothstep(snowlevel, snowlevel+200.0, (msl_altitude)));
}
@ -577,185 +577,13 @@ if ((dist < 5000.0)&& (quality_level > 3) && (wetness>0.0))
// is closer to what the OpenGL fixed function pipeline does.
color = clamp(color, 0.0, 1.0);
fragColor = color * texel + specular;
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, texel.rgb);
// here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt;
if (dist > 0.04 * min(visibility,avisibility))
//if ((gl_FragCoord.y > ylimit) || (gl_FragCoord.x < zlimit1) || (gl_FragCoord.x > zlimit2))
//if (dist > 40.0)
{
alt = eye_alt;
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
// 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;
if (visibility < avisibility)
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering);
}
else
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
}
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 - effective_scattering);
}
transmission = fog_func(transmission_arg, alt);
// 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 = get_hazeColor(lightArg);
// now dim the light for haze
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
// Mie-like factor
if (lightArg < 10.0)
{
intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
intensity = length(hazeColor);
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
{
// high altitude desaturation of the haze color
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* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
// reduce haze intensity when looking at shaded surfaces, only in terminator region
float shadow = mix( min(1.0 + dot(n,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));
// don't let the light fade out too rapidly
lightArg = (terminator + 200000.0)/100000.0;
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
hazeColor *= eqColorFactor * eShade;
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
}
// Testing phase controls
if (reduce_haze_without_removing_calculation_overhead == 1)
{
transmission = 1.0 - (transmission/1000000.0);
}
fragColor.rgb = mix(clamp(hazeColor,0.0,1.0) , clamp(fragColor.rgb,0.0,1.0),transmission);
}
fragColor.rgb = filter_combined(fragColor.rgb);
gl_FragColor = fragColor;
gl_FragColor = applyHaze(fragColor, hazeColor, vec3(0.0), ct, hazeLayerAltitude, visibility, avisibility, dist, lightArg, mie_angle);
// Testing phase controls:

View file

@ -25,10 +25,12 @@ attribute vec2 orthophotoTexCoord;
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos;
//varying vec2 orthoTexCoord;
varying vec4 eyePos;
varying vec4 ecPosition;
// Sent packed into alpha channels
//varying float yprime_alt;
@ -36,6 +38,19 @@ varying float mie_angle;
varying float steepness;
// For water calculations
varying float earthShade;
varying vec3 lightdir;
varying vec4 waterTex1;
varying vec4 waterTex2;
varying vec4 waterTex4;
varying vec3 specular_light;
uniform float osg_SimulationTime;
uniform float WindN;
uniform float WindE;
uniform int colorMode;
uniform float hazeLayerAltitude;
uniform float terminator;
@ -55,7 +70,6 @@ uniform mat4 osg_ViewMatrixInverse;
uniform mat4 fg_zUpTransform;
uniform vec3 fg_modelOffset;
float earthShade;
float yprime_alt;
//float mie_angle;
@ -77,6 +91,14 @@ if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
void createRotationMatrix(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()
{
@ -95,7 +117,7 @@ void main()
float vertex_alt;
float scattering;
rawPos = (fg_zUpTransform * gl_Vertex).xyz;
rawPos = (fg_zUpTransform * gl_Vertex).xy;
worldPos = fg_modelOffset + gl_Vertex.xyz;
eyePos = gl_ModelViewMatrix * gl_Vertex;
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
@ -104,12 +126,16 @@ void main()
// this code is copied from default.vert
//vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
ecPosition = gl_ModelViewMatrix * gl_Vertex;
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//orthoTexCoord = orthophotoTexCoord;
normal = gl_NormalMatrix * gl_Normal;
//nvec = (gl_NormalMatrix * gl_Normal).xy;
// Temporary value:
ground_tex_coord = gl_TexCoord[0].st;
// here start computations for the haze layer
// we need several geometrical quantities
@ -126,9 +152,29 @@ void main()
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(rawPos.z,100.0);
vertex_alt = max(relPos.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// Required for water calculations
lightdir = normalize(vec3(fg_zUpTransform * vec4(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(WindE * WindE + WindN * WindN) * 0.05;
if (WindN == 0.0 && WindE == 0.0) {
Angle = 0.0;
} else {
Angle = atan(-WindN, WindE) - atan(1.0);
}
mat4 RotationMatrix;
createRotationMatrix(Angle, RotationMatrix);
waterTex1 = gl_MultiTexCoord0 * RotationMatrix - t1 * windFactor;
waterTex2 = gl_MultiTexCoord0 * RotationMatrix - t2 * windFactor;
// early culling of vertices which can't be seen due to ground haze despite being in aloft visibility range
@ -193,6 +239,14 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
light_ambient.b = light_ambient.r * 0.5/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.5);
light_ambient.a = 1.0;
// Water specular calculations
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 = max(specular_light * scattering, vec3 (0.05, 0.05, 0.05));
intensity = length(specular_light.rgb);
specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.6,ground_scattering) ));
specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.5, 0.7,earthShade)));
@ -207,6 +261,13 @@ if (earthShade < 0.5)
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) ));
}
// directional scattering for low sun
if (lightArg < 10.0) {
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
@ -237,7 +298,9 @@ else // the faster, full-day version without lightfields
if (terminator > 3000000.0)
{light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0); }
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0);
specular_light = vec3 (1.0, 1.0, 1.0);
}
else
{
@ -253,9 +316,16 @@ else // the faster, full-day version without lightfields
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.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;
}
light_diffuse = light_diffuse * scattering;
specular_light = specular_light * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
@ -271,6 +341,7 @@ float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smooth
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
specular_light.rgb *= (1.0 + 1.2 * shade_depth);
if (use_IR_vision)
{

View file

@ -110,7 +110,7 @@
// Enable large scale transitions: 1=on, 0=off
// Disable use landclass texel scale transition, if using this.
const int enable_large_scale_transition_search = 0;
const int enable_large_scale_transition_search = 1;
// The search pattern is center + n points in four directions forming a cross.
@ -124,7 +124,7 @@
// Note: transitions occur on both sides of the landclass borders.
// The width of the transition is equal to 2x this value.
// Default: 100m
const float transition_search_distance_in_m = 100.0;
const float transition_search_distance_in_m = 25.0;
// Number of points to search in any direction, in addition to this fragment
// Default:4 points. Fewer points results in a less smooth transition (more banding)
@ -158,8 +158,11 @@
// This works by changing the weighting in the transition region using a
// noise lookup
// Possibe values: 0=off, 1=on. Default:0
const int grow_landclass_borders_with_large_scale_transition = 0;
const int grow_landclass_borders_with_large_scale_transition = 1;
// Use the edge-hardness parameter from materials.xml to determine
// weighting of the landclass in transitions
const int use_edge_hardness_with_large_scale_transition = 1;
//////////////////////////////////////////////////////////////////
@ -181,7 +184,7 @@
// Possible values: 0 = texture source, 1 = math source
// The texture source still shows some tiling. The math source detiles better, but might
// be slightly slower.
const int detiling_noise_type = 0;
const int detiling_noise_type = 1;
// Development tools - 2 controls, now located at the top of WS30-ALS-ultra.frag:
// 1. Reduce haze to almost zero, while preserving lighting. Useful for observing distant tiles.
@ -190,6 +193,15 @@
// Useful for checking texture rendering and scenery.
// The compiler will likely optimise out the haze and lighting calculations.
//
// Debugging: ground texture array lookup function
// Possible values:
// 0: Normal: TextureGrad() with partial derivatives. GLSL 1.30.
// 1: textureLod() using partial derivatives to manually calculate LoD. GLSL 1.20
// 2: texture() without partial derivatives. GLSL 1.20
const int tex_lookup_type = 0;
//
// End of test phase controls
//////////////////////////////////////////////////////////////////
@ -225,6 +237,7 @@
// Uniforms used by landclass search functions.
// If any uniforms change name or form, remember to update here and in fragment shaders.
uniform sampler2D landclass;
uniform sampler2DArray textureArray;
uniform sampler2D perlin;
@ -253,6 +266,33 @@ vec2 tile_size = vec2(fg_tileHeight , fg_tileWidth);
float rand2D(in vec2 co);
float Noise2D(in vec2 coord, in float wavelength);
// Generates a full precision 32 bit random number from 2 seeds
// as well as 6 random integers between 0 and factor that are rescaled 0.0-1.0
// by re-using the significant figures from the full precision number.
// This avoids having to generate 6 random numbers when
// limited variation is needed: say 6 numbers with 100 levels (i.e between 0 and 100).
// Seed 2 is incremented so the function can be called again to generate
// a different set of numbers
float get6_rand_nums(in float PRNGseed1, inout float PRNGseed2, float factor, out float [6] random_integers)
{
float r = fract(sin(dot(vec2(PRNGseed1,PRNGseed2),vec2(12.9898,78.233))) * 43758.5453);
// random number left over after extracting some decimal places
float rlo = r;
// To look at: can this be made simd friendly?
for (int i=0;i<6;i++)
{
rlo = (rlo*factor);
random_integers[i] = floor(rlo)/factor;
rlo = fract(rlo);
}
PRNGseed2+=1.0;
return r;
}
// Create random landclasses without a texture lookup to stress test.
// Each square of square_size in m is assigned a random landclass value.
int get_random_landclass(in vec2 co, in vec2 tile_size)
@ -263,17 +303,32 @@ int get_random_landclass(in vec2 co, in vec2 tile_size)
}
// Look up texture coordinates and stretching scale of ground textures
/*
// Look up stretching scale of ground textures for the base texture.
// Note terrain default effect only has controls for the texture stretching dimensions for the base texture.
// Non-base textures use hardcoded stretching of the ground texture coords, which are in units of meters.
vec2 get_ground_texture_scale(in int lc)
{
// Look up stretching dimensions of ground textures in m - scaled to
// fit in [0..1], so rescale
vec2 g_texture_stretch_dim = fg_dimensionsArray[lc].st;
return (tile_size.xy / g_texture_stretch_dim.xy);
}
*/
// Look up texture coordinates and stretching scale of ground textures for the base texture.
// Note terrain default effect only has controls for the texture stretching dimensions for the base texture.
// Non-base textures use hardcoded stretching of the ground texture coords, which are in units of meters.
void get_ground_texture_data(in int lc, in vec2 tile_coord,
out vec2 st, out vec2 g_texture_scale, inout vec2 dx, inout vec2 dy)
out vec2 st, out vec2 g_texture_scale, inout vec4 dFdx_and_dFdy)
{
// Look up stretching dimensions of ground textures in m - scaled to
// fit in [0..1], so rescale
vec2 g_texture_stretch_dim = fg_dimensionsArray[lc].st;
g_texture_scale = tile_size.xy / g_texture_stretch_dim.xy;
// Correct partial derivatives to account for stretching of different textures
dx = dx * g_texture_scale;
dy = dy * g_texture_scale;
dFdx_and_dFdy = dFdx_and_dFdy * vec4(g_texture_scale.st, g_texture_scale.st);
// Ground texture coords
st = g_texture_scale * tile_coord.st;
}
@ -284,10 +339,12 @@ void get_ground_texture_data(in int lc, in vec2 tile_coord,
// Testing: if this or get_ground_texture_data used in final WS3 to handle
// many base texture lookups, see if optimising to handle many inputs helps
// (vectorising Noise2D versus just many texture calls)
// To do: adjust for non-tile based ground coords.
vec2 detile_texcoords_with_perlin_noise(in vec2 st, in vec2 ground_texture_scale,
in vec2 tile_coord, inout vec2 dx, inout vec2 dy)
in vec2 tile_coord, inout vec4 dFdx_and_dFdy)
{
vec4 dxdy = dFdx_and_dFdy;
vec2 pnoise;
// Ratio tile dimensions are stretched relative to s.
@ -315,21 +372,25 @@ vec2 detile_texcoords_with_perlin_noise(in vec2 st, in vec2 ground_texture_scale
if (pnoise[0] >= 0.5)
{
// To do: fix once ground coords are no longer tile based
st = ground_texture_scale.st * (tile_coord * stretch_r).ts;
// Get back original partial derivatives by undoing
// previous texture stretching adjustment done in get_ground_data
dx = dx / ground_texture_scale.st;
dy = dy / ground_texture_scale.st;
dxdy = dxdy / vec4(ground_texture_scale.st, ground_texture_scale.st);
// Recalculate new derivatives
dx = dx.ts * ground_texture_scale.st * stretch_r.ts;
dy = dy.ts * ground_texture_scale.st * stretch_r.ts;
vec2 factor = ground_texture_scale.st * stretch_r.ts;
dxdy.st = dxdy.ts * factor;
dxdy.pq = dxdy.qp * factor;
}
if (pnoise[1] >= 0.5)
{
st = -st; dx = -dx; dy = -dy;
st = -st; dxdy = -dxdy;
}
dFdx_and_dFdy = dxdy;
return st;
}
@ -339,38 +400,130 @@ vec2 detile_texcoords_with_perlin_noise(in vec2 st, in vec2 ground_texture_scale
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
// the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams.
// Texture types: 0: base texture, 1: grain texture, 2: gradient texture, 3 dot texture,
// 4: mix texture, 5: detail texture.
vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id,
in vec2 dx, in vec2 dy)
vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec4 dFdx_and_dFdy)
{
// Testing: may be able to save 1 or 2 op slots by combining dx/dy in a vec4 and
// using swizzles which are free, but mostly operations are working independenly on s and t.
// Only 1 place so far that just multiplies everything by a scalar.
vec2 st;
vec2 g_tex_coord = ground_texture_coord;
vec2 g_texture_scale;
vec4 texel;
int lc = landclass_id;
vec4 dxdy = dFdx_and_dFdy;
get_ground_texture_data(lc, tile_coord, st, g_texture_scale, dx, dy);
// Find the index of the specified texture type (e.g. mix or gradient texture ) in
// the ground texture lookup array.
// Since texture_type is a constant in the fragment shader, there should be no performance hit for branching.
int tex_idx = 0;
int type = texture_type;
// Index for the base texture is contained fg_textureLookup1[lc].r
if (type == 0) tex_idx = int(uint(fg_textureLookup1[lc].r * 255.0 + 0.5));
// Grain texture is material texture slot 14, the index of which is mapped to the r channel of fg_textureLookup2
else if (type == 1) tex_idx = int(fg_textureLookup2[lc].r * 255.0 + 0.5);
// Gradient texture is material texture 13, the index of which is mapped to the a channel of fg_textureLookup1
else if (type == 2) tex_idx = int(fg_textureLookup1[lc].a * 255.0 + 0.5);
// Dot texture is material texture 15, the index of which is mapped to the g channel of fg_textureLookup2
else if (type == 3) tex_idx = int(fg_textureLookup2[lc].g * 255.0 + 0.5);
// Mix texture is material texture 12, the index of which is mapped to the b channel of fg_textureLookup1
else if (type == 4) tex_idx = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
// Detail texture is material texture 11, the index of which is mapped to the g channel of fg_textureLookup1
else if (type == 5) tex_idx = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
st = detile_texcoords_with_perlin_noise(st, g_texture_scale, tile_coord, dx, dy);
if (type == 0)
{
// Scale normalised tile coords by stretching factor, and get info
vec2 tile_coord = g_tex_coord;
get_ground_texture_data(lc, tile_coord, st, g_texture_scale, dxdy);
st = detile_texcoords_with_perlin_noise(st, g_texture_scale, tile_coord, dxdy);
}
else
{
st = g_tex_coord;
}
//texel = texture(textureArray, vec3(st, lc));
//texel = textureLod(textureArray, vec3(st, lc), 12.0);
uint tex1 = uint(fg_textureLookup1[lc].r * 255.0 + 0.5);
texel = textureGrad(textureArray, vec3(st, tex1), dx, dy);
// Debugging: multiple texture lookup functions if there are issues
// with old GPUs and compilers.
if (tex_lookup_type == 0)
{
texel = textureGrad(textureArray, vec3(st, tex_idx), dxdy.st, dxdy.pq);
}
else if (tex_lookup_type == 1)
{
float lod = max(length(dxdy.sp), length(dxdy.tq));
lod = log2(lod);
texel = textureLod(textureArray, vec3(st, tex_idx), lod);
}
else texel = texture(textureArray, vec3(st, tex_idx));
//texel = textureGrad(textureArray, vec3(st, tex_idx), dxdy.st, dxdy.pq);
return texel;
}
// Look up the texel of the specified texture type (e.g. grain or detail textures) for this fragment
// and any neighbor texels, then mix.
vec4 get_mixed_texel(in int texture_type, in vec2 g_texture_coord,
in int landclass_id, in int num_unique_neighbors,
in ivec4 neighbor_texel_landclass_ids, in vec4 neighbor_mix_factors,
in vec4 dFdx_and_dFdy
)
{
vec2 st = g_texture_coord;
int lc = landclass_id;
ivec4 lc_n = neighbor_texel_landclass_ids;
// Not implemented yet
int type = texture_type;
vec4 dxdy = dFdx_and_dFdy;
vec4 mfact = neighbor_mix_factors;
vec4 texel = lookup_ground_texture_array(0, st, lc, dxdy);
// Mix texels - to work consistently it needs a more preceptual interpolation than mix()
if (num_unique_neighbors != 0)
{
// Closest neighbor landclass
vec4 texel_closest = lookup_ground_texture_array(0, st, lc_n[0], dxdy);
// Neighbor contributions
vec4 texel_nc=texel_closest;
if (num_unique_neighbors > 1)
{
// 2nd Closest neighbor landclass
vec4 texel_2nd_closest = lookup_ground_texture_array(0, st, lc_n[1], dxdy);
texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]);
}
texel = mix(texel, texel_nc, mfact[0]);
}
return texel;
}
// Landclass sources: texture or random
int read_landclass_id(in vec2 tile_coord)
{
vec2 dx = dFdx(tile_coord.st);
vec2 dy = dFdy(tile_coord.st);
int lc;
if (landclass_source == 0) lc = (int(texture2D(landclass, tile_coord.st).r * 255.0 + 0.5));
if (landclass_source == 0) lc = (int(texture2D(landclass, tile_coord.st).g * 255.0 + 0.5));
else lc = (get_random_landclass(tile_coord.st, tile_size));
return lc;
}
@ -411,13 +564,14 @@ float get_growth_priority(in int current_landclass, in int neighbor_landclass1,
}
int lookup_landclass_id(in vec2 tile_coord, in vec2 dx, in vec2 dy,
int lookup_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out ivec4 neighbor_texel_landclass_ids,
out int number_of_unique_neighbors_found, out vec4 landclass_neighbor_texel_weights)
{
// To do: fix landclass border artifacts, with all shaders. do small scale texel mixing for 2 neighbors
// To do: fix landclass border artifacts, with all shaders.
vec4 dxdy = dFdx_and_dFdy;
// Number of unique neighbours found
int num_n = 0;
@ -622,7 +776,9 @@ if (remove_squareness_from_landclass_texture == 1)
// Turn neighbor growth off at longer ranges, otherwise there is flickering noise
// Testing: The exact cutoff could be done sooner to save some performance - needs
// to be part of a larger solution to similar issues. User should set a tolerance factor.
float lod_factor = min(length(vec2(dx.s, dy.s)),length(vec2(dx.t, dy.t)));
// Effectively: lod_factor = min(length(vec2(dFdx(..).s, dFdy(..).s)),length(vec2(dFdx(..).t, dFdy(..).t)));
float lod_factor = min(length(vec2(dxdy.s, dxdy.p)),length(vec2(dxdy.t, dxdy.q)));
// Estimate of frequency of growth noise in texels - i.e. how many peaks and troughs fit in one texel
const float frequency_g_n = 1000.0;
const float cutoff = 1.0/frequency_g_n;
@ -732,19 +888,20 @@ if ( (use_landclass_texel_scale_transition_only == 1) &&
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
// Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor
)
{
// Each tile has 1 texture containing landclass ids stetched over it
// Landclass source type: 0=texture, 1=random squares
// Controls are defined at global scope. const int landclass_source
float ts = landclass_texel_size_m;
// Controls are defined at global scope.
vec2 sz = tile_size;
vec4 dxdy = dFdx_and_dFdy;
// Number of unique neighbors found
int num_n = 0;
@ -756,7 +913,12 @@ void get_landclass_id(in vec2 tile_coord,
// Number of unique neighbors in neighboring texels
int num_n_tx = 0;
int lc = lookup_landclass_id(tile_coord, dx, dy, lc_n_tx, num_n_tx, lc_n_w);
int lc = lookup_landclass_id(tile_coord, dxdy, lc_n_tx, num_n_tx, lc_n_w);
float edge_hardness = 0.0;
if (use_edge_hardness_with_large_scale_transition == 1) {
edge_hardness = fg_dimensionsArray[lc].a;
}
// Neighbor landclass ids
ivec4 lc_n = ivec4(lc);
@ -791,13 +953,14 @@ if ( (enable_large_scale_transition_search == 1) &&
// Transition search
const int n = num_search_points_in_a_direction;
const float search_dist = transition_search_distance_in_m;
vec2 step_size_m = vec2(search_dist/float(n));
// step size in tile coords
vec2 steps = step_size_m.st / tile_size.st;
// step size in tile coords. Modulated by the edge hardness which makes
// the step size smaller and hence the range of adjacent landclasses
// smaller.
vec2 steps = step_size_m.st / tile_size.st * (1.0 - edge_hardness);
vec2 c0 = tile_coord;
@ -818,6 +981,11 @@ if ( (enable_large_scale_transition_search == 1) &&
// landclass.
// Testing: breaking the loop once the closest neighbour is found
// results in very slightly lower FPS on a 10 series GPU for 100m search
// distance and 4 points. May be faster on old GPUs with slow caching.
// +s direction
vec2 dir = vec2(steps.s, 0.0);
@ -982,7 +1150,7 @@ if (grow_landclass_borders_with_large_scale_transition == 1)
// Decide whether to extrude furthest neighbor or closest neighbor onto lc
float grow_n1 = get_growth_priority(lc_n[0],lc_n[1]);
mfact[1] = mfact[1]+((grow_n > 0.0)?neighbor_growth_mixf:+neighbor_growth_mixf);
mfact[1] = mfact[1]+((grow_n > 0.0)?neighbor_growth_mixf:-neighbor_growth_mixf);
mfact[1] = clamp(mfact[1],0.0,1.0);
@ -1006,3 +1174,46 @@ if (grow_landclass_borders_with_large_scale_transition == 1)
// End Test-phase code
////////////////////////
// Determine the texel and material parameters for a particular fragment,
// Taking into account photoscenery etc.
void get_material(in int landclass,
in vec2 ground_tex_coord,
in vec4 dxdy_gc,
out float mat_shininess,
out vec4 mat_ambient,
out vec4 mat_diffuse,
out vec4 mat_specular,
out vec4 dxdy,
out vec2 st
)
{
// Calculate texture coords for ground textures
// Textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters.
vec2 stretch_dimensions = fg_dimensionsArray[landclass].st;
vec2 tileSize = vec2(fg_tileWidth, fg_tileHeight);
vec2 texture_scaling = tileSize.yx / stretch_dimensions.st;
st = texture_scaling.st * ground_tex_coord.st;
// Scale partial derivatives
dxdy = vec4(texture_scaling.st, texture_scaling.st) * dxdy_gc;
if (fg_photoScenery) {
// In the photoscenery case we don't have landclass or materials available, so we
// just use constants for the material properties.
mat_ambient = vec4(0.2,0.2,0.2,1.0);
mat_diffuse = vec4(0.8,0.8,0.8,1.0);
mat_specular = vec4(0.0,0.0,0.0,1.0);
mat_shininess = 1.2;
} else {
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray.
mat_ambient = vec4(1.0,1.0,1.0,1.0);
mat_diffuse = vec4(1.0,1.0,1.0,1.0);
mat_specular = fg_specularArray[landclass];
mat_shininess = fg_dimensionsArray[landclass].z;
}
}

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,6 @@
#define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2
//attribute vec2 orthophotoTexCoord;
// The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha
@ -25,12 +24,25 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos;
varying vec3 ecViewdir;
varying vec2 grad_dir;
//varying vec2 orthoTexCoord;
varying vec4 ecPosition;
varying vec3 vertVec;
// For water calculations
varying float earthShade;
varying vec3 lightdir;
varying vec4 waterTex1;
varying vec4 waterTex2;
varying vec4 waterTex4;
varying vec3 specular_light;
uniform float osg_SimulationTime;
uniform float WindN;
uniform float WindE;
// Sent packed into alpha channels
//varying float yprime_alt;
@ -60,7 +72,6 @@ uniform mat4 osg_ViewMatrixInverse;
uniform mat4 fg_zUpTransform;
uniform vec3 fg_modelOffset;
float earthShade;
float yprime_alt;
vec3 moonlight_perception (in vec3 light);
@ -77,13 +88,18 @@ 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 createRotationMatrix(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()
{
@ -103,12 +119,18 @@ void main()
float vertex_alt;
float scattering;
rawPos = (fg_zUpTransform * gl_Vertex).xyz;
worldPos = fg_modelOffset + gl_Vertex.xyz;
// The ALS code assumes that units are in meters - e.g. model space vertices (gl_Vertex) are in meters
// WS30 model space, Nov 21, 2021:
// Coordinate axes are the same for geocentric, but not the origin.
// +z direction points from the Earth center to North pole.
// +x direction points from the Earth center to longitude = 0 on the equator.
// +y direction points from the Earth center to logntitude = East on the equator.
// Model space origin is at sea level. Units are in meters.
// Each tile, for each LoD level, its own model origin
// modelOffset is the model origin relative to the Earth center. It is in a geocentric
// space with the same axes, but with the Earth center as the origin. Units are in meters.
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
grad_dir = normalize(gl_Normal.xy);
vec4 pos = gl_Vertex;
if (raise_vertex)
@ -124,25 +146,111 @@ void main()
ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//orthoTexCoord = orthophotoTexCoord;
normal = gl_NormalMatrix * gl_Normal;
// Required for water calculations
lightdir = normalize(vec3(fg_zUpTransform * vec4(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(WindE * WindE + WindN * WindN) * 0.05;
if (WindN == 0.0 && WindE == 0.0) {
Angle = 0.0;
} else {
Angle = atan(-WindN, WindE) - atan(1.0);
}
mat4 RotationMatrix;
createRotationMatrix(Angle, RotationMatrix);
waterTex1 = gl_MultiTexCoord0 * RotationMatrix - t1 * windFactor;
waterTex2 = gl_MultiTexCoord0 * RotationMatrix - t2 * windFactor;
///////////////////////////////////////////
// Test phase code:
//
// Coords for ground textures
// Due to precision issues coordinates should restart (i.e. go to zero) every 5000m or so.
const float restart_dist_m = 5000.0;
// Model position
vec3 mp = gl_Vertex.xyz;
// Temporary approximation to get shaders to compile:
ground_tex_coord = gl_TexCoord[0].st;
//
// End test phase code
///////////////////////////////////////////
// WS2:
// 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;
// Transform for frame of reference where:
// +z is in the up direction.
// The orientation of x and y axes are unknown currently.
// The origin is at the same position as the model space origin.
// The units are in meters.
mat4 viewSpaceToZUpSpace = fg_zUpTransform * gl_ModelViewMatrixInverse;
vec4 vertexZUp = fg_zUpTransform * gl_Vertex;
// WS2: rawPos = gl_Vertex.xy;
rawPos = vertexZUp.xy;
// WS2: worldPos = (osg_ViewMatrixInverse *gl_ModelViewMatrix * gl_Vertex).xyz;
worldPos = fg_modelOffset + gl_Vertex.xyz;
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
// Gradient direction used for small scale noise. In the same space as noise coords, rawpos.xy.
grad_dir = normalize(gl_Normal.xy);
// here start computations for the haze layer
// we need several geometrical quantities
// Eye position in z up space
vec4 epZUp = viewSpaceToZUpSpace * vec4(0.0,0.0,0.0,1.0);
// Position of vertex relative to the eye position in z up space
vec3 relPosZUp = (vertexZUp - epZUp).xyz;
// 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 = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
ecViewdir = (gl_ModelViewMatrix * (ep - gl_Vertex)).xyz;
// Eye position in model space
vec4 epMS = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
/*
//old: and relative position to vector. This is also used for cloud shadow positioning.
relPosOld = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
if (any(notEqual(relPosOld, relPosZUp))) relPos = vec3(1000000.0);
*/
relPos = relPosZUp;
vertVec = relPosZUp;
ecViewdir = (gl_ModelViewMatrix * (epMS - gl_Vertex)).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(rawPos.z,100.0);
// Altitude of the vertex above mean sea level in meters.
// This is equal to vertexZUp.z as the model space origin is at mean sea level.
// Somehow zero leads to artefacts, so ensure it is at least 100m.
//WS2: vertex_alt = max(gl_Vertex.z,100.0);
vertex_alt = max(vertexZUp.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
@ -150,15 +258,11 @@ void main()
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);
@ -179,8 +283,6 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
{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);
@ -194,6 +296,14 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
light_ambient.b = light_ambient.r * 0.5/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.5);
light_ambient.a = 1.0;
// Water specular calculations
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 = max(specular_light * scattering, vec3 (0.05, 0.05, 0.05));
intensity = length(specular_light.rgb);
specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.6,ground_scattering) ));
specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.5, 0.7,earthShade)));
@ -208,6 +318,13 @@ if (earthShade < 0.5)
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) ));
}
// directional scattering for low sun
if (lightArg < 10.0) {
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
@ -228,7 +345,7 @@ else
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
} // End if (terminator < 1000000.0)
else // the faster, full-day version without lightfields
{
//vertex_alt = max(gl_Vertex.z,100.0);
@ -237,11 +354,13 @@ else // the faster, full-day version without lightfields
mie_angle = 1.0;
if (terminator > 3000000.0)
{light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0); }
{
light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0);
specular_light = vec3 (1.0, 1.0, 1.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;
@ -254,11 +373,18 @@ else // the faster, full-day version without lightfields
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.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;
}
light_diffuse = light_diffuse * scattering;
specular_light = specular_light * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
} //End the faster, full-day version without lightfields
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
@ -272,6 +398,7 @@ float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smooth
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
specular_light.rgb *= (1.0 + 1.2 * shade_depth);
if (use_IR_vision)
{

View file

@ -22,6 +22,9 @@
// Possible values: 0:Normal, 1:Just the texture.
const int remove_haze_and_lighting = 0;
// Use built-in water shader. Use for testing impact of ws30-water.frag
const int water_shader = 1;
//
// End of test phase controls
//////////////////////////////////////////////////////////////////
@ -43,6 +46,7 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec2 ground_tex_coord;
uniform sampler2D landclass;
uniform sampler2DArray textureArray;
@ -72,6 +76,8 @@ uniform vec4 fg_diffuseArray[128];
uniform vec4 fg_specularArray[128];
uniform vec4 fg_textureLookup1[128];
uniform vec4 fg_textureLookup2[128];
uniform vec4 fg_materialParams3[128];
#define MAX_TEXTURES 8
uniform mat4 fg_zUpTransform;
uniform vec3 fg_modelOffset;
@ -106,6 +112,7 @@ vec3 filter_combined (in vec3 color) ;
float getShadowing();
vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
vec4 generateWaterTexel();
// Not used
float luminance(vec3 color)
@ -117,7 +124,6 @@ float luminance(vec3 color)
//////////////////////////
// Test-phase code:
// These should be sent as uniforms
// Tile dimensions in meters
@ -130,47 +136,81 @@ float luminance(vec3 color)
// From noise.frag
float rand2D(in vec2 co);
// These functions, and other function they depend on, are defined
// in ws30-ALS-landclass-search.frag.
// Create random landclasses without a texture lookup to stress test.
// Each square of square_size in m is assigned a random landclass value.
int get_random_landclass(in vec2 co, in vec2 tile_size);
// End Test-phase code
////////////////////////
// These functions, and other function they depend on, are defined
// in ws30-ALS-landclass-search.frag.
// Lookup a ground texture at a point based on the landclass at that point, without visible
// seams at coordinate discontinuities or at landclass boundaries where texture are switched.
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
// the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams.
// Texture types: 0: base texture, 1: grain texture, 2: gradient texture, 3 dot texture,
// 4: mix texture, 5: detail texture.
vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy);
vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec4 dFdx_and_dFdy);
// Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance.
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
// Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor
);
// End Test-phase code
////////////////////////
// Look up the texel of the specified texture type (e.g. grain or detail textures) for this fragment
// and any neighbor texels, then mix.
vec4 get_mixed_texel(in int texture_type, in vec2 g_texture_coord,
in int landclass_id, in int num_unique_neighbors,
in ivec4 neighbor_texel_landclass_ids, in vec4 neighbor_mix_factors,
in vec4 dFdx_and_dFdy
);
// Determine the texel and material parameters for a particular fragment,
// Taking into account photoscenery etc.
void get_material(in int landclass,
in vec2 ground_tex_coord,
in vec4 dxdy_gc,
out float mat_shininess,
out vec4 mat_ambient,
out vec4 mat_diffuse,
out vec4 mat_specular,
out vec4 dxdy,
out vec2 st
);
// Apply the ALS haze model to a specific fragment
vec4 applyHaze(inout vec4 fragColor,
inout vec3 hazeColor,
in vec3 secondary_light,
in float ct,
in float hazeLayerAltitude,
in float visibility,
in float avisibility,
in float dist,
in float lightArg,
in float mie_angle);
// Procedurally generate a water texel for this fragment
vec4 generateWaterTexel();
void main()
{
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
// this is taken from default.frag
vec3 n;
float NdotL, NdotHV, fogFactor;
vec3 n = normalize(normal);
vec3 lightDir = gl_LightSource[0].position.xyz;
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
vec4 texel;
@ -178,27 +218,18 @@ void main()
vec4 specular = vec4(0.0);
float intensity;
// Material/texel properties
float mat_shininess;
vec2 st;
vec4 mat_ambient, mat_diffuse, mat_specular, dxdy;
// Oct 27 2021:
// Geometry is in the form of roughly rectangular 'tiles'
// with a mesh forming a grid with regular spacing.
// Each vertex in the mesh is given an elevation
// Tile dimensions in m
// Testing: created from two float uniforms in global scope. Should be sent as a vec2
// vec2 tile_size
// Tile texture coordinates range [0..1] over the tile 'rectangle'
vec2 tile_coord = gl_TexCoord[0].st;
// Test phase: Constants and toggles for transitions between landlcasses are defined at
// the top of this file.
// Look up the landclass id [0 .. 255] for this particular fragment
// and any neighbouring landclass that is close.
// Each tile has 1 texture containing landclass ids stetched over it.
// Landclass for current fragment, and up-to 4 neighboring landclasses - 2 used currently
int lc;
ivec4 lc_n;
@ -208,75 +239,30 @@ void main()
// Mix factor of base textures for 2 neighbour landclass(es)
vec4 mfact;
const float landclass_texel_size_m = 25.0;
// Partial derivatives of s and t for this fragment,
// with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord);
vec2 dy = dFdy(tile_coord);
// dFdx and dFdy are packed in a vec4 so multiplying
// to scale takes 1 instruction slot.
vec4 dxdy_gc = vec4(dFdx(tile_coord) , dFdy(tile_coord));
get_landclass_id(tile_coord, landclass_texel_size_m, dx, dy,
lc, lc_n, num_unique_neighbors, mfact);
// The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as
// defined in the regional definitions
float index = float(lc)/512.0;
vec4 index_n = vec4(lc_n)/512.0;
// Material properties.
vec4 mat_diffuse, mat_ambient, mat_specular;
float mat_shininess;
get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
get_material(lc, ground_tex_coord, dxdy_gc, mat_shininess, mat_ambient, mat_diffuse, mat_specular, dxdy, st);
if (fg_photoScenery) {
mat_ambient = vec4(1.0,1.0,1.0,1.0);
mat_diffuse = vec4(1.0,1.0,1.0,1.0);
mat_specular = vec4(0.1, 0.1, 0.1, 1.0);
mat_shininess = 1.2;
texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t));
} else {
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray.
mat_ambient = vec4(1.0,1.0,1.0,1.0);
mat_diffuse = vec4(1.0,1.0,1.0,1.0);
mat_specular = fg_specularArray[lc];
mat_shininess = fg_dimensionsArray[lc].z;
// Look up ground textures by indexing into the texture array.
// Different textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters
// Look up texture coordinates and scale of ground textures
// Landclass for this fragment
texel = lookup_ground_texture_array(tile_coord, lc, dx, dy);
// Mix texels - to work consistently it needs a more preceptual interpolation than mix()
if (num_unique_neighbors != 0)
{
// Closest neighbor landclass
vec4 texel_closest = lookup_ground_texture_array(tile_coord, lc_n[0], dx, dy);
// Neighbor contributions
vec4 texel_nc=texel_closest;
if (num_unique_neighbors > 1)
{
// 2nd Closest neighbor landclass
vec4 texel_2nd_closest = lookup_ground_texture_array(tile_coord, lc_n[1],
dx, dy);
texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]);
// Lookup the base texture texel for this fragment. No mixing at this quality level.
texel = lookup_ground_texture_array(0, st, lc, dxdy);
}
texel = mix(texel, texel_nc, mfact[0]);
}
}
if ((water_shader == 1) && (fg_photoScenery == false) && fg_materialParams3[lc].x > 0.5) {
// This is a water fragment, so calculate the fragment color procedurally
fragColor = generateWaterTexel();
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, fragColor.rgb);
} else {
// Photoscenery or land fragment, so determine the shading and color normally
vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient);
// Testing code:
@ -291,7 +277,7 @@ void main()
// 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(normal);
NdotL = dot(n, lightDir);
@ -321,164 +307,19 @@ void main()
fragColor = color * texel + specular;
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
// here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt;
float dist = length(relPos);
float mvisibility = min(visibility,avisibility);
if (dist > 0.04 * mvisibility)
{
alt = eye_alt;
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
}
// angle with horizon
float dist = length(relPos);
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,mvisibility) * 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;
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 -effective_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 -effective_scattering);
}
transmission = fog_func(transmission_arg, alt);
// 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 = get_hazeColor(lightArg);
// now dim the light for haze
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
// Mie-like factor
if (lightArg < 10.0)
{intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
// 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* shadedFogColor, 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, shadedFogColor, (1.0-smoothstep(0.5,0.9,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));
// don't let the light fade out too rapidly
lightArg = (terminator + 200000.0)/100000.0;
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
hazeColor *= eqColorFactor * eShade;
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
// determine the right mix of transmission and haze
// Testing phase controls
if (reduce_haze_without_removing_calculation_overhead == 1)
{
transmission = 1.0 - (transmission/1000000.0);
}
fragColor.rgb = mix(hazeColor, fragColor.rgb,transmission);
}
fragColor.rgb = filter_combined(fragColor.rgb);
gl_FragColor = fragColor;
gl_FragColor = applyHaze(fragColor, hazeColor, vec3(0.0), ct, hazeLayerAltitude, visibility, avisibility, dist, lightArg, mie_angle);
// Testing phase controls:
if (remove_haze_and_lighting == 1)
{
gl_FragColor = texel;
}
}

View file

@ -27,11 +27,24 @@ uniform vec3 fg_modelOffset;
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec2 ground_tex_coord;
varying vec4 ecPosition;
varying float yprime_alt;
varying float mie_angle;
// For water calculations
varying float earthShade;
varying vec3 lightdir;
varying vec4 waterTex1;
varying vec4 waterTex2;
varying vec4 waterTex4;
varying vec3 specular_light;
uniform float osg_SimulationTime;
uniform float WindN;
uniform float WindE;
uniform int colorMode;
uniform float hazeLayerAltitude;
uniform float terminator;
@ -41,6 +54,7 @@ uniform float visibility;
uniform float overcast;
uniform float ground_scattering;
uniform float moonlight;
uniform float eye_alt;
void setupShadows(vec4 eyeSpacePos);
@ -48,19 +62,20 @@ void setupShadows(vec4 eyeSpacePos);
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float earthShade;
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 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()
{
@ -85,6 +100,31 @@ void main()
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
normal = gl_NormalMatrix * gl_Normal;
// Required for water calculations
lightdir = normalize(vec3(fg_zUpTransform * vec4(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(WindE * WindE + WindN * WindN) * 0.05;
if (WindN == 0.0 && WindE == 0.0) {
Angle = 0.0;
} else {
Angle = atan(-WindN, WindE) - atan(1.0);
}
mat4 RotationMatrix;
rotationmatrix(Angle, RotationMatrix);
waterTex1 = gl_MultiTexCoord0 * RotationMatrix - t1 * windFactor;
rotationmatrix(Angle, RotationMatrix);
waterTex2 = gl_MultiTexCoord0 * RotationMatrix - t2 * windFactor;
// Temporary value:
ground_tex_coord = gl_TexCoord[0].st;
// here start computations for the haze layer
// we need several geometrical quantities
@ -99,23 +139,17 @@ void main()
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(relPos.z,100.0);
vertex_alt = max(relPos.z + eye_alt, 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);
@ -130,13 +164,11 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun
if (lightArg < 10.0)
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else
{mie_angle = 1.0;}
if (lightArg < 10.0) {
mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;
} else {
mie_angle = 1.0;
}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
@ -150,12 +182,17 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.0;
// Water specular calculations
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 = max(specular_light * scattering, vec3 (0.05, 0.05, 0.05));
intensity = length(specular_light.rgb);
specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.6,ground_scattering) ));
specular_light.rgb = intensity * normalize(mix(specular_light.rgb, shadedFogColor, 1.0 -smoothstep(0.5, 0.7,earthShade)));
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
if (earthShade < 0.5) {
//light_ambient = light_ambient * (0.7 + 0.3 * smoothstep(0.2, 0.5, earthShade));
intensity = length(light_ambient.xyz);
@ -166,6 +203,12 @@ if (earthShade < 0.5)
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) ));
}
// directional scattering for low sun
if (lightArg < 10.0) {
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
@ -179,27 +222,22 @@ if (vertex_alt > hazeLayerAltitude)
vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else
{
} 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
{
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);
specular_light = vec3 (1.0, 1.0, 1.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;
@ -210,9 +248,17 @@ else // the faster, full-day version without lightfields
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.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;
}
light_diffuse = light_diffuse * scattering;
specular_light = specular_light * scattering;
float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smoothstep(0.1,0.5,overcast)) * smoothstep(0.4,1.5,earthShade);
specular_light.rgb *= (1.0 + 1.2 * shade_depth);
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
@ -228,8 +274,10 @@ else // the faster, full-day version without lightfields
vec4 constant_term = gl_LightModel.ambient + light_ambient;
// 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;
gl_FrontColor.rgb = constant_term.rgb;
gl_BackColor.rgb = constant_term.rgb;
gl_FrontColor.a = mie_angle;
gl_BackColor.a = mie_angle;
setupShadows(ecPosition);
}

View file

@ -0,0 +1,75 @@
// -*-C++-*-
#version 120
#extension GL_EXT_geometry_shader4 : enable
// The following is copied from terrain-overlay.geom
#define MAX_LAYERS 8
#define MIN_LAYERS 2
#define MAX_MINUS_MIN_LAYERS 6
uniform float overlay_max_height;
varying in vec3 v_normal[3];
varying out vec2 g_rawpos;
varying out float g_distance_to_eye;
varying out vec3 g_normal;
varying out float g_altitude;
varying out float g_layer;
uniform mat4 fg_LightMatrix_csm0;
uniform mat4 fg_LightMatrix_csm1;
uniform mat4 fg_LightMatrix_csm2;
uniform mat4 fg_LightMatrix_csm3;
varying out vec4 lightSpacePos[4];
void setupShadows(vec4 eyeSpacePos)
{
lightSpacePos[0] = fg_LightMatrix_csm0 * eyeSpacePos;
lightSpacePos[1] = fg_LightMatrix_csm1 * eyeSpacePos;
lightSpacePos[2] = fg_LightMatrix_csm2 * eyeSpacePos;
lightSpacePos[3] = fg_LightMatrix_csm3 * eyeSpacePos;
}
float min3(in float a, in float b, in float c)
{
float m = a;
if (m > b) m = b;
if (m > c) m = c;
return m;
}
void main()
{
float distances[3];
distances[0] = -(gl_ModelViewMatrix * gl_PositionIn[0]).z;
distances[1] = -(gl_ModelViewMatrix * gl_PositionIn[1]).z;
distances[2] = -(gl_ModelViewMatrix * gl_PositionIn[2]).z;
float minDistance = min3(distances[0], distances[1], distances[2]);
//float avgDistance = (distances[0]+distances[1]+distances[2])*0.33;
int numLayers = MIN_LAYERS + int((1.0 - smoothstep(250.0, 5000.0, minDistance)) * float(MAX_MINUS_MIN_LAYERS));
float deltaLayer = 1.0 / float(numLayers);
float currDeltaLayer = 1.5 * deltaLayer;// * 0.5;
for (int layer = 0; layer < numLayers; ++layer) {
for (int i = 0; i < 3; ++i) {
vec4 pos = gl_PositionIn[i] + vec4(v_normal[i] * currDeltaLayer * overlay_max_height, 0.0);
g_rawpos = gl_PositionIn[i].xy;
g_distance_to_eye = distances[i];
g_layer = currDeltaLayer;
g_normal = v_normal[i];
g_altitude = gl_PositionIn[i].z;
setupShadows(gl_ModelViewMatrix * pos);
gl_Position = gl_ModelViewProjectionMatrix * pos;
gl_TexCoord[0] = gl_TexCoordIn[i][0];
EmitVertex();
}
EndPrimitive();
currDeltaLayer += deltaLayer;
}
}

View file

@ -0,0 +1,21 @@
// -*-C++-*-
#version 120
//Copied from grass-ALS.vert
// The UV scale controls the grass thickness. Lower numbers thicken the blades
// while higher numbers make them thinner.
#define UV_SCALE 10.0
varying vec3 v_normal;
void main()
{
gl_Position = gl_Vertex;
// WS2: gl_TexCoord[0] = gl_MultiTexCoord0 * UV_SCALE;
gl_TexCoord[0] = gl_MultiTexCoord0 * UV_SCALE;
v_normal = gl_Normal;
}

View file

@ -58,7 +58,7 @@ void main()
} else {
// The Landclass for this particular fragment. This can be used to
// index into the atlas textures.
int lc = int(texture2D(landclass, gl_TexCoord[0].st).r * 255.0 + 0.5);
int lc = int(texture2D(landclass, gl_TexCoord[0].st).g * 255.0 + 0.5);
uint tex1 = uint(fg_textureLookup1[lc].r * 255.0 + 0.5);
// Color Mode is always AMBIENT_AND_DIFFUSE, which means

View file

@ -0,0 +1,735 @@
// -*- mode: C; -*-
// Licence: GPL v2
// Authors: Frederic Bouvier and Gijs de Rooy
// with major additions and revisions by
// Emilian Huminiuc and Vivian Meazza 2011
// ported to Atmospheric Light Scattering
// by Thorsten Renk, 2013
// changes for road and traffic rendering
// by Thorsten Renk 2017 -2019
#version 120
varying vec3 VBinormal;
varying vec3 VNormal;
varying vec3 VTangent;
varying vec3 rawpos;
//varying vec3 reflVec;
//varying vec3 vViewVec;
varying vec3 vertVec;
varying vec3 relPos;
varying float alpha;
uniform sampler2D BaseTex;
//uniform sampler2D NormalTex;
//uniform sampler2D ReflMapTex;
uniform sampler2D CarTex;
uniform sampler2D CarMetaTex;
//uniform sampler2D ReflGradientsTex;
//uniform samplerCube Environment;
//uniform sampler2D GrainTex;
//uniform int dirt_enabled;
//uniform int dirt_multi;
//uniform int nmap_dds;
//uniform int nmap_enabled;
//uniform int refl_enabled;
//uniform int refl_type;
//uniform int refl_map;
//uniform int grain_texture_enabled;
uniform int road_traffic_direction;
//uniform int rain_enabled;
uniform int road_traffic_enabled;
uniform int cloud_shadow_flag;
uniform int use_searchlight;
uniform int use_landing_light;
uniform int use_alt_landing_light;
uniform float amb_correction;
uniform float dirt_b_factor;
uniform float dirt_g_factor;
uniform float dirt_r_factor;
//uniform float nmap_tile;
//uniform float refl_correction;
//uniform float refl_fresnel;
//uniform float refl_fresnel_factor;
//uniform float refl_noise;
//uniform float refl_rainbow;
//uniform float grain_magnification;
//uniform float wetness;
//uniform float rain_norm;
uniform float road_traffic_density;
uniform float streetlight_factor;
uniform float road_traffic_variation;
uniform float avisibility;
uniform float cloud_self_shading;
uniform float eye_alt;
uniform float ground_scattering;
uniform float hazeLayerAltitude;
uniform float moonlight;
uniform float overcast;
uniform float scattering;
uniform float terminator;
uniform float terrain_alt;
uniform float visibility;
uniform float air_pollution;
uniform float snowlevel;
uniform float snow_thickness_factor;
uniform float osg_SimulationTime;
uniform float landing_light1_offset;
uniform float landing_light2_offset;
uniform float landing_light3_offset;
uniform bool use_IR_vision;
uniform mat4 fg_zUpTransform;
uniform vec3 fg_modelOffset;
// constants needed by the light and fog computations ###################################################
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
//uniform vec3 dirt_r_color;
//uniform vec3 dirt_g_color;
//uniform vec3 dirt_b_color;
uniform vec3 streetlight_color;
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dot_density);
float shadow_func (in float x, in float y, in float noise, in float dist);
float fog_func (in float targ, in float altitude);
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt);
float alt_factor(in float eye_alt, in float vertex_alt);
float light_distance_fading(in float dist);
float fog_backscatter(in float avisibility);
float rand2D(in vec2 co);
float Noise2D(in vec2 coord, in float wavelength);
vec3 rayleigh_out_shift(in vec3 color, in float outscatter);
vec3 get_hazeColor(in float lightArg);
vec3 searchlight();
vec3 landing_light(in float offset, in float offsetv);
vec3 filter_combined (in vec3 color) ;
vec3 addLights(in vec3 color1, in vec3 color2);
float getShadowing();
vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
if (x > 30.0) {return e;}
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
void road_type_mapper (in vec2 coord, out float rtype_traffic_density, out float rtype_base_illumination, out float rtype_traffic_speed, out int rtype_dual_lane)
{
if (coord.s < 0.125) // railway
{
rtype_dual_lane = 0;
rtype_traffic_density = 0;
rtype_base_illumination = 0;
rtype_traffic_speed = 0.0;
}
else if (coord.s < 0.250) // residential
{
rtype_dual_lane = 0;
rtype_traffic_density = 0.3;
rtype_base_illumination = 0.65;
rtype_traffic_speed = 0.5;
}
else if (coord.s < 0.375) // single-lane major
{
rtype_dual_lane = 0;
rtype_traffic_density = 1.0;
rtype_base_illumination = 0.65;
rtype_traffic_speed = 1.0;
}
else if (coord.s < 0.5)
{
rtype_dual_lane = 0;
rtype_traffic_density = 0.0;
rtype_base_illumination = 0.0;
rtype_traffic_speed = 0.0;
}
else if (coord.s < 0.625) // grass
{
rtype_dual_lane = 0;
rtype_traffic_density = 0.0;
rtype_base_illumination = 0.0;
rtype_traffic_speed = 0.0;
}
else if (coord.s < 0.750) // dual-lane highway
{
rtype_dual_lane = 1;
rtype_traffic_density = 1.0;
rtype_base_illumination = 0.0;
rtype_traffic_speed = 1.0;
}
else if (coord.s < 0.875) // dirt
{
rtype_dual_lane = 0;
rtype_traffic_density = 0.1;
rtype_base_illumination = 0.0;
rtype_traffic_speed = 0.3;
}
else // tramway
{
rtype_dual_lane = 0;
rtype_traffic_density = 0.0;
rtype_base_illumination = 0.0;
rtype_traffic_speed = 0.0;
}
}
void main (void)
{
vec4 texel = texture2D(BaseTex, gl_TexCoord[0].st);
vec4 noisevec = vec4 (1.0, 1.0, 1.0, 1.0);
vec4 grainTexel;
vec3 mixedcolor;
vec3 N = vec3(0.0,0.0,1.0);
// noise
float noise_1m = Noise2D(rawpos.xy, 1.0);
float noise_5m = Noise2D(rawpos.xy, 5.0);
// road type characteristics
float rtype_traffic_density = 0.0;
float rtype_base_illumination = 0.0;
float rtype_traffic_speed = 0.0;
int rtype_dual_lane = 0;
road_type_mapper (gl_TexCoord[0].st, rtype_traffic_density, rtype_base_illumination, rtype_traffic_speed, rtype_dual_lane);
float pf = 0.0;
float pf1 = 0.0;
///some generic light scattering parameters
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight;
float alt = eye_alt;
float effective_scattering = min(scattering, cloud_self_shading);
/// BEGIN geometry for light
vec3 up = (gl_ModelViewMatrix * vec4(0.0,0.0,1.0,0.0)).xyz;
vec3 nVertVec = normalize(vertVec);
float dist = length(relPos);
// angle of view vector with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
float vertex_alt = (relPos.z + eye_alt);
float vertex_scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
vec3 lightHorizon = gl_LightSource[0].position.xyz - up * dot(up,gl_LightSource[0].position.xyz);
float yprime = -dot(vertVec, lightHorizon);
float yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
float lightArg = (terminator-yprime_alt)/100000.0;
float earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
float mie_angle = gl_Color.a;
float fog_vertex_alt = max(vertex_alt,hazeLayerAltitude);
float fog_yprime_alt = yprime_alt;
if (fog_vertex_alt > hazeLayerAltitude)
{
if (dist > 0.8 * avisibility)
{
fog_vertex_alt = mix(fog_vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
fog_yprime_alt = yprime -sqrt(2.0 * EarthRadius * fog_vertex_alt);
}
}
else
{
fog_vertex_alt = hazeLayerAltitude;
fog_yprime_alt = yprime -sqrt(2.0 * EarthRadius * fog_vertex_alt);
}
float fog_lightArg = (terminator-fog_yprime_alt)/100000.0;
float fog_earthShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, fog_yprime_alt) + 0.1;
/// END geometry for light
/// BEGIN light
vec4 light_diffuse;
vec4 light_ambient;
float intensity;
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 = 1.0;
light_diffuse = light_diffuse * vertex_scattering;
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.0;
if (earthShade < 0.5)
{
intensity = length(light_ambient.rgb);
light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.8,earthShade) ));
light_ambient.rgb = light_ambient.rgb + moonLightColor * (1.0 - smoothstep(0.4, 0.5, earthShade));
intensity = length(light_diffuse.rgb);
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.1, 0.7,earthShade) ));
}
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
vec3 ecViewDir = (gl_ModelViewMatrix * (ep - vec4(rawpos, 1.0))).xyz;
vec3 HV = normalize(normalize(gl_LightSource[0].position.xyz) + normalize(ecViewDir));
/// END light
/// BEGIN procedural textures - cars and snow
vec2 roadCoords = gl_TexCoord[0].st;
roadCoords.s *=8.0;
roadCoords.s = fract(roadCoords.s);
vec4 snow_texel = vec4 (0.95, 0.95, 0.95, 1.0);
float noise_term = 0.5 * (noise_5m - 0.5);
noise_term += 0.5 * (noise_1m - 0.5);
snow_texel.a = snow_texel.a * 0.2+0.8* smoothstep(0.2,0.8, 0.3 +noise_term + 0.5*snow_thickness_factor +0.0001*(relPos.z +eye_alt -snowlevel) );
float noise_2000m = 0.0;
float noise_10m = 0.0;
float snowLaneShape = smoothstep(0.20, 0.28, roadCoords.s) * (1.0-smoothstep(0.42, 0.5, roadCoords.s));
snowLaneShape += smoothstep(0.6, 0.68, roadCoords.s) * (1.0-smoothstep(0.82, 0.9, roadCoords.s));
snow_texel.a *= (1.0 - 0.3* snowLaneShape * rtype_traffic_density);
texel.rgb = mix(texel.rgb, snow_texel.rgb, snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, 1.0 * (relPos.z + eye_alt)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
float cTag = 0.0;
float cPresent = 0.0;
float cSign = 1.0;
float total_traffic_density = 0.0;
vec4 carMetaTexel;
if (road_traffic_enabled == 1)
{
float cOffset = 0.0;
if (roadCoords.s > 0.5)
{
if (rtype_dual_lane == 0) {cSign = -1.0;}
else {cOffset = 5.0;}
}
if (rtype_dual_lane == 1) {cSign = -1.0;}
cSign *= road_traffic_direction;
total_traffic_density = road_traffic_density * rtype_traffic_density * road_traffic_variation;
float cCoord = roadCoords.t + cOffset;
cCoord += 0.3 * osg_SimulationTime * cSign * rtype_traffic_speed * (1.0 - (0.9 * smoothstep(1.0, 2.5, total_traffic_density)));
cCoord *= 5.0;
cTag = fract(cCoord);
float cDomain = cCoord - cTag;
float cRnd = rand2D(vec2 (cDomain, cSign));
cPresent = 0.0;
float cDisc = 0.2 * total_traffic_density;
if (cRnd > 1.0 - cDisc) {cPresent = 1.0;}
float cColorRnd = (cRnd - 1.0 + cDisc)/ max(cDisc, 0.05);
float cColorRnd2 = rand2D(vec2 (cDomain, 0.5));
float cColumn = (cColorRnd2 * 16.0) - fract(cColorRnd2 * 16.0);
float cRow = (rand2D(vec2 (cDomain, 1.5)) * 2.0);
cRow = cRow- fract(cRow);
//cRow = 0.0;
vec3 cColor = vec3 (0.8 * (1.0 - cColorRnd), 0.8 * 2.0 * (0.5 - abs(cColorRnd - 0.5)) , 0.8 * cColorRnd);
cColor *= cColorRnd2;
float cPos = cTag;
if (cSign > 0.0) {cPos = 1.0 - cPos;}
float cShape = smoothstep(0.0, 0.05, cPos) * (1.0-smoothstep(0.35, 0.4, cPos));
float ctPos;
if (roadCoords.s < 0.5)
{ctPos = clamp(5.0 * (roadCoords.s - 0.25), 0.0,1.0); }
else
{ctPos = clamp(5.0 * (roadCoords.s - 0.65), 0.0,1.0); }
float clPos = cPos;// + 0.45;
vec4 carTexel = texture2D(CarTex, vec2((ctPos + cColumn) / 16.0 , ((clPos + cRow) / 2.0) ));
carMetaTexel = texture2D(CarMetaTex, vec2((ctPos + cColumn) / 16.0 , ((clPos + cRow) / 2.0) ));
float laneShape = smoothstep(0.25, 0.28, roadCoords.s) * (1.0-smoothstep(0.42, 0.45, roadCoords.s));
laneShape += smoothstep(0.65, 0.68, roadCoords.s) * (1.0-smoothstep(0.82, 0.85, roadCoords.s));
cShape *= laneShape;
//texel.rgb = mix(texel.rgb, cColor, cPresent * cShape);
texel.rgb = mix(texel.rgb, carTexel.rgb, cPresent * carTexel.a * laneShape);
//texel.rgb = mix(texel.rgb, vec3 (1.0, 0.0, 0.0) * cColorRnd2, 0.3);
}
/// END procedural cars
//vec3 reflVecN;
//vec3 viewVec = normalize(vViewVec);
//float v = abs(dot(viewVec, normalize(VNormal)));// Map a rainbowish color
//float nDotVP = max(0.0, dot(N, normalize(gl_LightSource[0].position.xyz)));
float nDotVP = max(0.0, dot(N, normalize(gl_LightSource[0].position.xyz)));
//float nDotHV = max(0.0, dot(N, normalize(gl_LightSource[0].halfVector.xyz)));
float nDotHV = max(0.0, dot(N,HV));
//glare on the backside of tranparent objects
//if ((gl_FrontMaterial.diffuse.a < 1.0 || texel.a < 1.0)
// && dot(N, normalize(gl_LightSource[0].position.xyz)) < 0.0) {
// nDotVP = max(0.0, dot(-N, normalize(gl_LightSource[0].position.xyz)) * (1.0 -texel.a) );
// nDotHV = max(0.0, dot(-N, HV) * (1.0 -texel.a) );
// }
float nDotVP1 = 0.0;
float nDotHV1 = 0.0;
// try specular reflection of sky irradiance
nDotVP1 = max(0.0, dot(N, up));
nDotHV1 = max(0.0, dot(N, normalize(normalize(up) + normalize(-vertVec))));
if (nDotVP == 0.0)
{pf = 0.0;}
else
{pf = pow(nDotHV, gl_FrontMaterial.shininess);}
if (nDotVP1 == 0.0)
{pf1 = 0.0;}
else
{pf1 = pow(nDotHV1, 0.5*gl_FrontMaterial.shininess);}
if (cloud_shadow_flag == 1)
{
light_diffuse = light_diffuse * shadow_func(relPos.x, relPos.y, 1.0, dist);
}
vec3 secondary_light = vec3 (0.0,0.0,0.0);
if (use_searchlight == 1)
{
secondary_light += searchlight();
}
if (use_landing_light == 1)
{
secondary_light += landing_light(landing_light1_offset, landing_light3_offset);
}
if (use_alt_landing_light == 1)
{
secondary_light += landing_light(landing_light2_offset, landing_light3_offset);
}
float shadowmap = getShadowing();
vec4 Diffuse = light_diffuse * nDotVP * shadowmap;
Diffuse.rgb += secondary_light * light_distance_fading(dist);
if (use_IR_vision)
{
Diffuse.rgb = max(Diffuse.rgb, vec3 (0.5, 0.5, 0.5));
}
vec4 Specular = gl_FrontMaterial.specular * light_diffuse * pf + gl_FrontMaterial.specular * light_ambient * pf1 * shadowmap;
Specular+= gl_FrontMaterial.specular * pow(max(0.0,-dot(N,nVertVec)),gl_FrontMaterial.shininess) * vec4(secondary_light,1.0);
//vec4 color = gl_Color + Diffuse * gl_FrontMaterial.diffuse;
vec4 color = Diffuse;// * gl_FrontMaterial.diffuse;
color = clamp( color, 0.0, 1.0 );
// set ambient adjustment to remove bluiness with user input
float ambient_offset = clamp(amb_correction, -1.0, 1.0);
vec4 ambient = gl_LightModel.ambient + light_ambient;
vec4 ambient_Correction = vec4(ambient.rg, ambient.b * 0.6, 1.0)
* ambient_offset ;
ambient_Correction = clamp(ambient_Correction, -1.0, 1.0);
color += ambient;
color.a = texel.a * alpha;
vec4 fragColor = vec4(color.rgb * mixedcolor + ambient_Correction.rgb, color.a);
fragColor += Specular;
fragColor.rgb += getClusteredLightsContribution(vertVec, N, texel.rgb);
//////////////////////////////////////////////////////////////////////
// BEGIN procedural lightmap
//////////////////////////////////////////////////////////////////////
vec3 pLMColor = streetlight_color;
float pLMIntensity = smoothstep(0.0, 0.4, roadCoords.s) * (1.0 - smoothstep(0.6, 1.0, roadCoords.s));
pLMIntensity = 0.25 * rtype_base_illumination * (1.0+ streetlight_factor) + 0.1 * max(0.0,sin(4.0 * roadCoords.t)) * streetlight_factor;
pLMIntensity = clamp(pLMIntensity, 0.0, 1.0);
if (gl_FrontMaterial.diffuse.r == 0.0) {pLMIntensity =0.0;}
pLMColor *= pLMIntensity;
if (road_traffic_enabled == 1)
{
float viewAngleFactor = smoothstep(-0.05, 0.0, cSign * dot(normalize(VBinormal), nVertVec));
vec3 pCLColor = vec3 (0.95, 1.0, 1.0);
vec3 pTLColor = vec3 (0.95, 0.0, 0.0);
// mean illumination by car headlights
pLMColor = pLMColor + 0.2 * min(1.0,total_traffic_density) * pCLColor;
//float pCLIntensity = smoothstep(0.4, 0.6, cTag) * (1.0-smoothstep(0.6, 0.8, cTag));
//float laneFact = smoothstep(0.25, 0.3, roadCoords.s) * (1.0-smoothstep(0.3, 0.35, roadCoords.s));
//laneFact += smoothstep(0.35, 0.4, roadCoords.s) * (1.0-smoothstep(0.4, 0.45, roadCoords.s));
//laneFact += smoothstep(0.65, 0.7, roadCoords.s) * (1.0-smoothstep(0.7, 0.75, roadCoords.s));
//laneFact += smoothstep(0.75, 0.8, roadCoords.s) * (1.0-smoothstep(0.8, 0.85, roadCoords.s));
//pCLIntensity = pCLIntensity * laneFact * cPresent;
float pCLIntensity, pTLIntensity;
if (cSign == -1.0)
{
pCLIntensity = carMetaTexel.r * cPresent * smoothstep(0.45, 0.55, cTag) * viewAngleFactor ;
pCLIntensity += 0.85 * carMetaTexel.b * cPresent * smoothstep(0.45, 0.55, cTag);
pTLIntensity = carMetaTexel.r * cPresent * (1.0 - smoothstep(0.45, 0.55, cTag)) * (1.0 - viewAngleFactor);
pTLIntensity += 0.85 * carMetaTexel.b * cPresent * (1.0 - smoothstep(0.45, 0.55, cTag));
}
else
{
pCLIntensity = carMetaTexel.r * cPresent * (1.0 - smoothstep(0.45, 0.55, cTag)) *viewAngleFactor ;
pCLIntensity += 0.85 * carMetaTexel.b * cPresent * (1.0 - smoothstep(0.45, 0.55, cTag));
pTLIntensity = carMetaTexel.r * cPresent * smoothstep(0.45, 0.55, cTag) * (1.0 - viewAngleFactor);
pTLIntensity += 0.85 * carMetaTexel.b * cPresent * smoothstep(0.45, 0.55, cTag);
}
//pCLColor *= pCLIntensity;
//if (cSign == 1.0)
// {
// pTLIntensity = smoothstep(0.9, 0.94, cTag) * (1.0-smoothstep(0.96, 1.0, cTag));
// }
//else
// {
// pTLIntensity = smoothstep(0.0, 0.04, cTag) * (1.0-smoothstep(0.06, 0.1, cTag));
// }
//pTLIntensity = pTLIntensity * laneFact * cPresent * (1.0 - viewAngleFactor);
pCLColor = pCLColor * pCLIntensity + pTLColor * pTLIntensity;
pLMColor = clamp(pLMColor, 0.0, 1.0);
pLMColor = max(pLMColor,pCLColor);
}
//fragColor.rgb = max(fragColor.rgb, pLMColor * gl_FrontMaterial.diffuse.rgb * smoothstep(0.0, 1.0, mixedcolor*.5 + pLMColor*.5));
fragColor.rgb = max(fragColor.rgb, pLMColor * smoothstep(0.0, 1.0, mixedcolor*.5 + pLMColor*.5));
//////////////////////////////////////////////////////////////////////
// END procedural lightmap
//////////////////////////////////////////////////////////////////////
/// BEGIN fog amount
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
float eqColorFactor;
float delta_z = hazeLayerAltitude - eye_alt;
float mvisibility = min(visibility, avisibility);
if (dist > 0.04 * mvisibility)
{
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,mvisibility) * 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;
}
}
transmission_arg = (dist-distance_in_layer)/avisibility;
if (visibility < avisibility)
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -effective_scattering);
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -effective_scattering);
}
transmission = fog_func(transmission_arg, alt);
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
}
else
{
eqColorFactor = 1.0;
transmission = 1.0;
}
/// END fog amount
/// BEGIN fog color
vec3 hazeColor = get_hazeColor(fog_lightArg);
float rShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt + 420000.0);
float lightIntensity = length(hazeColor * effective_scattering) * rShade;
if (transmission< 1.0)
{
if (fog_lightArg < 10.0)
{
intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
intensity = length(hazeColor);
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
hazeColor.r = hazeColor.r * 0.83;
hazeColor.g = hazeColor.g * 0.9;
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,fog_earthShade) ));
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
float shadow = mix( min(1.0 + dot(VNormal,gl_LightSource[0].position.xyz),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));
}
else
{
hazeColor = vec3 (1.0, 1.0, 1.0);
}
/// END fog color
fragColor = clamp(fragColor, 0.0, 1.0);
hazeColor = clamp(hazeColor, 0.0, 1.0);
///BEGIN Rayleigh fog ///
// Rayleigh color shift due to out-scattering
float rayleigh_length = 0.5 * avisibility * (2.5 - 1.9 * air_pollution)/alt_factor(eye_alt, eye_alt+relPos.z);
float outscatter = 1.0-exp(-dist/rayleigh_length);
fragColor.rgb = rayleigh_out_shift(fragColor.rgb,outscatter);
vec3 rayleighColor = vec3 (0.17, 0.52, 0.87) * lightIntensity;
float rayleighStrength = rayleigh_in_func(dist, air_pollution, avisibility/max(lightIntensity,0.05), eye_alt, eye_alt + relPos.z);
fragColor.rgb = mix(fragColor.rgb, rayleighColor,rayleighStrength);
/// END Rayleigh fog
// don't let the light fade out too rapidly
lightArg = (terminator + 200000.0)/100000.0;
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
hazeColor *= eqColorFactor * fog_earthShade;
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
fragColor.rgb = mix(hazeColor +secondary_light * fog_backscatter(mvisibility), fragColor.rgb,transmission);
fragColor.rgb = filter_combined(fragColor.rgb);
gl_FragColor = fragColor;
}

360
Shaders/ws30-water.frag Normal file
View file

@ -0,0 +1,360 @@
// SPDX-FileCopyrightText: (C) 2022 Stuart Buchanan stuart13@gmail.com
// SPDX-License-Identifier: GPL-2.0-or-later
// Helper functions for WS30 water implementation, heavily based on the
// water-ALS-base.frag and waterr_ALS-high.frag
#version 130
#extension GL_EXT_texture_array : enable
// Hardcoded indexes into the texture atlas
const int ATLAS_INDEX_WATER = 0;
const int ATLAS_INDEX_WATER_REFLECTION = 1;
const int ATLAS_INDEX_WAVES_VERT10_NM = 2;
const int ATLAS_INDEX_WATER_SINE_NMAP = 3;
const int ATLAS_INDEX_WATER_REFLECTION_GREY = 4;
const int ATLAS_INDEX_SEA_FOAM = 5;
const int ATLAS_INDEX_PERLIN_NOISE_NM = 6;
const int ATLAS_INDEX_OCEAN_DEPTH = 7;
const int ATLAS_INDEX_GLOBAL_COLORS = 8;
const int ATLAS_INDEX_PACKICE_OVERLAY = 9;
// WS30 uniforms
uniform sampler2DArray textureArray;
uniform float ground_scattering;
uniform float overcast;
uniform float fg_tileWidth;
uniform float fg_tileHeight;
// Water.eff uniforms
uniform float sea_r;
uniform float sea_g;
uniform float sea_b;
uniform float osg_SimulationTime;
uniform float WindN;
uniform float WindE;
uniform float WaveFreq;
uniform float WaveAmp;
uniform float WaveSharp;
uniform float WaveAngle;
uniform float WaveFactor;
uniform float WaveDAngle;
uniform float saturation;
// WS30 varying
varying vec3 relPos;
// Water.eff varying
varying float earthShade;
varying vec3 lightdir;
varying vec4 waterTex1;
varying vec4 waterTex2;
varying vec4 waterTex4;
varying vec3 specular_light;
/////// functions /////////
float getShadowing();
vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
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, in vec2 pos, in float t) {
return w.amp * sin( dot(w.dir, pos) * w.freq + t * w.phase);
}
// derivative of wave function
float evaluateWaveDeriv(in Wave w, in vec2 pos, in float t) {
return w.freq * w.amp * cos( dot(w.dir, pos)*w.freq + t*w.phase);
}
// sharp wave functions
float evaluateWaveSharp(in Wave w, in vec2 pos, in float t, in float k) {
return w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k);
}
float evaluateWaveDerivSharp(in Wave w, in vec2 pos, in float t, in 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(in float angle, in float dangle, in float windScale, in 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;
}
vec4 generateWaterTexel()
{
vec4 texel;
float dist = length(relPos);
float tileScale = 1 / (fg_tileHeight + fg_tileWidth) / 2.0;
vec4 sca = vec4(0.005, 0.005, 0.005, 0.005) * tileScale;
vec4 sca2 = vec4(0.02, 0.02, 0.02, 0.02) * tileScale;
vec4 tscale = vec4(0.25, 0.25, 0.25, 0.25) / 10000.0 * tileScale;
mat4 RotationMatrix;
// compute direction to viewer
vec3 E = normalize(-relPos);
// compute direction to light source
vec3 L = normalize(lightdir);
// half vector
vec3 Hv = normalize(L + E);
vec3 Normal = vec3 (0.0, 0.0, 1.0);
const float water_shininess = 240.0;
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 = 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;
float angle;
ddx = 0.0, ddy = 0.0;
ddx1 = 0.0, ddy1 = 0.0;
ddx2 = 0.0, ddy2 = 0.0;
ddx3 = 0.0, ddy3 = 0.0;
if (detail_flag == 1)
{
angle = 0.0;
wave0.freq = WaveFreq ;
wave0.amp = WaveAmp;
wave0.dir = vec2 (0.0, 1.0); //vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = WaveAmp * 1.25;
wave1.dir = vec2(0.70710, -0.7071); //vec2(cos(radians(angle)), sin(radians(angle)));
angle += 30;
wave2.freq = WaveFreq * 3.5;
wave2.amp = WaveAmp * 0.75;
wave2.dir = vec2(0.96592, -0.2588);// vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 50;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = WaveAmp * 0.75;
wave3.dir = vec2(0.42261, -0.9063); //vec2(cos(radians(angle)), sin(radians(angle)));
// sum waves
sumWaves(WaveAngle, -1.5, windScale, WaveFactor, ddx, ddy);
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 (0.0, 1.0); //vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 20;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = waveamp * 1.25;
wave1.dir = vec2(0.93969, -0.34202);// vec2(cos(radians(angle)), sin(radians(angle)));
angle += 35;
wave2.freq = WaveFreq * 3.5;
wave2.amp = waveamp * 0.75;
wave2.dir = vec2(0.965925, 0.25881); //vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = waveamp * 0.75;
wave3.dir = vec2(0.866025, -0.5); //vec2(cos(radians(angle)), sin(radians(angle)));
//sumWaves(WaveAngle + WaveDAngle, -1.5, windScale, WaveFactor, ddx2, ddy2);
//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);
vec2 st = vec2(waterTex2 * tscale * windScale);
vec4 disdis = texture(textureArray, vec3(st, ATLAS_INDEX_WATER_SINE_NMAP)) * 2.0 - 1.0;
vec4 vNorm;
//normalmaps
st = vec2(waterTex1 + disdis * sca2) * windScale;
vec4 nmap = texture(textureArray, vec3(st, ATLAS_INDEX_WAVES_VERT10_NM)) * 2.0 - 1.0;
vec4 nmap1 = texture(textureArray, vec3(st, ATLAS_INDEX_PERLIN_NOISE_NM)) * 2.0 - 1.0;
rotationmatrix(radians(3.0 * sin(osg_SimulationTime * 0.0075)), RotationMatrix);
st = vec2(waterTex2 * RotationMatrix * tscale) * windScale;
nmap += texture(textureArray, vec3(st, ATLAS_INDEX_WAVES_VERT10_NM)) * 2.0 - 1.0;
nmap *= windEffect_low;
nmap1 *= windEffect_low;
// mix water and noise, modulated by factor
vNorm = normalize(mix(nmap, nmap1, mixFactor) * waveRoughness);
vNorm.r += ddx + ddx1 + ddx2 + ddx3;
//if (normalmap_dds > 0) {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.1, 0.8, 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), 0.5 * smoothstep(0.1, 0.9, overcast));
vec3 N;
st = vec2(waterTex1 + disdis * sca2) * windScale;
vec3 N0 = vec3(texture(textureArray, vec3(st, ATLAS_INDEX_WAVES_VERT10_NM))) * 2.0 - 1.0;
st = vec2(waterTex1 + disdis * sca) * windScale;
vec3 N1 = vec3(texture(textureArray, vec3(st, ATLAS_INDEX_PERLIN_NOISE_NM))) * 2.0 - 1.0;
st = vec2(waterTex1 * tscale) * windScale;
N0 += vec3(texture(textureArray, vec3(st, ATLAS_INDEX_WAVES_VERT10_NM))) * 2.0 - 1.0;
N1 += vec3(texture(textureArray, vec3(st, ATLAS_INDEX_PERLIN_NOISE_NM))) * 2.0 - 1.0;
rotationmatrix(radians(2.0 * sin(osg_SimulationTime * 0.005)), RotationMatrix);
st = vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale;
N0 += vec3(texture(textureArray, vec3(st, ATLAS_INDEX_WAVES_VERT10_NM))) * 2.0 - 1.0;
N1 += vec3(texture(textureArray, vec3(st, ATLAS_INDEX_PERLIN_NOISE_NM))) * 2.0 - 1.0;
rotationmatrix(radians(-4.0 * sin(osg_SimulationTime * 0.003)), RotationMatrix);
st = vec2(waterTex1 * RotationMatrix + disdis * sca2) * windScale;
N0 += vec3(texture(textureArray, vec3(st, ATLAS_INDEX_WAVES_VERT10_NM))) * 2.0 - 1.0;
st = vec2(waterTex1 * RotationMatrix + disdis * sca) * windScale;
N1 += vec3(texture(textureArray, vec3(st, ATLAS_INDEX_PERLIN_NOISE_NM))) * 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);
vec3 specular_color = vec3(specular_light * earthShade) * pow(max(0.0, dot(N, Hv)), water_shininess) * 6.0;
// secondary reflection of sky irradiance
vec3 ER = E - 2.0 * N * dot(E,N);
float ctrefl = dot(vec3(0.0,0.0,1.0), -normalize(ER));
//float fresnel = -0.5 + 8.0 * (1.0-smoothstep(0.0,0.4, dot(E,N)));
float fresnel = 8.0 * (1.0-smoothstep(0.0,0.4, dot(E,N)));
//specular_color += (ctrefl*ctrefl) * fresnel* specular_light.rgb;
specular_color += ((0.15*(1.0-ctrefl* ctrefl) * fresnel) - 0.3) * specular_light.rgb * earthShade;
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;
//intensity = length(specular_light.rgb);
ambient_light.rgb = max(specular_light.rgb * earthShade, vec3(0.05, 0.05, 0.05));
//ambient_light.rgb = max(intensity * normalize(vec3 (0.33, 0.4, 0.5)), vec3 (0.1,0.1,0.1));
ambient_light.a = 1.0;
// compute object shadow effect
float shadowValue = getShadowing();
specular = specular * shadowValue;
refl = refl * (0.7 + 0.3 *shadowValue);
texel = refl + specular * smoothstep(0.3, 0.6, ground_scattering);
// For the clustered lighting function we use the simple up direction (Normal) to get an
// approximate lighting contribution, as the procedural normal map is done afterwards.
//texel += vec4(getClusteredLightsContribution(ecPosition.xyz, Normal, vec3(1.0)), 0.0) * light_distance_fading(dist) * 2.0 * pow(max(0.0,dot(E,N)), water_shininess);
if (dist < 10000.0)
{
float foamSlope = 0.10 + 0.1 * windScale;
float waveSlope = N.g;
if ((windEffect >= 8.0) && (waveSlope >= foamSlope)) {
//add foam
st = vec2(waterTex2 * tscale) * 25.0;
vec4 foam_texel = texture(textureArray, vec3(st, ATLAS_INDEX_SEA_FOAM) );
texel = mix(texel, max(texel, texel + foam_texel), smoothstep(0.01, 0.50, N.g));
}
}
texel *= ambient_light;
return texel;
}

View file

@ -57,7 +57,7 @@ void main()
} else {
// The Landclass for this particular fragment. This can be used to
// index into the atlas textures.
int lc = int(texture2D(landclass, gl_TexCoord[0].st).r * 255.0 + 0.5);
int lc = int(texture2D(landclass, gl_TexCoord[0].st).g * 255.0 + 0.5);
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -813,6 +813,7 @@ Started September 2000 by David Megginson, david@megginson.com
<draw-heliports type="bool" userarchive="y">false</draw-heliports>
<draw-traffic type="bool" userarchive="y">false</draw-traffic>
<draw-flight-history type="bool" userarchive="y">false</draw-flight-history>
<draw-pois type="bool" userarchive="y">true</draw-pois>
<magnetic-headings type="bool" userarchive="y">true</magnetic-headings>
<centre-on-aircraft type="bool" userarchive="y">true</centre-on-aircraft>
@ -1021,6 +1022,13 @@ Started September 2000 by David Megginson, david@megginson.com
<speed type="double">1.0</speed>
<codec>libx265</codec>
</video>
<model>
<civilian type="bool">true</civilian>
<livery>
<fresnel type="double">0.7</fresnel>
<shininess type="double">-0.5</shininess>
</livery>
</model>
</sim>
<!-- accelerations -->
<accelerations>
@ -1459,6 +1467,7 @@ Started September 2000 by David Megginson, david@megginson.com
<constraint-gap-m type="float" userarchive="y">1.0</constraint-gap-m>
<sample-ratio type="float" userarchive="y">1.0</sample-ratio>
<vertical-scale type="float" userarchive="y">1.0</vertical-scale>
<separate-water-mesh type="bool" userarchive="y">false</separate-water-mesh>
</elevation-mesh>
</scenery>
<earthview>

View file

@ -39,82 +39,7 @@
<nasal>
<!-- Generalize all this, turn into helpers and load defaults via XML -->
<open><![CDATA[
var MAX_RUNWAYS = 28; # number of entries at KEDW
var DIALOG = cmdarg();
var listeners = [];
## "prologue" currently required by the canvas-generic-map
var dialog_name ="airports"; #TODO: use substr() and cmdarg() to get this dynamically
var dialog_property = func(p) return "/sim/gui/dialogs/airports/"~p; #TODO: generalize using cmdarg
var DIALOG_CANVAS = gui.findElementByName(DIALOG, "airport-selection");
setprop("/sim/gui/dialogs/airports/selected-airport/lat", 0);
setprop("/sim/gui/dialogs/airports/selected-airport/lon", 0);
setprop("/sim/gui/dialogs/airports/selected-airport/rwy", "");
setprop("/sim/gui/dialogs/airports/selected-airport/parkpos", "");
setprop("/sim/gui/dialogs/airports/mode", "search");
setprop("/sim/gui/dialogs/airports/display-mode", "0");
setprop("/sim/gui/dialogs/airports/list", "");
if (getprop("/sim/gui/dialogs/airports/display-taxiways") == "") {
setprop("/sim/gui/dialogs/airports/display-taxiways", "1");
}
if (getprop("/sim/gui/dialogs/airports/display-parking") == "") {
setprop("/sim/gui/dialogs/airports/display-parking", "0");
}
if (getprop("/sim/gui/dialogs/airports/display-tower") == "") {
setprop("/sim/gui/dialogs/airports/display-tower", "1");
}
if (getprop("/sim/gui/dialogs/airports/show-helipads") == "") {
setprop("/sim/gui/dialogs/airports/show-helipads", "1");
}
# Start with the closest airport
var airport_id = airportinfo().id;
# Retrieve METAR
fgcommand("request-metar", var n = props.Node.new({ "path": "/sim/gui/dialogs/airports/selected-airport/metar",
"station": airport_id}));
var dlg = props.globals.getNode("/sim/gui/dialogs/airports", 1);
var avail_runways = dlg.getNode("available-runways", 1);
var avail_parking = {};
if (dlg.getNode("list") == nil)
dlg.getNode("list", 1).setValue("");
var airportlist = dlg.getNode("list");
var mode = {
runway: dlg.getNode("use_runway", 1),
bestrunway: dlg.getNode("use_best_runway", 1),
parkpos: dlg.getNode("use_parkpos", 1)
};
var set_radio = func(m) {
foreach (k; keys(mode)) {
mode[k].setBoolValue(m == k);
}
}
var initialized = 0;
foreach (k; keys(mode)) {
if (mode[k].getType() == "NONE" or initialized) {
mode[k].setBoolValue(0);
} else {
initialized += mode[k].getBoolValue();
}
}
if (!initialized) {
set_radio("bestrunway");
}
var update_info = func {
var update_info = func(open = 0) {
var info = airportinfo(airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/id", airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/name", info.name);
@ -124,7 +49,9 @@
setprop("/sim/gui/dialogs/airports/selected-airport/elevation-ft", 3.28 * info.elevation);
setprop("/sim/gui/dialogs/airports/selected-airport/rwy", "");
setprop("/sim/gui/dialogs/airports/selected-airport/parkpos", "");
if (!open) {
AirportChart.getController().setPosition(info.lat, info.lon);
}
if (info.has_metar) {
# Retrieve an updated METAR, and indicate that we've not got one currently.
@ -219,6 +146,81 @@
gui.dialog_update("airports", "runway-list");
}
var MAX_RUNWAYS = 28; # number of entries at KEDW
var DIALOG = cmdarg();
var listeners = [];
## "prologue" currently required by the canvas-generic-map
var dialog_name ="airports"; #TODO: use substr() and cmdarg() to get this dynamically
var dialog_property = func(p) return "/sim/gui/dialogs/airports/"~p; #TODO: generalize using cmdarg
var DIALOG_CANVAS = gui.findElementByName(DIALOG, "airport-selection");
var displayMode = getprop("/sim/gui/dialogs/airports/display-mode");
if ((displayMode != 0) and (displayMode != 1)) {
setprop("/sim/gui/dialogs/airports/display-mode", 0);
}
var displayTaxiways = getprop("/sim/gui/dialogs/airports/display-taxiways");
if ((displayTaxiways != 0) and (displayTaxiways != 1)) {
setprop("/sim/gui/dialogs/airports/display-taxiways", 1);
}
var displayParking = getprop("/sim/gui/dialogs/airports/display-parking");
if ((displayParking != 0) and (displayParking != 1)) {
setprop("/sim/gui/dialogs/airports/display-parking", 0);
}
var displayTower = getprop("/sim/gui/dialogs/airports/display-tower");
if ((displayTower != 0) and (displayTower != 1)) {
setprop("/sim/gui/dialogs/airports/display-tower", 1);
}
var showHelipads = getprop("/sim/gui/dialogs/airports/show-helipads");
if ((showHelipads != 0) and (showHelipads != 1)) {
setprop("/sim/gui/dialogs/airports/show-helipads", 0);
}
var dlg = props.globals.getNode("/sim/gui/dialogs/airports", 1);
var avail_runways = dlg.getNode("available-runways", 1);
var avail_parking = {};
# Start with the closest airport
var airport_id = airportinfo().id;
update_info(open = 1);
# Retrieve METAR
fgcommand("request-metar", var n = props.Node.new({ "path": "/sim/gui/dialogs/airports/selected-airport/metar",
"station": airport_id}));
dlg.getNode("list", 1).setValue("");
var airportlist = dlg.getNode("list");
var mode = {
runway: dlg.getNode("use_runway", 1),
bestrunway: dlg.getNode("use_best_runway", 1),
parkpos: dlg.getNode("use_parkpos", 1)
};
var set_radio = func(m) {
foreach (k; keys(mode)) {
mode[k].setBoolValue(m == k);
}
}
var initialized = 0;
foreach (k; keys(mode)) {
if (mode[k].getType() == "NONE" or initialized) {
mode[k].setBoolValue(0);
} else {
initialized += mode[k].getBoolValue();
}
}
if (!initialized) {
set_radio("bestrunway");
}
var listbox = func {
airport_id = pop(split(" ", airportlist.getValue()));
airport_id = substr(airport_id, 1, size(airport_id) - 2); # strip parentheses
@ -820,11 +822,9 @@
{
var range = AirportChart.getScreenRange();
if (e.deltaY >0) {
if (range < 10000)
AirportChart.setScreenRange(range*range_step);
AirportChart.setScreenRange(math.min(range*range_step, 10000));
} else {
if (range > 100)
AirportChart.setScreenRange(range/range_step);
AirportChart.setScreenRange(math.max(range/range_step, 100));
}
setprop("/sim/gui/dialogs/airports/zoom-range", AirportChart.getScreenRange());
});
@ -893,8 +893,7 @@
<command>nasal</command>
<script>
var range = AirportChart.getScreenRange();
if (range &lt; 10000)
AirportChart.setScreenRange(range*range_step);
AirportChart.setScreenRange(math.min(range*range_step, 10000));
setprop("/sim/gui/dialogs/airports/zoom-range", AirportChart.getScreenRange());
</script>
</binding>
@ -902,8 +901,8 @@
<text>
<name>zoomdisplay</name>
<label>MMMMMMMMMMMMM</label>
<format>Zoom %d</format>
<label>XXXXXXXXXXXX</label>
<format>Zoom: %d%%</format>
<property>/sim/gui/dialogs/airports/zoom-range</property>
<live>true</live>
</text>
@ -918,8 +917,7 @@
<command>nasal</command>
<script>
var range = AirportChart.getScreenRange();
if (range &gt; 100)
AirportChart.setScreenRange(range/range_step);
AirportChart.setScreenRange(math.max(range/range_step, 100));
setprop("/sim/gui/dialogs/airports/zoom-range", AirportChart.getScreenRange());
</script>
</binding>

View file

@ -1,5 +1,33 @@
<?xml version="1.0"?>
<PropertyList>
<nasal>
<open>
<![CDATA[
var self = cmdarg();
var icao = self.getNode("nasal/params/param/icao");
if (props.getNode("/sim/atc/freq-airport")!=nil) {
icao = props.getNode("/sim/atc/freq-airport");
}
var dialogTitle = sprintf("Airportfrequencies %s", icao.getValue());
self.getNode("text/label").setValue(dialogTitle);
var apt = airportinfo(icao.getValue());
var frequencies = apt.comms();
var textgroup = self.getNode("group").getNode("group-template");
var i = 0;
foreach (var c; frequencies) {
var target = self.getNode("group").getChild("group", i, 1);
props.copy(textgroup, target);
i = i + 1;
target.getNode("text/label").setValue(c.ident);
var formattedFreq = sprintf("%.3f MHz", c.frequency);
target.getNode("text[1]/label").setValue(formattedFreq);
target.getNode("button/binding/value").setValue(c.frequency);
target.getNode("button[1]/binding/value").setValue(c.frequency);
target.getNode("enabled").setValue(1);
}
]]>
</open>
</nasal>
<name>atc-freq-display</name>
<layout>vbox</layout>

View file

@ -1,12 +1,37 @@
<?xml version="1.0"?>
<PropertyList>
<nasal>
<open>
<![CDATA[
var self = cmdarg();
var dlgname = self.getNode("name").getValue();
self.getNode("group").removeChildren("button");
var textgroup = self.getNode("group").getNode("button-template");
var apts = findAirportsWithinRange(50);
if (size(apts) > 0) {
forindex (var i; apts) {
var target = self.getNode("group").getChild("button", i, 1);
props.copy(textgroup, target);
target.getNode("legend").setValue(apts[i].id);
target.getNode("binding/value").setValue(apts[i].id);
target.getNode("enabled").setValue(1);
}
props.dump(target);
} else {
self.getNode("text/enabled").setValue(1);
}
]]>
</open>
</nasal>
<name>atc-freq-search</name>
<layout>vbox</layout>
<text>
<label>Display Airport Frequencies</label>
<label>Display Nearest Airport Frequencies</label>
</text>
<hrule/>
<group>
@ -17,8 +42,13 @@
<enabled>false</enabled>
<legend>ICAO</legend>
<binding>
<command>ATC-freq-display</command>
<icao type="string">ICAO</icao>
<command>property-assign</command>
<property>/sim/atc/freq-airport</property>
<value type="string">ICAO</value>
</binding>
<binding>
<command>dialog-show</command>
<dialog-name>atc-freq-display</dialog-name>
</binding>
<binding>
<command>dialog-close</command>
@ -53,14 +83,20 @@
<empty><stretch>true</stretch></empty>
<button>
<legend>OK</legend>
<legend>Search</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>ATC-freq-display</command>
<command>dialog-show</command>
<dialog-name>atc-freq-display</dialog-name>
<!--
<params>
<icao type="string">ICAO</icao>
</params>
-->
</binding>
<binding>
<command>dialog-close</command>
@ -77,8 +113,6 @@
<command>dialog-close</command>
</binding>
</button>
<empty><stretch>true</stretch></empty>
</group>
</PropertyList>

View file

@ -204,12 +204,25 @@
<col>2</col>
<min>0.0</min>
<max>1.0</max>
<step>0.05</step>
<live>true</live>
<property>/environment/sea/surface/ice-cover</property>
<binding>
<command>dialog-apply</command>
<object-name>ice-cover</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
<![CDATA[
if (getprop( "/environment/sea/surface/ice-cover" ) < 0.05 ) {
setprop( "/environment/surface/ice-cover", 0 );
} else {
setprop( "/environment/surface/ice-cover", 1 );
}
]]>
</script>
</binding>
</slider>
<text>

View file

@ -41,7 +41,8 @@
</text>
<button>
<legend>Replay in-memory recording</legend>
<legend>Replay in-memory recording &lt;Ctrl-R&gt;</legend>
<equal>true</equal>
<enable><not><property>sim/replay/replay-state</property></not></enable>
<halign>left</halign>
<binding>
@ -55,6 +56,7 @@
<button>
<legend>Replay recording from file...</legend>
<equal>true</equal>
<halign>left</halign>
<binding>
<command>dialog-show</command>
@ -64,6 +66,7 @@
<button>
<legend>(Re)show replay dialogue</legend>
<equal>true</equal>
<enable><property>sim/replay/replay-state</property></enable>
<halign>left</halign>
<binding>
@ -74,6 +77,7 @@
<button>
<legend>Save in-memory recording to file...</legend>
<equal>true</equal>
<halign>left</halign>
<binding>
<command>dialog-show</command>
@ -98,6 +102,7 @@
<button>
<legend>Start Continuous recording to file</legend>
<equal>true</equal>
<halign>left</halign>
<enable>
<not>
@ -114,6 +119,7 @@
<button>
<legend>Stop Continuous recording to file</legend>
<equal>true</equal>
<halign>left</halign>
<enable>
<property>sim/replay/record-continuous</property>
@ -126,11 +132,6 @@
</binding>
</button>
<text>
<label>Settings</label>
<halign>left</halign>
</text>
<checkbox>
<property>sim/replay/record-continuous-compression</property>
<enable><not><property>sim/replay/record-continuous</property></not></enable>
@ -184,7 +185,7 @@
<hrule/>
<text>
<label>Continuous replay settings</label>
<label>Continuous replay</label>
</text>
<checkbox>

View file

@ -122,6 +122,19 @@ command interface /autopilot/route-manager/input:
<command>property-toggle</command>
</binding>
</checkbox>
<checkbox>
<label>Landmarks</label>
<halign>left</halign>
<property>/sim/gui/map/draw-pois</property>
<live>true</live>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>property-toggle</command>
</binding>
</checkbox>
<!--
<button>
<legend>Airways</legend>

View file

@ -509,7 +509,8 @@
<colspan>3</colspan>
<legend>ATC Services in range</legend>
<binding>
<command>ATC-freq-search</command>
<command>dialog-show</command>
<dialog-name>atc-freq-search</dialog-name>
</binding>
</button>

View file

View file

@ -305,6 +305,77 @@
</group>
<vrule/>
<group>
<layout>vbox</layout>
<halign>center</halign>
<valign>top</valign>
<text>
<label>Marker Pins</label>
</text>
<checkbox>
<halign>left</halign>
<label>Show</label>
<property>/sim/marker-pins/master</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
<hrule/>
<checkbox>
<halign>left</halign>
<label>Airports</label>
<property>/sim/marker-pins/airports</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
<checkbox>
<halign>left</halign>
<label>Navaids</label>
<property>/sim/marker-pins/navaids</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
<checkbox>
<halign>left</halign>
<label>Fixes</label>
<property>/sim/marker-pins/fixes</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
<checkbox>
<halign>left</halign>
<label>POI</label>
<property>/sim/marker-pins/pois</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
<hrule/>
<checkbox>
<halign>left</halign>
<label>Traffic</label>
<property>/sim/marker-pins/traffic</property>
<binding>
<command>dialog-apply</command>
</binding>
</checkbox>
</group>
</group>
<hrule/>

View file

@ -50,6 +50,7 @@
<item>
<name>video-start</name>
<enabled>true</enabled>
<binding>
<command>nasal</command>
<script>
@ -60,6 +61,7 @@
<item>
<name>video-stop</name>
<enabled>false</enabled>
<binding>
<command>nasal</command>
<script>
@ -592,7 +594,8 @@
<item>
<name>atc-in-range</name>
<binding>
<command>ATC-freq-search</command>
<command>dialog-show</command>
<dialog-name>atc-freq-search</dialog-name>
</binding>
</item>

View file

@ -125,6 +125,17 @@
<brief/>
</option>
<option>
<name>load-tape-create-video</name>
<description>load-tape-create-video</description>
</option>
<option>
<name>load-tape-fixed-dt</name>
<arg>value</arg>
<description>load-tape-fixed-dt</description>
</option>
<option>
<name>restore-defaults</name>
<description>restore-defaults-desc</description>