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. --> 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"> <technique n="5">
<predicate> <predicate>
<and> <and>

View file

@ -635,7 +635,8 @@
<material n="3002"> <material n="3002">
<name>ws30Road</name> <name>ws30Road</name>
<texture>osm2city/roads.png</texture> <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-x0>0.25</line-feature-tex-x0>
<line-feature-tex-x1>0.375</line-feature-tex-x1> <line-feature-tex-x1>0.375</line-feature-tex-x1>
<line-feature-offset-m>0.75</line-feature-offset-m> <line-feature-offset-m>0.75</line-feature-offset-m>
@ -664,6 +665,7 @@
<name>ws30Freeway</name> <name>ws30Freeway</name>
<texture>osm2city/roads.png</texture> <texture>osm2city/roads.png</texture>
<effect>Effects/terrain-default</effect> <effect>Effects/terrain-default</effect>
<!-- <effect>Effects/road-high</effect> -->
<line-feature-tex-x0>0.625</line-feature-tex-x0> <line-feature-tex-x0>0.625</line-feature-tex-x0>
<line-feature-tex-x1>0.75</line-feature-tex-x1> <line-feature-tex-x1>0.75</line-feature-tex-x1>
<line-feature-offset-m>1.0</line-feature-offset-m> <line-feature-offset-m>1.0</line-feature-offset-m>

View file

@ -43,7 +43,8 @@
varying vec4 light_diffuse_comp; varying vec4 light_diffuse_comp;
varying vec3 normal; varying vec3 normal;
varying vec3 relPos; varying vec3 relPos;
varying vec3 rawPos; varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos; varying vec3 worldPos;
// Testing code: // Testing code:
//vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0); //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 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 // the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams. // 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. // Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance. // 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 // 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 // Create a mix factor weighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord, void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
out int landclass_id, out ivec4 neighbor_landclass_ids, out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor 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 // End Test-phase code
//////////////////////// ////////////////////////
@ -270,16 +283,15 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
vec4 mfact; 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. // with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail // Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord); // dFdx and dFdy are packed in a vec4 so multiplying everything
vec2 dy = dFdy(tile_coord); // 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, get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
lc, lc_n, num_unique_neighbors, mfact);
// The landclass id is used to index into arrays containing // The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as // 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_ambient = fg_ambientArray[lc];
vec4 mat_diffuse = fg_diffuseArray[lc]; vec4 mat_diffuse = fg_diffuseArray[lc];
vec4 mat_specular = fg_specularArray[lc]; vec4 mat_specular = fg_specularArray[lc];
vec2 st = gl_TexCoord[0].st;
// Testing code: // Testing code:
// Use rlc even when looking up textures to recreate the extra performance hit // 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 // 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)); // 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) { if (fg_photoScenery) {
// In the photoscenery case we don't have landclass or materials available, so we // In the photoscenery case we don't have landclass or materials available, so we
@ -305,9 +327,12 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
mat_ambient = vec4(0.2,0.2,0.2,1.0); mat_ambient = vec4(0.2,0.2,0.2,1.0);
mat_diffuse = vec4(0.8,0.8,0.8,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_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)); texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t));
} else { } else
{
// Color Mode is always AMBIENT_AND_DIFFUSE, which means // Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse, // using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray. // rather than the material color from ambientArray/diffuseArray.
@ -316,40 +341,11 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
mat_specular = fg_specularArray[lc]; mat_specular = fg_specularArray[lc];
mat_shininess = fg_dimensionsArray[lc].z; mat_shininess = fg_dimensionsArray[lc].z;
// Different textures have different have different dimensions. // Lookup the base texture texel for this fragment and any neighbors, with mixing
vec2 atlas_dimensions = fg_dimensionsArray[lc].st; texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
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. //if (ground_tex_coord.x > 0.0) texel = vec4(1.0);
// 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]);
}
} }
vec4 color = gl_Color * mat_ambient; 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); //vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
//texel = mix(texel, green, (mfact[2])); //texel = mix(texel, green, (mfact[2]));
//mix_texel = texel;
//detail_texel = texel;
vec4 t = texel;
int flag = 1; int flag = 1;
int mix_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))); //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; 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 = 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)); snow_texel.r = snow_texel.r * (0.9 + 0.05 * (noise_10m + noise_5m));
@ -393,16 +392,20 @@ 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) ); 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)) if ((tquality_level > 2) && (mix_flag == 1))
{ {
// Mix texture is material texture 15, which is mapped to the b channel of fg_textureLookup1 // 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); //int tex2 = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2)); //mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
if (mix_texel.a < 0.1) { mix_flag = 0;} 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)) 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 // 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); //int tex3 = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
detail_texel = texture(textureArray, vec3(stprime, tex3)); //detail_texel = texture(textureArray, vec3(stprime, tex3));
if (detail_texel.a < 0.1) { flag = 0;} 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 // 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) ); 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 // mix snow
if (rawPos.z +500.0 > snowlevel) if (relPos.z +500.0 > snowlevel)
{ {
snow_alpha = smoothstep(0.75, 0.85, abs(steepness)); snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
//texel = mix(texel, snow_texel, texel_snow_fraction); //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 = 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 vec4 light_diffuse_comp;
varying vec3 normal; varying vec3 normal;
varying vec3 relPos; varying vec3 relPos;
varying vec3 rawPos; varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos; varying vec3 worldPos;
//varying vec2 orthoTexCoord; //varying vec2 orthoTexCoord;
varying vec4 eyePos; varying vec4 eyePos;
@ -95,7 +96,7 @@ void main()
float vertex_alt; float vertex_alt;
float scattering; float scattering;
rawPos = (fg_zUpTransform * gl_Vertex).xyz; rawPos = (fg_zUpTransform * gl_Vertex).xy;
worldPos = fg_modelOffset + gl_Vertex.xyz; worldPos = fg_modelOffset + gl_Vertex.xyz;
eyePos = gl_ModelViewMatrix * gl_Vertex; eyePos = gl_ModelViewMatrix * gl_Vertex;
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0)); 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; normal = gl_NormalMatrix * gl_Normal;
//nvec = (gl_NormalMatrix * gl_Normal).xy; //nvec = (gl_NormalMatrix * gl_Normal).xy;
// Temporary value:
ground_tex_coord = gl_TexCoord[0].st;
// here start computations for the haze layer // here start computations for the haze layer
// we need several geometrical quantities // we need several geometrical quantities
@ -126,7 +130,7 @@ void main()
float dist = length(relPos); float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m // 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); 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 // Enable large scale transitions: 1=on, 0=off
// Disable use landclass texel scale transition, if using this. // 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. // 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. // Note: transitions occur on both sides of the landclass borders.
// The width of the transition is equal to 2x this value. // The width of the transition is equal to 2x this value.
// Default: 100m // 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 // 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) // 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 // This works by changing the weighting in the transition region using a
// noise lookup // noise lookup
// Possibe values: 0=off, 1=on. Default:0 // 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 // Possible values: 0 = texture source, 1 = math source
// The texture source still shows some tiling. The math source detiles better, but might // The texture source still shows some tiling. The math source detiles better, but might
// be slightly slower. // 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: // 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. // 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. // Useful for checking texture rendering and scenery.
// The compiler will likely optimise out the haze and lighting calculations. // 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 // End of test phase controls
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
@ -225,6 +234,7 @@
// Uniforms used by landclass search functions. // Uniforms used by landclass search functions.
// If any uniforms change name or form, remember to update here and in fragment shaders. // If any uniforms change name or form, remember to update here and in fragment shaders.
uniform sampler2D landclass; uniform sampler2D landclass;
uniform sampler2DArray textureArray; uniform sampler2DArray textureArray;
uniform sampler2D perlin; uniform sampler2D perlin;
@ -253,6 +263,33 @@ vec2 tile_size = vec2(fg_tileHeight , fg_tileWidth);
float rand2D(in vec2 co); float rand2D(in vec2 co);
float Noise2D(in vec2 coord, in float wavelength); 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. // Create random landclasses without a texture lookup to stress test.
// Each square of square_size in m is assigned a random landclass value. // Each square of square_size in m is assigned a random landclass value.
int get_random_landclass(in vec2 co, in vec2 tile_size) 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 /*
// 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, 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 // Look up stretching dimensions of ground textures in m - scaled to
// fit in [0..1], so rescale // fit in [0..1], so rescale
vec2 g_texture_stretch_dim = fg_dimensionsArray[lc].st; vec2 g_texture_stretch_dim = fg_dimensionsArray[lc].st;
g_texture_scale = tile_size.xy / g_texture_stretch_dim.xy; g_texture_scale = tile_size.xy / g_texture_stretch_dim.xy;
// Correct partial derivatives to account for stretching of different textures // Correct partial derivatives to account for stretching of different textures
dx = dx * g_texture_scale; dFdx_and_dFdy = dFdx_and_dFdy * vec4(g_texture_scale.st, g_texture_scale.st);
dy = dy * g_texture_scale;
// Ground texture coords // Ground texture coords
st = g_texture_scale * tile_coord.st; 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 // 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 // many base texture lookups, see if optimising to handle many inputs helps
// (vectorising Noise2D versus just many texture calls) // (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, 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; vec2 pnoise;
// Ratio tile dimensions are stretched relative to s. // 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) 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; st = ground_texture_scale.st * (tile_coord * stretch_r).ts;
// Get back original partial derivatives by undoing // Get back original partial derivatives by undoing
// previous texture stretching adjustment done in get_ground_data // previous texture stretching adjustment done in get_ground_data
dx = dx / ground_texture_scale.st; dxdy = dxdy / vec4(ground_texture_scale.st, ground_texture_scale.st);
dy = dy / ground_texture_scale.st;
// Recalculate new derivatives // Recalculate new derivatives
dx = dx.ts * ground_texture_scale.st * stretch_r.ts; vec2 factor = ground_texture_scale.st * stretch_r.ts;
dy = dy.ts * ground_texture_scale.st * stretch_r.ts; dxdy.st = dxdy.ts * factor;
dxdy.pq = dxdy.qp * factor;
} }
if (pnoise[1] >= 0.5) if (pnoise[1] >= 0.5)
{ {
st = -st; dx = -dx; dy = -dy; st = -st; dxdy = -dxdy;
} }
dFdx_and_dFdy = dxdy;
return st; 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 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 // the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams. // 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, vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec2 dx, in vec2 dy) in vec4 dFdx_and_dFdy)
{ {
// Testing: may be able to save 1 or 2 op slots by combining dx/dy in a vec4 and // 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. // 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. // Only 1 place so far that just multiplies everything by a scalar.
vec2 st; vec2 st;
vec2 g_tex_coord = ground_texture_coord;
vec2 g_texture_scale; vec2 g_texture_scale;
vec4 texel; vec4 texel;
int lc = landclass_id; 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); // Debugging: multiple texture lookup functions if there are issues
uint tex1 = uint(fg_textureLookup1[lc].r * 255.0 + 0.5); // with old GPUs and compilers.
texel = textureGrad(textureArray, vec3(st, tex1), dx, dy); 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; 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 // Landclass sources: texture or random
int read_landclass_id(in vec2 tile_coord) int read_landclass_id(in vec2 tile_coord)
{ {
vec2 dx = dFdx(tile_coord.st);
vec2 dy = dFdy(tile_coord.st);
int lc; int lc;
if (landclass_source == 0) lc = (int(texture2D(landclass, tile_coord.st).g * 255.0 + 0.5)); 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 vec4 dFdx_and_dFdy,
int lookup_landclass_id(in vec2 tile_coord, in vec2 dx, in vec2 dy,
out ivec4 neighbor_texel_landclass_ids, out ivec4 neighbor_texel_landclass_ids,
out int number_of_unique_neighbors_found, out vec4 landclass_neighbor_texel_weights) 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 // Number of unique neighbours found
int num_n = 0; 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 // 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 // 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. // 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 // 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 frequency_g_n = 1000.0;
const float cutoff = 1.0/frequency_g_n; 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 // 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 // Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord, void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
out int landclass_id, out ivec4 neighbor_landclass_ids, out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor out int num_unique_neighbors,out vec4 mix_factor
) )
{ {
// Each tile has 1 texture containing landclass ids stetched over it // Each tile has 1 texture containing landclass ids stetched over it
// Landclass source type: 0=texture, 1=random squares // Landclass source type: 0=texture, 1=random squares
// Controls are defined at global scope. const int landclass_source // Controls are defined at global scope.
float ts = landclass_texel_size_m;
vec2 sz = tile_size; vec2 sz = tile_size;
vec4 dxdy = dFdx_and_dFdy;
// Number of unique neighbors found // Number of unique neighbors found
int num_n = 0; int num_n = 0;
@ -756,7 +910,7 @@ void get_landclass_id(in vec2 tile_coord,
// Number of unique neighbors in neighboring texels // Number of unique neighbors in neighboring texels
int num_n_tx = 0; 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 // Neighbor landclass ids
ivec4 lc_n = ivec4(lc); ivec4 lc_n = ivec4(lc);
@ -818,6 +972,11 @@ if ( (enable_large_scale_transition_search == 1) &&
// landclass. // 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 // +s direction
vec2 dir = vec2(steps.s, 0.0); 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 // Decide whether to extrude furthest neighbor or closest neighbor onto lc
float grow_n1 = get_growth_priority(lc_n[0],lc_n[1]); 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); mfact[1] = clamp(mfact[1],0.0,1.0);

View file

@ -22,6 +22,16 @@
// Possible values: 0:Normal, 1:Just the texture. // Possible values: 0:Normal, 1:Just the texture.
const int remove_haze_and_lighting = 0; const int remove_haze_and_lighting = 0;
// Randomise texture lookups for 5 non-base textures e.g. mix_texture, detaile_texture etc.
// Each landclass is assigned 5 random textures from the ground texture array.
// This simulates a worst case possible texture lookup scenario, without needing access to material parameters.
// This does not simulate multiple texture sets, of which there may be up-to 4.
// The performance will likely be worse than in a real situation - there might be fewer textures
// for mix, detail and other textures. This might be easier on the GPUs texture caches.
// Possible values: 0: disabled (default),
// 1: enabled,
// 2: remove texture array lookups for 5 textures - only base texture + neighbour base textures
const int randomise_texture_lookups = 0;
// //
// End of test phase controls // End of test phase controls
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
@ -43,8 +53,9 @@
varying vec4 light_diffuse_comp; varying vec4 light_diffuse_comp;
varying vec3 normal; varying vec3 normal;
varying vec3 relPos; varying vec3 relPos;
varying vec3 rawPos; varying vec2 ground_tex_coord;
varying vec3 worldPos; varying vec3 worldPos;
varying vec2 rawPos;
// Testing code: // Testing code:
//vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0); //vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
varying vec3 ecViewdir; varying vec3 ecViewdir;
@ -89,7 +100,6 @@ uniform float osg_SimulationTime;
uniform int wind_effects; uniform int wind_effects;
uniform int cloud_shadow_flag; uniform int cloud_shadow_flag;
uniform int rock_strata;
uniform int use_searchlight; uniform int use_searchlight;
uniform int use_landing_light; uniform int use_landing_light;
uniform int use_alt_landing_light; uniform int use_alt_landing_light;
@ -100,12 +110,20 @@ uniform int swatch_size; //in metres, typically 1000 or 2000
uniform float fg_tileWidth; uniform float fg_tileWidth;
uniform float fg_tileHeight; uniform float fg_tileHeight;
uniform bool fg_photoScenery; uniform bool fg_photoScenery;
// Material parameters, from material definitions and effect defaults, for each landclass.
// xsize and ysize
uniform vec4 fg_dimensionsArray[128]; uniform vec4 fg_dimensionsArray[128];
// RGBA ambient color
uniform vec4 fg_ambientArray[128]; uniform vec4 fg_ambientArray[128];
// RGBA diffuse color
uniform vec4 fg_diffuseArray[128]; uniform vec4 fg_diffuseArray[128];
// RGBA specular color
uniform vec4 fg_specularArray[128]; uniform vec4 fg_specularArray[128];
// Indicies of textures in the ground texture array for different
// texture slots (grain, gradient, dot, mix, detail) for each landclass
uniform vec4 fg_textureLookup1[128]; uniform vec4 fg_textureLookup1[128];
uniform vec4 fg_textureLookup2[128]; uniform vec4 fg_textureLookup2[128];
// Each element of a vec4 contains a different materials parameter.
uniform vec4 fg_materialParams1[128]; uniform vec4 fg_materialParams1[128];
uniform vec4 fg_materialParams2[128]; uniform vec4 fg_materialParams2[128];
@ -147,9 +165,9 @@ vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
float detail_fade (in float scale, in float angle, in float dist) float detail_fade (in float scale, in float angle, in float dist)
{ {
float fade_dist = 2000.0 * scale * angle/max(pow(steepness,4.0), 0.1); float fade_dist = 2000.0 * scale * angle/max(pow(steepness,4.0), 0.1);
return 1.0 - smoothstep(0.5 * fade_dist, fade_dist, dist); return 1.0 - smoothstep(0.5 * fade_dist, fade_dist, dist);
} }
////////////////////////// //////////////////////////
@ -159,15 +177,53 @@ return 1.0 - smoothstep(0.5 * fade_dist, fade_dist, dist);
// These should be sent as uniforms // These should be sent as uniforms
// Tile dimensions in meters // Tile dimensions in meters
// vec2 tile_size = vec2(tile_width , tile_height); // vec2 tile_size = vec2(fg_tileWidth , fg_tileHeight);
// Testing: texture coords are sent flipped right now: // Testing: texture coords are sent flipped right now:
// Note tile_size is defined in the shader include: ws30-landclass-search-functions.frag. // Note tile_size is defined in the shader include: ws30-landclass-search-functions.frag.
// vec2 tile_size = vec2(tile_height , tile_width); //vec2 tile_size = vec2(fg_tileHeight , fg_tileWidth);
// Uniform array lookup functions example:
// Access data[] as if it was a 1-d array of floats
// with data sorted as rows of data values for each row of texture variants
// using index for the relevant value
/*
float getFloatFromArrayData(int i)
{
int n = int(floor(float(i/4.0)));
vec4 v4 = someArray[n];
int index_within_v4 = int(mod(float(i),4.0));
float value = v4[index_within_v4];
return value;
}
vec4 getVec4FromArrayData(int i)
{
return (vec4(getFloatFromArrayData(i), getFloatFromArrayData(i+1), getFloatFromArrayData(i+2), getFloatFromArrayData(i+3)));
}
*/
// From noise.frag // From noise.frag
float rand2D(in vec2 co); float rand2D(in vec2 co);
// 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
);
// These functions, and other function they depend on, are defined // These functions, and other function they depend on, are defined
// in ws30-ALS-landclass-search.frag. // in ws30-ALS-landclass-search.frag.
@ -182,45 +238,56 @@ 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 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 // the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams. // 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, vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec2 dx, in vec2 dy); in vec4 dFdx_and_dFdy);
// Look up the landclass id [0 .. 255] for this particular fragment. // Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance. // 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 // 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 // Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord, void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
out int landclass_id, out ivec4 neighbor_landclass_ids, out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor 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 // End Test-phase code
//////////////////////// ////////////////////////
void main() void main()
{ {
float alt; float alt;
yprime_alt = light_diffuse_comp.a; yprime_alt = light_diffuse_comp.a;
//diffuse_term.a = 1.0; //diffuse_term.a = 1.0;
mie_angle = gl_Color.a; mie_angle = gl_Color.a;
float effective_scattering = min(scattering, cloud_self_shading); float effective_scattering = min(scattering, cloud_self_shading);
// distance to fragment // distance to fragment
float dist = length(relPos); float dist = length(relPos);
// angle of view vector with horizon // angle of view vector with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist; float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
// float altitude of fragment above sea level // float altitude of fragment above sea level
float msl_altitude = (relPos.z + eye_alt); float msl_altitude = (relPos.z + eye_alt);
// vec3 shadedFogColor = vec3(0.65, 0.67, 0.78); // vec3 shadedFogColor = vec3(0.65, 0.67, 0.78);
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88); vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
// this is taken from default.frag // this is taken from default.frag
vec3 n; vec3 n;
@ -243,11 +310,11 @@ float msl_altitude = (relPos.z + eye_alt);
// Wind motion of the overlay noise simulating movement of vegetation and loose debris // Wind motion of the overlay noise simulating movement of vegetation and loose debris
vec2 windPos; vec2 windPos;
if (wind_effects > 1) if (wind_effects > 1)
{ {
float windSpeed = length(vec2 (WindE,WindN)) /3.0480; float windSpeed = length(vec2 (WindE,WindN)) /3.0480;
// interfering sine wave wind pattern // interfering sine wave wind pattern
@ -264,60 +331,65 @@ if (wind_effects > 1)
windPos = vec2 (rawPos.x + WindN * timeArg, rawPos.y + WindE * timeArg); windPos = vec2 (rawPos.x + WindN * timeArg, rawPos.y + WindE * timeArg);
} }
else else
{ {
windPos = rawPos.xy; windPos = rawPos.xy;
} }
// get noise at different wavelengths in units of swatch_size // get noise at different wavelengths in units of swatch_size
// original assumed 4km texture. // original assumed 4km texture.
// used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow // used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow
// 50m: detail texel // 50m: detail texel
// 250m: detail texel // 250m: detail texel
// 500m: distortion and overlay // 500m: distortion and overlay
// 1500m: overlay, detail, dust, fog // 1500m: overlay, detail, dust, fog
// 2000m: overlay, detail, snow, fog // 2000m: overlay, detail, snow, fog
// Perlin noise // Perlin noise
float noise_10m = Noise2D(rawPos.xy, 10.0); float noise_10m = Noise2D(rawPos.xy, 10.0);
float noise_5m = Noise2D(rawPos.xy ,5.0); float noise_5m = Noise2D(rawPos.xy ,5.0);
float noise_2m = Noise2D(rawPos.xy ,2.0); float noise_2m = Noise2D(rawPos.xy ,2.0);
float noise_1m = Noise2D(rawPos.xy ,1.0); float noise_1m = Noise2D(rawPos.xy ,1.0);
float noise_01m = Noise2D(windPos.xy, 0.1); float noise_01m = Noise2D(windPos.xy, 0.1);
float noisegrad_10m; float noisegrad_10m;
float noisegrad_5m; float noisegrad_5m;
float noisegrad_2m; float noisegrad_2m;
float noisegrad_1m; float noisegrad_1m;
// Noise relative to swatch size // Noise relative to swatch size
float noise_25m = Noise2D(rawPos.xy, swatch_size*0.000625); float noise_25m = Noise2D(rawPos.xy, swatch_size*0.000625);
float noise_50m = Noise2D(rawPos.xy, swatch_size*0.00125); float noise_50m = Noise2D(rawPos.xy, swatch_size*0.00125);
float noise_250m = Noise3D(worldPos.xyz,swatch_size*0.0625); float noise_250m = Noise3D(worldPos.xyz,swatch_size*0.0625);
float noise_500m = Noise3D(worldPos.xyz, swatch_size*0.125); float noise_500m = Noise3D(worldPos.xyz, swatch_size*0.125);
float noise_1500m = Noise3D(worldPos.xyz, swatch_size*0.3750); float noise_1500m = Noise3D(worldPos.xyz, swatch_size*0.3750);
float noise_2000m = Noise3D(worldPos.xyz, swatch_size*0.5); float noise_2000m = Noise3D(worldPos.xyz, swatch_size*0.5);
float noise_4000m = Noise3D(worldPos.xyz, swatch_size); float noise_4000m = Noise3D(worldPos.xyz, swatch_size);
//WS2: uniforms aren't looked up until later in WS3
// dot noise
//float dotnoise_2m = DotNoise2D(rawPos.xy, 2.0 * dot_size,0.5, dot_density);
//float dotnoise_10m = DotNoise2D(rawPos.xy, 10.0 * dot_size, 0.5, dot_density);
//float dotnoise_15m = DotNoise2D(rawPos.xy, 15.0 * dot_size, 0.33, dot_density);
float dotnoisegrad_10m;
float dotnoisegrad_10m; // slope noise
float slopenoise_50m = SlopeLines2D(rawPos.xy, grad_dir, 50.0, steepness);
float slopenoise_100m = SlopeLines2D(rawPos.xy, grad_dir, 100.0, steepness);
// slope noise float snownoise_25m = mix(noise_25m, slopenoise_50m, clamp(3.0*(1.0-steepness),0.0,1.0));
float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),0.0,1.0));
float slopenoise_50m = SlopeLines2D(rawPos.xy, grad_dir, 50.0, steepness); // get the texels
float slopenoise_100m = SlopeLines2D(rawPos.xy, grad_dir, 100.0, steepness);
float snownoise_25m = mix(noise_25m, slopenoise_50m, clamp(3.0*(1.0-steepness),0.0,1.0));
float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),0.0,1.0));
// get the texels
@ -340,8 +412,12 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
// Tile texture coordinates range [0..1] over the tile 'rectangle' // Tile texture coordinates range [0..1] over the tile 'rectangle'
vec2 tile_coord = gl_TexCoord[0].st; vec2 tile_coord = gl_TexCoord[0].st;
// Testing code: Coordinate used by ground texture arrays
//vec2 ground_tex_coord = gl_TexCoord[0].st;
// Test phase: Constants and toggles for transitions between landlcasses are defined at // Test phase: Constants and toggles for transitions between landlcasses are defined at
// the top of this file. // the top landclass-search-functions.frag.
// There are some controls for haze and lighting at the top of this file.
// Look up the landclass id [0 .. 255] for this particular fragment // Look up the landclass id [0 .. 255] for this particular fragment
// and any neighbouring landclass that is close. // and any neighbouring landclass that is close.
@ -356,17 +432,15 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
// Mix factor of base textures for 2 neighbour landclass(es) // Mix factor of base textures for 2 neighbour landclass(es)
vec4 mfact; vec4 mfact;
// Partial derivatives of s and t of ground texture coords for this fragment,
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. // with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail // Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord); // dFdx and dFdy are packed in a vec4 so multiplying everything
vec2 dy = dFdy(tile_coord); // 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_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 // The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as // material parameters and textures for the landclass as
@ -378,26 +452,48 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
vec4 mat_ambient = fg_ambientArray[lc]; vec4 mat_ambient = fg_ambientArray[lc];
vec4 mat_diffuse = fg_diffuseArray[lc]; vec4 mat_diffuse = fg_diffuseArray[lc];
vec4 mat_specular = fg_specularArray[lc]; vec4 mat_specular = fg_specularArray[lc];
vec2 st = gl_TexCoord[0].st;
// Testing code: // Testing code:
// Use rlc even when looking up textures to recreate the extra performance hit // 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 // 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)); // color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
// Look up ground textures by indexing into the texture array.
// 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;
// Scale partial derivatives
vec4 dxdy = vec4(texture_scaling.st, texture_scaling.st) * dxdy_gc;
if (fg_photoScenery) { if (fg_photoScenery) {
// In the photoscenery case we don't have landclass or materials available, so we // In the photoscenery case we don't have landclass or materials available, so we
// just use constants for the material properties. // just use constants for the material properties.
mat_ambient = vec4(0.2,0.2,0.2,1.0); mat_ambient = vec4(0.2,0.2,0.2,1.0);
mat_diffuse = vec4(0.8,0.8,0.8,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_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)); // The photoscenery orthophots are stored in the landclass texture
// and use normalised tile coordinates
texel = texture(landclass, vec2(tile_coord.s, 1.0 - tile_coord.t));
// Do not attempt any mixing // Do not attempt any mixing
flag = 0; flag = 0;
mix_flag = 0; mix_flag = 0;
} else { }
else
{
// Color Mode is always AMBIENT_AND_DIFFUSE, which means // Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse, // using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray. // rather than the material color from ambientArray/diffuseArray.
@ -407,39 +503,9 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
mat_shininess = fg_dimensionsArray[lc].z; mat_shininess = fg_dimensionsArray[lc].z;
// Look up ground textures by indexing into the texture array. // Lookup the base texture texel for this fragment and any neighbors, with mixing
// Different textures are stretched along the ground to different texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters
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 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]);
}
} }
vec4 color = gl_Color * mat_ambient; vec4 color = gl_Color * mat_ambient;
@ -449,19 +515,46 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
//vec4 green = vec4(0.0, 0.5, 0.0, 0.0); //vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
//texel = mix(texel, green, (mfact[2])); //texel = mix(texel, green, (mfact[2]));
// Mix texture is material texture 12, 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));
if (mix_texel.a < 0.1) { mix_flag = 0;}
// Dot texture is material texture 15, which is mapped to the g channel of fg_textureLookup2
tex2 = int(fg_textureLookup2[lc].g * 255.0 + 0.5);
dot_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
// Detail texture is material texture 11, which is mapped to the g channel of fg_textureLookup1
tex2 = int(fg_textureLookup1[lc].g * 255.0 + 0.5); // Lookup material parameters for the landclass at this fragment.
detail_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2)); // Material parameters are from material definitions XML files (e.g. regional definitions in data/Materials/regions). They have the same names.
if (detail_texel.a < 0.1) { flag = 0;} // These parameters are contained in arrays of uniforms fg_materialParams1 and fg_materialParams2.
// The uniforms are vec4s, and each parameter is mapped to a vec4 element (rgba channels).
// In WS2 these parameters were available as uniforms of the same name.
// Testing: The mapping is hardcoded at the moment.
float transition_model = fg_materialParams1[lc].r;
float hires_overlay_bias = fg_materialParams1[lc].g;
float grain_strength = fg_materialParams1[lc].b;
float intrinsic_wetness = fg_materialParams1[lc].a;
float dot_density = fg_materialParams2[lc].r;
float dot_size = fg_materialParams2[lc].g;
float dust_resistance = fg_materialParams2[lc].b;
int rock_strata = int(fg_materialParams2[lc].a);
// dot noise
float dotnoise_2m = DotNoise2D(rawPos.xy, 2.0 * dot_size,0.5, dot_density);
float dotnoise_10m = DotNoise2D(rawPos.xy, 10.0 * dot_size, 0.5, dot_density);
float dotnoise_15m = DotNoise2D(rawPos.xy, 15.0 * dot_size, 0.33, dot_density);
// Testing code - set randomise_texture_lookups = 2 to only look up the base texture with no extra transitions.
detail_texel = texel;
mix_texel = texel;
grain_texel = texel;
dot_texel = texel;
gradient_texel = texel;
/*
// Texture lookup testing code:
// To test this block, uncomment it and turn off normal and random texture lookups
// by setting randomise_texture_lookups = 2 or more.
int tex2;
// Grain texture is material texture 14, which is mapped to the r channel of fg_textureLookup2 // Grain texture is material texture 14, which is mapped to the r channel of fg_textureLookup2
tex2 = int(fg_textureLookup2[lc].r * 255.0 + 0.5); tex2 = int(fg_textureLookup2[lc].r * 255.0 + 0.5);
@ -471,28 +564,76 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
tex2 = int(fg_textureLookup1[lc].a * 255.0 + 0.5); tex2 = int(fg_textureLookup1[lc].a * 255.0 + 0.5);
gradient_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2)); gradient_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
// Other material parameters, which are mapped to various channels from fg_materialParams1 and fg_materialParams2 // Dot texture is material texture 15, which is mapped to the g channel of fg_textureLookup2
float transition_model = fg_materialParams1[lc].r; tex2 = int(fg_textureLookup2[lc].g * 255.0 + 0.5);
float hires_overlay_bias = fg_materialParams1[lc].g; dot_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
float grain_strength = fg_materialParams1[lc].b;
float intrinsic_wetness = fg_materialParams1[lc].a;
float dot_density = fg_materialParams2[lc].r; // Mix texture is material texture 12, which is mapped to the b channel of fg_textureLookup1
float dot_size = fg_materialParams2[lc].g; tex2 = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
float dust_resistance = fg_materialParams2[lc].b; mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
float rock_strata = fg_materialParams2[lc].a; if (mix_texel.a < 0.1) { mix_flag = 0;} // Disable if no index found
// dot noise // Detail texture is material texture 11, which is mapped to the g channel of fg_textureLookup1
float dotnoise_2m = DotNoise2D(rawPos.xy, 2.0 * dot_size,0.5, dot_density); tex2 = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
float dotnoise_10m = DotNoise2D(rawPos.xy, 10.0 * dot_size, 0.5, dot_density); detail_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
float dotnoise_15m = DotNoise2D(rawPos.xy, 15.0 * dot_size, 0.33, dot_density); if (detail_texel.a < 0.1) { flag = 0;} // Disable if no index found
// Testing: WS2 code after this //Examples of how lookup_ground_texture array is used with the above grain/gradient texture lookups:
//grain_texel = lookup_ground_texture_array(1, st * 1.3, lc, dxdy * 1.3);
//gradient_texel = lookup_ground_texture_array(2, st * 1.3, lc, dxdy * 1.3);
*/
// Generate 6 random numbers
float pseed2 = 1.0;
int tex_id_lc[6];
float rn[6];
if (randomise_texture_lookups == 1)
{
get6_rand_nums(float(lc)*33245.31, pseed2, 47.0, rn);
for (int i=0;i<6;i++) tex_id_lc[i] = int(mod( (float(lc)+(rn[i]*47.0)+1.0) , 48.0));
}
//texel = mix(vec4(vec3(0.0),1.0), vec4(0.0,0.5,0.0,1.0), float(tex_id_lc[2])/48.0);
// WS2:
//grain_texel = texture2D(grain_texture, gl_TexCoord[0].st * 25.0);
//gradient_texel = texture2D(gradient_texture, gl_TexCoord[0].st * 4.0);
//stprime = gl_TexCoord[0].st * 80.0;
//stprime = stprime + normalize(relPos).xy * 0.01 * (dotnoise_10m + dotnoise_15m);
//dot_texel = texture2D(dot_texture, vec2 (stprime.y, stprime.x) );
if (randomise_texture_lookups == 0)
{
grain_texel = lookup_ground_texture_array(1, st * 25.0, lc, dxdy * 25.0);
gradient_texel = lookup_ground_texture_array(2, st * 4.0, lc, dxdy * 4.0);
}
else if (randomise_texture_lookups == 1)
{
grain_texel = lookup_ground_texture_array(0, st * 25.0, tex_id_lc[0], dxdy * 25.0);
gradient_texel = lookup_ground_texture_array(0, st * 4.0, tex_id_lc[1], dxdy * 4.0);
}
stprime = st * 80.0;
stprime = stprime + normalize(relPos).xy * 0.01 * (dotnoise_10m + dotnoise_15m);
vec4 dxdy_prime = vec4(dFdx(stprime), dFdy(stprime));
if (randomise_texture_lookups == 0)
{
dot_texel = lookup_ground_texture_array(3, stprime.ts, lc, dxdy_prime.tsqp);
}
else if (randomise_texture_lookups == 1)
{
dot_texel = lookup_ground_texture_array(0, stprime.ts, tex_id_lc[2], dxdy_prime.tsqp);
}
// Testing: WS2 code after this, except for random texture lookups and partial derivatives
float local_autumn_factor = texel.a; float local_autumn_factor = texel.a;
// we need to fade procedural structures when they get smaller than a single pixel, for this we need // we need to fade procedural structures when they get smaller than a single pixel, for this we need
// to know under what angle we see the surface // to know under what angle we see the surface
@ -517,29 +658,62 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
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) ); 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 (mix_flag == 1)
{
//WS2: mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3);
if (randomise_texture_lookups == 0)
{
mix_texel = lookup_ground_texture_array(4, st * 1.3, lc, dxdy * 1.3);
}
else if (randomise_texture_lookups == 1)
{
mix_texel = lookup_ground_texture_array(0, st * 1.3, tex_id_lc[3], dxdy * 1.3);
}
if (mix_texel.a <0.1) {mix_flag = 0;}
}
// the hires overlay texture is loaded with parallax mapping // the hires overlay texture is loaded with parallax mapping
if (flag == 1) { if (flag == 1)
stprime = vec2 (0.86*gl_TexCoord[0].s + 0.5*gl_TexCoord[0].t, 0.5*gl_TexCoord[0].s - 0.86*gl_TexCoord[0].t); {
stprime = vec2 (0.86*st.s + 0.5*st.t, 0.5*st.s - 0.86*st.t);
distortion_factor = 0.97 + 0.06 * noise_500m; distortion_factor = 0.97 + 0.06 * noise_500m;
stprime = stprime * distortion_factor * 15.0; stprime = stprime * distortion_factor * 15.0;
stprime = stprime + normalize(relPos).xy * 0.022 * (noise_10m + 0.5 * noise_5m +0.25 * noise_2m - 0.875 ); stprime = stprime + normalize(relPos).xy * 0.022 * (noise_10m + 0.5 * noise_5m +0.25 * noise_2m - 0.875 );
//detail_texel = texture2D(detail_texture, stprime); // temp //WS2: detail_texel = texture2D(detail_texture, stprime); // temp
dxdy_prime = vec4(dFdx(stprime), dFdy(stprime));
if (randomise_texture_lookups == 0)
{
detail_texel = lookup_ground_texture_array(5, stprime , lc, dxdy_prime);
} }
else if (randomise_texture_lookups == 1)
{
detail_texel = lookup_ground_texture_array(0, stprime, tex_id_lc[4], dxdy_prime);
}
if (detail_texel.a <0.1) {flag = 0;}
} // End if (flag == 1)
// texture preparation according to detail level
// mix in hires texture patches // texture preparation according to detail level
float dist_fact; // mix in hires texture patches
float nSum;
float mix_factor; float dist_fact;
float nSum;
float mix_factor;
// first the second texture overlay // first the second texture overlay
// transition model 0: random patch overlay without any gradient information // transition model 0: random patch overlay without any gradient information
// transition model 1: only gradient-driven transitions, no randomness // transition model 1: only gradient-driven transitions, no randomness
if (mix_flag == 1) {
if (mix_flag == 1)
{
nSum = 0.167 * (noise_4000m + 2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m); nSum = 0.167 * (noise_4000m + 2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
nSum = mix(nSum, 0.5, max(0.0, 2.0 * (transition_model - 0.5))); nSum = mix(nSum, 0.5, max(0.0, 2.0 * (transition_model - 0.5)));
nSum = nSum + 0.4 * (1.0 -smoothstep(0.9,0.95, abs(steepness)+ 0.05 * (noise_50m - 0.5))) * min(1.0, 2.0 * transition_model); nSum = nSum + 0.4 * (1.0 -smoothstep(0.9,0.95, abs(steepness)+ 0.05 * (noise_50m - 0.5))) * min(1.0, 2.0 * transition_model);
@ -550,7 +724,9 @@ float mix_factor;
// then the detail texture overlay // then the detail texture overlay
mix_factor = 0.0; mix_factor = 0.0;
if ((flag == 1) && (dist < 40000.0)) { //WS2: condition was broken up - does it matter for dynamic branching?
if ((flag == 1) && (dist < 40000.0))
{
dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist)); dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist));
nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0; nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0;
nSum = nSum - 0.08 * (1.0 -smoothstep(0.9,0.95, abs(steepness))); nSum = nSum - 0.08 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
@ -560,7 +736,9 @@ float mix_factor;
} }
// rock for very steep gradients // rock for very steep gradients
if (gradient_texel.a > 0.0) {
if (gradient_texel.a > 0.0)
{
texel = mix(texel, gradient_texel, 1.0 - smoothstep(0.75,0.8,abs(steepness)+ 0.00002* msl_altitude + 0.05 * (noise_50m - 0.5))); texel = mix(texel, gradient_texel, 1.0 - smoothstep(0.75,0.8,abs(steepness)+ 0.00002* msl_altitude + 0.05 * (noise_50m - 0.5)));
local_autumn_factor = texel.a; local_autumn_factor = texel.a;
} }
@ -571,7 +749,9 @@ float mix_factor;
float stratnoise_50m; float stratnoise_50m;
float stratnoise_10m; float stratnoise_10m;
if (rock_strata > 0.99) { // Testing: if rock_strata parameter is not cast into int, need (rock_strata > 0.99)
if (rock_strata==1)
{
stratnoise_50m = Strata3D(vec3 (rawPos.x, rawPos.y, msl_altitude), 50.0, 0.2); stratnoise_50m = Strata3D(vec3 (rawPos.x, rawPos.y, msl_altitude), 50.0, 0.2);
stratnoise_10m = Strata3D(vec3 (rawPos.x, rawPos.y, msl_altitude), 10.0, 0.2); stratnoise_10m = Strata3D(vec3 (rawPos.x, rawPos.y, msl_altitude), 10.0, 0.2);
stratnoise_50m = mix(stratnoise_50m, 1.0, smoothstep(0.8,0.9, steepness)); stratnoise_50m = mix(stratnoise_50m, 1.0, smoothstep(0.8,0.9, steepness));
@ -580,6 +760,7 @@ float mix_factor;
} }
// the dot vegetation texture overlay // the dot vegetation texture overlay
texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * (dotnoise_10m + dotnoise_15m) * detail_fade(1.0 * (dot_size * (1.0 +0.1*dot_size)), view_angle,dist)); texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * (dotnoise_10m + dotnoise_15m) * detail_fade(1.0 * (dot_size * (1.0 +0.1*dot_size)), view_angle,dist));
texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * dotnoise_2m * detail_fade(0.1 * dot_size, view_angle,dist)); texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * dotnoise_2m * detail_fade(0.1 * dot_size, view_angle,dist));
@ -591,17 +772,17 @@ float mix_factor;
// for really hires, add procedural noise overlay // for really hires, add procedural noise overlay
texel.rgb = texel.rgb * (1.0 + 0.4 * (noise_01m-0.5) * detail_fade(0.1, view_angle, dist)) ; texel.rgb = texel.rgb * (1.0 + 0.4 * (noise_01m-0.5) * detail_fade(0.1, view_angle, dist)) ;
// autumn colors // autumn colors
float autumn_factor = season * 2.0 * (1.0 - local_autumn_factor) ; float autumn_factor = season * 2.0 * (1.0 - local_autumn_factor) ;
texel.r = min(1.0, (1.0 + 2.5 * autumn_factor) * texel.r); texel.r = min(1.0, (1.0 + 2.5 * autumn_factor) * texel.r);
texel.g = texel.g; texel.g = texel.g;
texel.b = max(0.0, (1.0 - 4.0 * autumn_factor) * texel.b); texel.b = max(0.0, (1.0 - 4.0 * autumn_factor) * texel.b);
if (local_autumn_factor < 1.0) if (local_autumn_factor < 1.0)
{ {
intensity = length(texel.rgb) * (1.0 - 0.5 * smoothstep(1.1,2.0,season)); intensity = length(texel.rgb) * (1.0 - 0.5 * smoothstep(1.1,2.0,season));
texel.rgb = intensity * normalize(mix(texel.rgb, vec3(0.23,0.17,0.08), smoothstep(1.1,2.0, season))); texel.rgb = intensity * normalize(mix(texel.rgb, vec3(0.23,0.17,0.08), smoothstep(1.1,2.0, season)));
@ -610,21 +791,21 @@ if (local_autumn_factor < 1.0)
// slope line overlay // slope line overlay
texel.rgb = texel.rgb * (1.0 - 0.12 * slopenoise_50m - 0.08 * slopenoise_100m); texel.rgb = texel.rgb * (1.0 - 0.12 * slopenoise_50m - 0.08 * slopenoise_100m);
//const vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0); //const vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
const vec4 dust_color = vec4 (0.76, 0.65, 0.45, 1.0); const vec4 dust_color = vec4 (0.76, 0.65, 0.45, 1.0);
const vec4 lichen_color = vec4 (0.17, 0.20, 0.06, 1.0); const vec4 lichen_color = vec4 (0.17, 0.20, 0.06, 1.0);
// mix vegetation // mix vegetation
float gradient_factor = smoothstep(0.5, 1.0, steepness); float gradient_factor = smoothstep(0.5, 1.0, steepness);
texel = mix(texel, lichen_color, gradient_factor * (0.4 * lichen_cover_factor + 0.8 * lichen_cover_factor * 0.5 * (noise_10m + (1.0 - noise_5m))) ); texel = mix(texel, lichen_color, gradient_factor * (0.4 * lichen_cover_factor + 0.8 * lichen_cover_factor * 0.5 * (noise_10m + (1.0 - noise_5m))) );
// mix dust // mix dust
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor *dust_resistance + 3.0 * dust_cover_factor * dust_resistance *(((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) ); texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor *dust_resistance + 3.0 * dust_cover_factor * dust_resistance *(((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
// mix snow // mix snow
float snow_mix_factor = 0.0; float snow_mix_factor = 0.0;
if (msl_altitude +500.0 > snowlevel) if (msl_altitude +500.0 > snowlevel)
{ {
snow_alpha = smoothstep(0.75, 0.85, abs(steepness)); snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
snow_mix_factor = snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * msl_altitude+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0); snow_mix_factor = snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * msl_altitude+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0);
@ -634,28 +815,28 @@ if (msl_altitude +500.0 > snowlevel)
// get distribution of water when terrain is wet // get distribution of water when terrain is wet
float combined_wetness = min(1.0, wetness + intrinsic_wetness); float combined_wetness = min(1.0, wetness + intrinsic_wetness);
float water_threshold1; float water_threshold1;
float water_threshold2; float water_threshold2;
float water_factor =0.0; float water_factor =0.0;
if ((dist < 5000.0) && (combined_wetness>0.0)) if ((dist < 5000.0) && (combined_wetness>0.0))
{ {
water_threshold1 = 1.0-0.5* combined_wetness; water_threshold1 = 1.0-0.5* combined_wetness;
water_threshold2 = 1.0 - 0.3 * combined_wetness; water_threshold2 = 1.0 - 0.3 * combined_wetness;
water_factor = smoothstep(water_threshold1, water_threshold2 , (0.3 * (2.0 * (1.0-noise_10m) + (1.0 -noise_5m)) * (1.0 - smoothstep(2000.0, 5000.0, dist))) - 5.0 * (1.0 -steepness)); water_factor = smoothstep(water_threshold1, water_threshold2 , (0.3 * (2.0 * (1.0-noise_10m) + (1.0 -noise_5m)) * (1.0 - smoothstep(2000.0, 5000.0, dist))) - 5.0 * (1.0 -steepness));
} }
// darken wet terrain // darken wet terrain
texel.rgb = texel.rgb * (1.0 - 0.6 * combined_wetness); texel.rgb = texel.rgb * (1.0 - 0.6 * combined_wetness);
// light computations // light computations
vec4 light_specular = gl_LightSource[0].specular; vec4 light_specular = gl_LightSource[0].specular;
// If gl_Color.a == 0, this is a back-facing polygon and the // If gl_Color.a == 0, this is a back-facing polygon and the
@ -680,7 +861,11 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
NdotL = NdotL + 0.05 * noisegrad_1m * detail_fade(1.0, view_angle,dist); NdotL = NdotL + 0.05 * noisegrad_1m * detail_fade(1.0, view_angle,dist);
NdotL = NdotL + (1.0-snow_mix_factor) * 0.3* dot_texel.a * (0.5* dotnoisegrad_10m * detail_fade(1.0 * dot_size, view_angle, dist) +0.5 * dotnoisegrad_10m * noise_01m * detail_fade(0.1, view_angle, dist)) ; NdotL = NdotL + (1.0-snow_mix_factor) * 0.3* dot_texel.a * (0.5* dotnoisegrad_10m * detail_fade(1.0 * dot_size, view_angle, dist) +0.5 * dotnoisegrad_10m * noise_01m * detail_fade(0.1, view_angle, dist)) ;
if (NdotL > 0.0) { // Testing: Very temporary - reduce procedural normal map features with photoscenery active without breaking profiling as the controls are default (by request)
if (fg_photoScenery) NdotL = mix(dot(n, lightDir), NdotL, 0.00001);
if (NdotL > 0.0)
{
float shadowmap = getShadowing(); float shadowmap = getShadowing();
if (cloud_shadow_flag == 1) {NdotL = NdotL * shadow_func(relPos.x, relPos.y, 0.3 * noise_250m + 0.5 * noise_500m+0.2 * noise_1500m, dist);} if (cloud_shadow_flag == 1) {NdotL = NdotL * shadow_func(relPos.x, relPos.y, 0.3 * noise_250m + 0.5 * noise_500m+0.2 * noise_1500m, dist);}
vec4 diffuse_term = light_diffuse_comp * mat_diffuse; vec4 diffuse_term = light_diffuse_comp * mat_diffuse;
@ -726,12 +911,12 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
// Rayleigh color shift due to out-scattering // 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 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); float outscatter = 1.0-exp(-dist/rayleigh_length);
fragColor.rgb = rayleigh_out_shift(fragColor.rgb,outscatter); fragColor.rgb = rayleigh_out_shift(fragColor.rgb,outscatter);
// Rayleigh color shift due to in-scattering // Rayleigh color shift due to in-scattering
float rShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt + 420000.0); float rShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt + 420000.0);
//float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade; //float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade;
@ -741,7 +926,7 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
fragColor.rgb = mix(fragColor.rgb, rayleighColor,rayleighStrength); fragColor.rgb = mix(fragColor.rgb, rayleighColor,rayleighStrength);
// here comes the terrain haze model // here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt; float delta_z = hazeLayerAltitude - eye_alt;
@ -749,7 +934,6 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
if (dist > 0.04 * mvisibility) if (dist > 0.04 * mvisibility)
{ {
alt = eye_alt; alt = eye_alt;
float transmission; float transmission;
@ -760,8 +944,6 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
float transmission_arg; float transmission_arg;
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer // 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 (delta_z > 0.0) // we're inside the layer
{ {
@ -797,16 +979,16 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
} }
} }
// blur of the haze layer edge // blur of the haze layer edge
float blur_thickness = 50.0; float blur_thickness = 50.0;
float cphi = dot(vec3(0.0, 1.0, 0.0), relPos)/dist; 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 ctlayer = delta_z/dist-0.01 + 0.02 * Noise2D(vec2(cphi,1.0),0.1) -0.01;
float ctblur = 0.035 ; float ctblur = 0.035 ;
float blur_dist; float blur_dist;
if (abs(delta_z) < 400.0) if (abs(delta_z) < 400.0)
{ {
blur_dist = dist * (1.0-smoothstep(0.0,300.0,-delta_z)) * smoothstep(-400.0,-200.0, -delta_z); 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)); blur_dist = blur_dist * smoothstep(ctlayer-4.0*ctblur, ctlayer-ctblur, ct) * (1.0-smoothstep(ctlayer+0.5*ctblur, ctlayer+ctblur, ct));
@ -820,12 +1002,12 @@ if (abs(delta_z) < 400.0)
float eqColorFactor; float eqColorFactor;
if (visibility < avisibility) if (visibility < avisibility)
{ {
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) )); transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering); eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering);
} }
else else
{ {
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) )); transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 - effective_scattering); eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 - effective_scattering);
@ -833,8 +1015,8 @@ else
transmission = fog_func(transmission_arg, alt); transmission = fog_func(transmission_arg, alt);
// there's always residual intensity, we should never be driven to zero // there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2; if (eqColorFactor < 0.2) eqColorFactor = 0.2;
@ -842,7 +1024,7 @@ if (eqColorFactor < 0.2) eqColorFactor = 0.2;
// now dim the light for haze // now dim the light for haze
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt); eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
// Mie-like factor // Mie-like factor
if (lightArg < 10.0) if (lightArg < 10.0)
{ {
@ -851,10 +1033,10 @@ if (eqColorFactor < 0.2) eqColorFactor = 0.2;
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) ); hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
} }
intensity = length(hazeColor); intensity = length(hazeColor);
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly 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 // high altitude desaturation of the haze color
@ -888,32 +1070,33 @@ if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColo
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5); float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4); vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
hazeColor.rgb *= eqColorFactor * eShade; hazeColor.rgb *= eqColorFactor * eShade;
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb); hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
// finally, mix fog in // finally, mix fog in
// Testing phase controls
if (reduce_haze_without_removing_calculation_overhead == 1)
{
transmission = 1.0 - (transmission/1000000.0);
}
fragColor.rgb = mix(hazeColor+secondary_light * fog_backscatter(mvisibility) , fragColor.rgb,transmission);
// Testing phase controls
if (reduce_haze_without_removing_calculation_overhead == 1)
{
transmission = 1.0 - (transmission/1000000.0);
} }
fragColor.rgb = mix(hazeColor+secondary_light * fog_backscatter(mvisibility) , fragColor.rgb,transmission);
} // end if (dist > 0.04 * mvisibility)
fragColor.rgb = filter_combined(fragColor.rgb); fragColor.rgb = filter_combined(fragColor.rgb);
gl_FragColor = fragColor; gl_FragColor = fragColor;
// Testing phase controls: // Testing phase controls:
if (remove_haze_and_lighting == 1) if (remove_haze_and_lighting == 1)
{ {
gl_FragColor = texel; gl_FragColor = texel;
} }
} }

View file

@ -16,7 +16,6 @@
#define MODE_DIFFUSE 1 #define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2 #define MODE_AMBIENT_AND_DIFFUSE 2
//attribute vec2 orthophotoTexCoord;
// The constant term of the lighting equation that doesn't depend on // The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha // the surface normal is passed in gl_{Front,Back}Color. The alpha
@ -25,11 +24,11 @@
varying vec4 light_diffuse_comp; varying vec4 light_diffuse_comp;
varying vec3 normal; varying vec3 normal;
varying vec3 relPos; varying vec3 relPos;
varying vec3 rawPos; varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos; varying vec3 worldPos;
varying vec3 ecViewdir; varying vec3 ecViewdir;
varying vec2 grad_dir; varying vec2 grad_dir;
//varying vec2 orthoTexCoord;
varying vec4 ecPosition; varying vec4 ecPosition;
// Sent packed into alpha channels // Sent packed into alpha channels
@ -76,12 +75,10 @@ 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) 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; //x = x - 0.5;
// use the asymptotics to shorten computations
// use the asymptotics to shorten computations if (x < -15.0) {return 0.0;}
if (x < -15.0) {return 0.0;} return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
} }
@ -103,12 +100,18 @@ void main()
float vertex_alt; float vertex_alt;
float scattering; float scattering;
rawPos = (fg_zUpTransform * gl_Vertex).xyz; // The ALS code assumes that units are in meters - e.g. model space vertices (gl_Vertex) are in meters
worldPos = fg_modelOffset + gl_Vertex.xyz;
// 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; vec4 pos = gl_Vertex;
if (raise_vertex) if (raise_vertex)
@ -119,30 +122,93 @@ void main()
else gl_Position = ftransform(); else gl_Position = ftransform();
// this code is copied from default.vert // this code is copied from default.vert
ecPosition = gl_ModelViewMatrix * gl_Vertex; ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform(); //gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//orthoTexCoord = orthophotoTexCoord;
normal = gl_NormalMatrix * gl_Normal; 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));
// 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 // here start computations for the haze layer
// we need several geometrical quantities // 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 // first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0); 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;
ecViewdir = (gl_ModelViewMatrix * (epMS - gl_Vertex)).xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version // unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again // is later computed in the fragment shader again
float dist = length(relPos); float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m // Altitude of the vertex above mean sea level in meters.
vertex_alt = max(rawPos.z,100.0); // 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); scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
@ -150,15 +216,11 @@ void main()
if (terminator < 1000000.0) // the full, sunrise and sunset computation if (terminator < 1000000.0) // the full, sunrise and sunset computation
{ {
// establish coordinates relative to sun position // establish coordinates relative to sun position
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz; vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0)); vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction // yprime is the distance of the vertex into sun direction
yprime = -dot(relPos, lightHorizon); yprime = -dot(relPos, lightHorizon);
@ -179,8 +241,6 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
{mie_angle = 1.0;} {mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0); light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0); light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0); light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
@ -197,8 +257,8 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
// correct ambient light intensity and hue before sunrise // correct ambient light intensity and hue before sunrise
if (earthShade < 0.5) if (earthShade < 0.5)
{ {
intensity = length(light_ambient.rgb); 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 = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.8,earthShade) ));
@ -209,12 +269,12 @@ if (earthShade < 0.5)
} }
// the haze gets the light at the altitude of the haze top if the vertex in view is below // 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 // but the light at the vertex if the vertex is above
vertex_alt = max(vertex_alt,hazeLayerAltitude); vertex_alt = max(vertex_alt,hazeLayerAltitude);
if (vertex_alt > hazeLayerAltitude) if (vertex_alt > hazeLayerAltitude)
{ {
if (dist > 0.8 * avisibility) if (dist > 0.8 * avisibility)
{ {
@ -222,26 +282,27 @@ if (vertex_alt > hazeLayerAltitude)
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt); yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
} }
} }
else else
{ {
vertex_alt = hazeLayerAltitude; vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt); yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
} }
} } // End if (terminator < 1000000.0)
else // the faster, full-day version without lightfields else // the faster, full-day version without lightfields
{ {
//vertex_alt = max(gl_Vertex.z,100.0); //vertex_alt = max(gl_Vertex.z,100.0);
earthShade = 1.0; earthShade = 1.0;
mie_angle = 1.0; mie_angle = 1.0;
if (terminator > 3000000.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 else
{ {
lightArg = (terminator/100000.0 - 10.0)/20.0; lightArg = (terminator/100000.0 - 10.0)/20.0;
light_diffuse.b = 0.78 + lightArg * 0.21; light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.g = 0.907 + lightArg * 0.091; light_diffuse.g = 0.907 + lightArg * 0.091;
@ -258,28 +319,29 @@ else // the faster, full-day version without lightfields
light_diffuse = light_diffuse * scattering; light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude); yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
} //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 // a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
// steep faces end up shaded more // 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); 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_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth); light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
if (use_IR_vision) if (use_IR_vision)
{ {
light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5)); 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 // default lighting based on texture and material using the light we have just computed
light_diffuse_comp = light_diffuse; light_diffuse_comp = light_diffuse;
//Testing phase code: ambient colours are not sent to fragement shader yet. //Testing phase code: ambient colours are not sent to fragement shader yet.

View file

@ -43,6 +43,7 @@
varying vec4 light_diffuse_comp; varying vec4 light_diffuse_comp;
varying vec3 normal; varying vec3 normal;
varying vec3 relPos; varying vec3 relPos;
varying vec2 ground_tex_coord;
uniform sampler2D landclass; uniform sampler2D landclass;
uniform sampler2DArray textureArray; 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 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 // the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams. // 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. // Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance. // 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 // 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 // Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord, void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
out int landclass_id, out ivec4 neighbor_landclass_ids, out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor 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 // End Test-phase code
//////////////////////// ////////////////////////
@ -209,16 +222,15 @@ void main()
vec4 mfact; 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 for this fragment,
// with respect to window (screen space) x and y axes. // with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail // Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord); // dFdx and dFdy are packed in a vec4 so multiplying
vec2 dy = dFdy(tile_coord); // 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, get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
lc, lc_n, num_unique_neighbors, mfact);
// The landclass id is used to index into arrays containing // The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as // material parameters and textures for the landclass as
@ -230,6 +242,15 @@ void main()
vec4 mat_diffuse, mat_ambient, mat_specular; vec4 mat_diffuse, mat_ambient, mat_specular;
float mat_shininess; 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) { if (fg_photoScenery) {
mat_ambient = vec4(1.0,1.0,1.0,1.0); mat_ambient = vec4(1.0,1.0,1.0,1.0);
mat_diffuse = vec4(1.0,1.0,1.0,1.0); mat_diffuse = vec4(1.0,1.0,1.0,1.0);
@ -238,6 +259,7 @@ void main()
texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)); texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t));
} else { } else {
// Color Mode is always AMBIENT_AND_DIFFUSE, which means // Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse, // using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray. // rather than the material color from ambientArray/diffuseArray.
@ -251,30 +273,9 @@ void main()
// lengths along each axes as set by <xsize> and <ysize> // lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters // regional definitions parameters
// Look up texture coordinates and scale of ground textures // Lookup the base texture texel for this fragment and any neighbors, with mixing
// Landclass for this fragment texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
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]);
}
} }
vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient); vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient);

View file

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