1
0
Fork 0

WS30: MR #267: Improved texture lookups from VS

Squashed commit of the following:

commit 115511888c20c53670eba17a82c81c9af99d7302
Author: vs <vs2009@mail.com>
Date:   Mon Dec 6 18:52:06 2021 +1000

    WS30 effects and shaders:

    Changelog:

    ws30-ALS-ultra.frag:

    - Ground textures lookups use their own coordinates separate from the landclass  texture lookup.

    - Partial derivatives dFdx and Dfdy are packed together in a vec4, so simple   multiplication to scale can be done in 1 instruction. dFdx = s and t components. dFdy  = p and q components. These must be scaled properly for ground texture access as ground  texture stretching and detiling of tex coords mean textures are scaled differently.

    - Added calculation of partial derivatives for texture coordinates used by the 5 non- base textures. dFdx() and dFdy() were called for nontrivial texture coordinate manipulation.

    - New control randomise_texture_lookups added at top of ws30-ALS-ultra.frag, in the  development tools section. Setting this to 1 will do a stress test of ground texture  array lookups. A fast random number generation function is used to assign each  landclass 4 random textures from the ground texture array - this is done by .  Performance will not be as bad in the full ALS port as some texture slots will better caching in memory - e.g. have 1 or a few variants.

    - Possible optimisation: use a 2nd or 3rd texture array for some of the non-base  texture slots that typically have 256, 512, or 1024 textures. The resolutions of these  arrays should change based on the largest loaded texture size in the active regional  definitions - this will allow taking full advantage of smaller texture sizes in some  areas. The disadvantage is some texture duplication with more slots.

    - Possible optimisation: offer the option to shrink textures by 50% or 25% - for  texture slots that use large textures like base or mix slots.

    - Very temporary - reduce procedural normal map features with photoscenery active  without breaking profiling, as the inputs to shaders are effect defaults or  placeholder (by request on ML).

    ----

    ws30-ALS-ultra.vert:
    - Start of conversion of geocentic world space xyz into lat/lon coords used for ground  texture lookups. Currently commented out as it's unknown what model space coords are  in (not geocentric it seems).

    ws20-ALS-landclass-search-functions.frag:

    - Add control for changing the ground texture array lookup function for debugging in  case old compilers/GPUs have issues. tex_lookup_type: 0: normal( textureGrad(), 1:  textureLod (manual Lod calculation), 2: texture() with no partial derivative  adjustment.

    - New get6_random_integers() will extract 6 limited random values from the full  precision of a 32 bit random value.

    - Old landclass_texel_size_m references are removed since textureSize() is used. There  are no 'const in float' arguments that may cause issues on AMD compilers.

    ----

    WS30-overlay effect (Inactive):

    - ws30-overlay.eff (derived from terrain-overlay.eff). Technique no "4" is used for two passes. The 1st pass is a copy of the ALS ultra pass (technique no "5") from ws30.eff.  The 2nd pass is the same as terrain-overlay.eff. The 2nd pass uses terrain- overlay.frag from WS2.

    - grass-ALS.vert copied to ws30-ovelay-ALS.vert. To do: needs texture coords that  don't change with tiles.

    - terrain-overlay-ALS.geom copied to ws30-overlay-ALS.geom. To do: uses gl_PositionIn [i].xy for position in the horizontal plane - assumes z is vertical. Tile model space  doesn't seem to match this.

    - WS3 doesn't seem to have a way of switching references to terrain-overlay.eff (which  inherits from terrain-default.eff) to the new ws3-overlay.eff (which needs to inherit  from ws30.eff). The ws3-overlay.eff included /might/ just work without any other changes: the first pass is the WS3 als ultra settings pass, and the second overlay pass is unchanged from WS2 (the same terrain overlay shaders should probably work apart from texcoords and rawpos not being correct).

    - Materials/base/materials-base.xml: ws30Road material: uncomment line declaring terrain-default as the effect. The target effect for ws30 roads is road-*.eff and it's added to ws30Road and ws30Freeway but commented out as it's not working currently.

    - Misc: large scale transitions are turned on in ws30-ALS-landclass-search-functions.frag by default. Grow landclass borders with large scale transitions is now on by default.

    ----

    Changes after the multi-texture support commit:

    ws30-ALS-ultra.vert

    - Added documentation: WS30 model space and z up space - for future people working on WS30, and people looking through shaders to rule out possibilities e.g. when fixing bugs, or interpreting visual bug reports.

    ws30-ALS-landclass-search-functions.frag:

    - For now, lookup_ground_texture_array() also looks up the relevant texture's index  based on an integer.

    - Add get_mixed_texel() - looks up texel for this fragment and any neighbors before mixing. Moves currently shared mixing code out of 3 fragment shaders.

    Misc: changed indentation from mixed tabs/spaces to spaces in ws30-ALS-ultra frag and vert. The indentation can be changed again when the porting is complete.

    ws30-ALS vert/frag and ws30-ALS-detailed vert/frag:

    - Add varying for ground texture coordiante, currently set to gl_TexCoord[0]. Apply texture stretching dimensions in fragment shaders.

    - Misc: varying rawPos is set to vec2 for now, as relPos.z+eye_alt might be faster. Misc: keep WS2 mixing logic for now , including turning off mixing via the alpha channel of the textures

    ----

    Changes after sending material parameters in uniform arrays commit:

    - Materials parameter for rock_strata is cast into an int so rock_strata==1 should work. Misc: Left over uniform for rock strata cleaned up.

    - ws30-ALS-ultra.frag and ws30-ALS-detailed.frag: Add missing mat_shininess for photoscenery case .
This commit is contained in:
Stuart Buchanan 2022-01-03 15:43:29 +00:00
parent 43fa71b70c
commit 3261f4a97c
12 changed files with 2333 additions and 849 deletions

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

@ -0,0 +1,962 @@
<?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>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>

View file

@ -182,7 +182,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>

View file

@ -635,7 +635,8 @@
<material n="3002">
<name>ws30Road</name>
<texture>osm2city/roads.png</texture>
<!-- <effect>Effects/terrain-default</effect> -->
<effect>Effects/terrain-default</effect>
<!-- <effect>Effects/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>
@ -664,6 +665,7 @@
<name>ws30Freeway</name>
<texture>osm2city/roads.png</texture>
<effect>Effects/terrain-default</effect>
<!-- <effect>Effects/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>

View file

@ -43,7 +43,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);
@ -157,21 +158,33 @@ int get_random_landclass(in vec2 co, in vec2 tile_size);
// 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
);
// 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
);
// End Test-phase code
////////////////////////
@ -270,16 +283,15 @@ 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);
// 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, landclass_texel_size_m, dx, dy,
lc, lc_n, num_unique_neighbors, mfact);
get_landclass_id(tile_coord, dxdy_gc, 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
@ -291,13 +303,23 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
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));
// 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[lc].st;
vec2 tileSize = vec2(fg_tileWidth, fg_tileHeight);
vec2 texture_scaling = tileSize.xy / stretch_dimensions.st;
vec2 st = texture_scaling.st * ground_tex_coord.st;
// Scale partial derivatives
vec4 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
@ -305,51 +327,25 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
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;
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;
} else
{
// 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;
// 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
// 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);
// Look up texture coordinates and scale of ground textures
// Landclass for this fragment
texel = lookup_ground_texture_array(tile_coord, lc, dx, dy);
//if (ground_tex_coord.x > 0.0) texel = vec4(1.0);
// 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]);
}
}
vec4 color = gl_Color * mat_ambient;
@ -359,6 +355,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 +377,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)&&(relPos.z +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,17 +392,21 @@ 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*(relPos.z -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;}
}
if (tquality_level > 3 && (flag == 1))
{
@ -417,9 +420,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 +512,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 (relPos.z +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 * (relPos.z)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
}
}
else if (rawPos.z +500.0 > snowlevel)
else if (relPos.z +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*(relPos.z -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, (relPos.z)));
}

View file

@ -25,7 +25,8 @@ 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;
@ -95,7 +96,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));
@ -110,6 +111,9 @@ void main()
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,7 +130,7 @@ 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);

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 = 130.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,7 +158,7 @@
// 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;
@ -181,7 +181,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 +190,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 +234,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 +263,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 +300,32 @@ int get_random_landclass(in vec2 co, in vec2 tile_size)
}
// Look up texture coordinates and stretching scale of ground textures
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)
/*
// 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;
g_texture_scale = tile_size.xy / g_texture_stretch_dim.xy;
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 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 +336,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 +369,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,35 +397,127 @@ 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;
// 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.
get_ground_texture_data(lc, tile_coord, st, g_texture_scale, dx, dy);
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).g * 255.0 + 0.5));
@ -411,13 +561,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 +773,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 +885,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 +910,7 @@ 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);
// Neighbor landclass ids
ivec4 lc_n = ivec4(lc);
@ -818,6 +972,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 +1141,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);

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,11 +24,11 @@
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;
// Sent packed into alpha channels
@ -76,227 +75,290 @@ 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));
//x = x - 0.5;
// use the asymptotics to shorten computations
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
void main()
{
vec4 light_diffuse;
vec4 light_ambient;
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight + vec3 (0.005, 0.005, 0.005);
moonLightColor = moonlight_perception (moonLightColor);
//float yprime_alt;
float yprime;
float lightArg;
float intensity;
float vertex_alt;
float scattering;
// 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.
rawPos = (fg_zUpTransform * gl_Vertex).xyz;
vec4 pos = gl_Vertex;
if (raise_vertex)
{
pos.z+=0.1;
gl_Position = gl_ModelViewProjectionMatrix * pos;
}
else gl_Position = ftransform();
// this code is copied from default.vert
ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
normal = gl_NormalMatrix * gl_Normal;
///////////////////////////////////////////
// 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));
grad_dir = normalize(gl_Normal.xy);
vec4 pos = gl_Vertex;
if (raise_vertex)
{
pos.z+=0.1;
gl_Position = gl_ModelViewProjectionMatrix * pos;
}
else gl_Position = ftransform();
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);
// 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;
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 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);
// this code is copied from default.vert
ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//orthoTexCoord = orthophotoTexCoord;
normal = gl_NormalMatrix * gl_Normal;
// here start computations for the haze layer
// we need several geometrical quantities
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
relPos = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
ecViewdir = (gl_ModelViewMatrix * (ep - 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);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// branch dependent on daytime
// branch dependent on daytime
if (terminator < 1000000.0) // the full, sunrise and sunset computation
{
// establish coordinates relative to sun position
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction
yprime = -dot(relPos, lightHorizon);
// this gets an altitude correction, higher terrain gets to see the sun earlier
yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
// two times terminator width governs how quickly light fades into shadow
// now the light-dimming factor
earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
// parametrized version of the Flightgear ground lighting function
// parametrized version of the Flightgear ground lighting function
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;}
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else
{mie_angle = 1.0;}
{mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.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 * scattering;
//light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
//light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
light_ambient.g = light_ambient.r * 0.4/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.4);
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;
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 * scattering;
//light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
//light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
light_ambient.g = light_ambient.r * 0.4/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.4);
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;
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
intensity = length(light_ambient.rgb);
light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 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.4, 0.7,earthShade) ));
}
// the haze gets the light at the altitude of the haze top if the vertex in view is below
// but the light at the vertex if the vertex is above
vertex_alt = max(vertex_alt,hazeLayerAltitude);
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
intensity = length(light_ambient.rgb);
light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 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.4, 0.7,earthShade) ));
}
// the haze gets the light at the altitude of the haze top if the vertex in view is below
// but the light at the vertex if the vertex is above
vertex_alt = max(vertex_alt,hazeLayerAltitude);
if (vertex_alt > hazeLayerAltitude)
{
if (dist > 0.8 * avisibility)
{
vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else
{
vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else // the faster, full-day version without lightfields
{
if (vertex_alt > hazeLayerAltitude)
{
if (dist > 0.8 * avisibility)
{
vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else
{
vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
} // End if (terminator < 1000000.0)
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, 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);
}
else
{
lightArg = (terminator/100000.0 - 10.0)/20.0;
light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.g = 0.907 + lightArg * 0.091;
light_diffuse.r = 0.904 + lightArg * 0.092;
light_diffuse.a = 1.0;
//light_ambient.b = 0.41 + lightArg * 0.08;
//light_ambient.g = 0.333 + lightArg * 0.06;
light_ambient.r = 0.316 + lightArg * 0.016;
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.0;
}
{
lightArg = (terminator/100000.0 - 10.0)/20.0;
light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.g = 0.907 + lightArg * 0.091;
light_diffuse.r = 0.904 + lightArg * 0.092;
light_diffuse.a = 1.0;
//light_ambient.b = 0.41 + lightArg * 0.08;
//light_ambient.g = 0.333 + lightArg * 0.06;
light_ambient.r = 0.316 + lightArg * 0.016;
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.0;
}
light_diffuse = light_diffuse * 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
// steep faces end up shaded more
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
// steep faces end up shaded more
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2);
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2);
// deeper shadows when there is lots of direct light
// deeper shadows when there is lots of direct light
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);
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
if (use_IR_vision)
{
light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5));
}
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);
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
if (use_IR_vision)
{
light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5));
}
// default lighting based on texture and material using the light we have just computed
light_diffuse_comp = light_diffuse;
//Testing phase code: ambient colours are not sent to fragement shader yet.
// They are all default except for water/ocean etc. currently
// Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0)
//To do: Fix this once ambient colour becomes available in the fragment shaders.
//const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
const vec4 ambient_color = vec4(1.0);
vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient);
light_diffuse_comp.a = yprime_alt;
gl_FrontColor.rgb = constant_term.rgb; // gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; // gl_BackColor.a = 0.0;
gl_FrontColor.a = mie_angle;
gl_BackColor.a = mie_angle;
setupShadows(ecPosition);
// default lighting based on texture and material using the light we have just computed
light_diffuse_comp = light_diffuse;
//Testing phase code: ambient colours are not sent to fragement shader yet.
// They are all default except for water/ocean etc. currently
// Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0)
//To do: Fix this once ambient colour becomes available in the fragment shaders.
//const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
const vec4 ambient_color = vec4(1.0);
vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient);
light_diffuse_comp.a = yprime_alt;
gl_FrontColor.rgb = constant_term.rgb; // gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; // gl_BackColor.a = 0.0;
gl_FrontColor.a = mie_angle;
gl_BackColor.a = mie_angle;
setupShadows(ecPosition);
}

View file

@ -43,6 +43,7 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec2 ground_tex_coord;
uniform sampler2D landclass;
uniform sampler2DArray textureArray;
@ -144,21 +145,33 @@ int get_random_landclass(in vec2 co, in vec2 tile_size);
// 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
);
// 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
);
// End Test-phase code
////////////////////////
@ -209,16 +222,15 @@ void main()
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);
get_landclass_id(tile_coord, dxdy_gc, 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
@ -226,9 +238,18 @@ void main()
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;
// Material properties.
vec4 mat_diffuse, mat_ambient, mat_specular;
float mat_shininess;
// 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[lc].st;
vec2 tileSize = vec2(fg_tileWidth, fg_tileHeight);
vec2 texture_scaling = tileSize.yx / stretch_dimensions.st;
vec2 st = texture_scaling.st * ground_tex_coord.st;
if (fg_photoScenery) {
mat_ambient = vec4(1.0,1.0,1.0,1.0);
@ -238,46 +259,26 @@ void main()
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;
// 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);
// 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);
// 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]);
}
}
vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient);
vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient);
// Testing code:
// Use rlc even when looking up textures to recreate the extra performance hit

View file

@ -27,6 +27,7 @@ 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;
@ -85,6 +86,9 @@ void main()
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
normal = gl_NormalMatrix * gl_Normal;
// Temporary value:
ground_tex_coord = gl_TexCoord[0].st;
// here start computations for the haze layer
// we need several geometrical quantities

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