1
0
Fork 0

WS30: MR #267: Improved texture lookups from VS

Squashed commit of the following:

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

    WS30 effects and shaders:

    Changelog:

    ws30-ALS-ultra.frag:

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

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

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

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

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

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

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

    ----

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

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

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

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

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

    ----

    WS30-overlay effect (Inactive):

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

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

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

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

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

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

    ----

    Changes after the multi-texture support commit:

    ws30-ALS-ultra.vert

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

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

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

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

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

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

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

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

    ----

    Changes after sending material parameters in uniform arrays commit:

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

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

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

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

View file

@ -182,7 +182,11 @@
insert their own techniques first. -->
<!-- ALS ultra shaders -->
<!--
ALS ultra shaders. The 1st pass of ws30-overlay.eff is a copy of
this pass, and changes should be made there as well.
-->
<technique n="5">
<predicate>
<and>

View file

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

View file

@ -43,7 +43,8 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos;
// Testing code:
//vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
@ -157,21 +158,33 @@ int get_random_landclass(in vec2 co, in vec2 tile_size);
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
// the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams.
// Texture types: 0: base texture, 1: grain texture, 2: gradient texture, 3 dot texture,
// 4: mix texture, 5: detail texture.
vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy);
vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec4 dFdx_and_dFdy);
// Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance.
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
// Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
// Create a mix factor weighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor
);
// Look up the texel of the specified texture type (e.g. grain or detail textures) for this fragment
// and any neighbor texels, then mix.
vec4 get_mixed_texel(in int texture_type, in vec2 g_texture_coord,
in int landclass_id, in int num_unique_neighbors,
in ivec4 neighbor_texel_landclass_ids, in vec4 neighbor_mix_factors,
in vec4 dFdx_and_dFdy
);
// End Test-phase code
////////////////////////
@ -270,16 +283,15 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
vec4 mfact;
const float landclass_texel_size_m = 25.0;
// Partial derivatives of s and t for this fragment,
// Partial derivatives of s and t of ground texture coords for this fragment,
// with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord);
vec2 dy = dFdy(tile_coord);
// dFdx and dFdy are packed in a vec4 so multiplying everything
// to scale takes 1 instruction slot.
vec4 dxdy_gc = vec4(dFdx(ground_tex_coord) , dFdy(ground_tex_coord));
get_landclass_id(tile_coord, landclass_texel_size_m, dx, dy,
lc, lc_n, num_unique_neighbors, mfact);
get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
// The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as
@ -291,13 +303,23 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
vec4 mat_ambient = fg_ambientArray[lc];
vec4 mat_diffuse = fg_diffuseArray[lc];
vec4 mat_specular = fg_specularArray[lc];
vec2 st = gl_TexCoord[0].st;
// Testing code:
// Use rlc even when looking up textures to recreate the extra performance hit
// so any performance difference between the two is due to the texture lookup
// color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
// Calculate texture coords for ground textures
// Textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters.
vec2 stretch_dimensions = fg_dimensionsArray[lc].st;
vec2 tileSize = vec2(fg_tileWidth, fg_tileHeight);
vec2 texture_scaling = tileSize.xy / stretch_dimensions.st;
vec2 st = texture_scaling.st * ground_tex_coord.st;
// Scale partial derivatives
vec4 dxdy = vec4(texture_scaling.st, texture_scaling.st) * dxdy_gc;
if (fg_photoScenery) {
// In the photoscenery case we don't have landclass or materials available, so we
@ -305,9 +327,12 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
mat_ambient = vec4(0.2,0.2,0.2,1.0);
mat_diffuse = vec4(0.8,0.8,0.8,1.0);
mat_specular = vec4(0.0,0.0,0.0,1.0);
mat_shininess = 1.2;
texel = texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t));
} else {
} else
{
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray.
@ -316,40 +341,11 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
mat_specular = fg_specularArray[lc];
mat_shininess = fg_dimensionsArray[lc].z;
// Different textures have different have different dimensions.
vec2 atlas_dimensions = fg_dimensionsArray[lc].st;
vec2 atlas_scale = vec2(fg_tileWidth / atlas_dimensions.s, fg_tileHeight / atlas_dimensions.t );
st = atlas_scale * gl_TexCoord[0].st;
// Lookup the base texture texel for this fragment and any neighbors, with mixing
texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
// Look up ground textures by indexing into the texture array.
// Different textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters
//if (ground_tex_coord.x > 0.0) texel = vec4(1.0);
// 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;
@ -359,6 +355,9 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
//vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
//texel = mix(texel, green, (mfact[2]));
//mix_texel = texel;
//detail_texel = texel;
vec4 t = texel;
int flag = 1;
int mix_flag = 1;
@ -378,7 +377,7 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
//float view_angle = abs(dot(normal, normalize(ecViewdir)));
if ((quality_level > 3)&&(rawPos.z +500.0 > snowlevel)) {
if ((quality_level > 3)&&(relPos.z +500.0 > snowlevel)) {
float sfactor;
snow_texel = vec4 (0.95, 0.95, 0.95, 1.0) * (0.9 + 0.1* noise_500m + 0.1* (1.0 - noise_10m) );
snow_texel.r = snow_texel.r * (0.9 + 0.05 * (noise_10m + noise_5m));
@ -393,15 +392,19 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
noise_term = noise_term + 0.3 * (noise_5m -0.5) * (1.0 - smoothstep(1000.0 * sfactor, 3000.0 *sfactor, dist) );
}
snow_texel.a = snow_texel.a * 0.2+0.8* smoothstep(0.2,0.8, 0.3 +noise_term + snow_thickness_factor +0.0001*(rawPos.z -snowlevel) );
snow_texel.a = snow_texel.a * 0.2+0.8* smoothstep(0.2,0.8, 0.3 +noise_term + snow_thickness_factor +0.0001*(relPos.z -snowlevel) );
}
if ((tquality_level > 2) && (mix_flag == 1))
{
// Mix texture is material texture 15, which is mapped to the b channel of fg_textureLookup1
int tex2 = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
//int tex2 = int(fg_textureLookup1[lc].b * 255.0 + 0.5);
//mix_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
if (mix_texel.a < 0.1) { mix_flag = 0;}
//WS2: mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3); // temp
mix_texel = lookup_ground_texture_array(4, st * 1.3, lc, dxdy * 1.3);
if (mix_texel.a <0.1) {mix_flag = 0;}
}
@ -417,9 +420,13 @@ float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
}
// Detail texture is material texture 11, which is mapped to the g channel of fg_textureLookup1
int tex3 = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
detail_texel = texture(textureArray, vec3(stprime, tex3));
//int tex3 = int(fg_textureLookup1[lc].g * 255.0 + 0.5);
//detail_texel = texture(textureArray, vec3(stprime, tex3));
if (detail_texel.a < 0.1) { flag = 0;}
//WS2: detail_texel = texture2D(detail_texture, stprime); // temp
vec4 dxdy_prime = vec4(dFdx(stprime), dFdy(stprime));
detail_texel = lookup_ground_texture_array(5, stprime, lc, dxdy_prime);
}
// texture preparation according to detail level
@ -505,18 +512,18 @@ if (quality_level > 3)
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
// mix snow
if (rawPos.z +500.0 > snowlevel)
if (relPos.z +500.0 > snowlevel)
{
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
//texel = mix(texel, snow_texel, texel_snow_fraction);
texel = mix(texel, snow_texel, snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (rawPos.z)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
texel = mix(texel, snow_texel, snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (relPos.z)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
}
}
else if (rawPos.z +500.0 > snowlevel)
else if (relPos.z +500.0 > snowlevel)
{
float snow_alpha = 0.5+0.5* smoothstep(0.2,0.8, 0.3 + snow_thickness_factor +0.0001*(rawPos.z -snowlevel) );
float snow_alpha = 0.5+0.5* smoothstep(0.2,0.8, 0.3 + snow_thickness_factor +0.0001*(relPos.z -snowlevel) );
// texel = vec4(dot(vec3(0.2989, 0.5870, 0.1140), texel.rgb));
texel = mix(texel, vec4(1.0), snow_alpha* smoothstep(snowlevel, snowlevel+200.0, (rawPos.z)));
texel = mix(texel, vec4(1.0), snow_alpha* smoothstep(snowlevel, snowlevel+200.0, (relPos.z)));
}

View file

@ -25,7 +25,8 @@ attribute vec2 orthophotoTexCoord;
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos;
//varying vec2 orthoTexCoord;
varying vec4 eyePos;
@ -95,7 +96,7 @@ void main()
float vertex_alt;
float scattering;
rawPos = (fg_zUpTransform * gl_Vertex).xyz;
rawPos = (fg_zUpTransform * gl_Vertex).xy;
worldPos = fg_modelOffset + gl_Vertex.xyz;
eyePos = gl_ModelViewMatrix * gl_Vertex;
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
@ -110,6 +111,9 @@ void main()
normal = gl_NormalMatrix * gl_Normal;
//nvec = (gl_NormalMatrix * gl_Normal).xy;
// Temporary value:
ground_tex_coord = gl_TexCoord[0].st;
// here start computations for the haze layer
// we need several geometrical quantities
@ -126,7 +130,7 @@ void main()
float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m
vertex_alt = max(rawPos.z,100.0);
vertex_alt = max(relPos.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);

View file

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

View file

@ -22,6 +22,16 @@
// Possible values: 0:Normal, 1:Just the texture.
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
//////////////////////////////////////////////////////////////////
@ -43,8 +53,9 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec3 worldPos;
varying vec2 rawPos;
// Testing code:
//vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
varying vec3 ecViewdir;
@ -89,7 +100,6 @@ uniform float osg_SimulationTime;
uniform int wind_effects;
uniform int cloud_shadow_flag;
uniform int rock_strata;
uniform int use_searchlight;
uniform int use_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_tileHeight;
uniform bool fg_photoScenery;
// Material parameters, from material definitions and effect defaults, for each landclass.
// xsize and ysize
uniform vec4 fg_dimensionsArray[128];
// RGBA ambient color
uniform vec4 fg_ambientArray[128];
// RGBA diffuse color
uniform vec4 fg_diffuseArray[128];
// RGBA specular color
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_textureLookup2[128];
// Each element of a vec4 contains a different materials parameter.
uniform vec4 fg_materialParams1[128];
uniform vec4 fg_materialParams2[128];
@ -159,15 +177,53 @@ return 1.0 - smoothstep(0.5 * fade_dist, fade_dist, dist);
// These should be sent as uniforms
// 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:
// 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
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
// in ws30-ALS-landclass-search.frag.
@ -182,22 +238,33 @@ int get_random_landclass(in vec2 co, in vec2 tile_size);
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
// the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams.
// Texture types: 0: base texture, 1: grain texture, 2: gradient texture, 3 dot texture,
// 4: mix texture, 5: detail texture.
vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id,
in vec2 dx, in vec2 dy);
vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec4 dFdx_and_dFdy);
// Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance.
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
// Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor
);
// Look up the texel of the specified texture type (e.g. grain or detail textures) for this fragment
// and any neighbor texels, then mix.
vec4 get_mixed_texel(in int texture_type, in vec2 g_texture_coord,
in int landclass_id, in int num_unique_neighbors,
in ivec4 neighbor_texel_landclass_ids, in vec4 neighbor_mix_factors,
in vec4 dFdx_and_dFdy
);
// End Test-phase code
////////////////////////
@ -305,6 +372,11 @@ float noise_1500m = Noise3D(worldPos.xyz, swatch_size*0.3750);
float noise_2000m = Noise3D(worldPos.xyz, swatch_size*0.5);
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;
@ -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'
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
// 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
// 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)
vec4 mfact;
const float landclass_texel_size_m = 25.0;
// Partial derivatives of s and t for this fragment,
// Partial derivatives of s and t of ground texture coords for this fragment,
// with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord);
vec2 dy = dFdy(tile_coord);
// dFdx and dFdy are packed in a vec4 so multiplying everything
// to scale takes 1 instruction slot.
vec4 dxdy_gc = vec4(dFdx(ground_tex_coord) , dFdy(ground_tex_coord));
get_landclass_id(tile_coord, 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
// 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_diffuse = fg_diffuseArray[lc];
vec4 mat_specular = fg_specularArray[lc];
vec2 st = gl_TexCoord[0].st;
// Testing code:
// Use rlc even when looking up textures to recreate the extra performance hit
// so any performance difference between the two is due to the texture lookup
// color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
// 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) {
// In the photoscenery case we don't have landclass or materials available, so we
// just use constants for the material properties.
mat_ambient = vec4(0.2,0.2,0.2,1.0);
mat_diffuse = vec4(0.8,0.8,0.8,1.0);
mat_specular = vec4(0.0,0.0,0.0,1.0);
mat_shininess = 1.2;
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
flag = 0;
mix_flag = 0;
} else {
}
else
{
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray.
@ -407,39 +503,9 @@ float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),
mat_shininess = fg_dimensionsArray[lc].z;
// Look up ground textures by indexing into the texture array.
// Different textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters
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;
// Lookup the base texture texel for this fragment and any neighbors, with mixing
texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
// Look up texture coordinates and scale of ground textures
// Landclass for this fragment
texel = lookup_ground_texture_array(tile_coord, lc, dx, dy);
// 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;
@ -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);
//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);
detail_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
if (detail_texel.a < 0.1) { flag = 0;}
// Lookup material parameters for the landclass at this fragment.
// Material parameters are from material definitions XML files (e.g. regional definitions in data/Materials/regions). They have the same names.
// 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
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);
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
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;
// 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));
float dot_density = fg_materialParams2[lc].r;
float dot_size = fg_materialParams2[lc].g;
float dust_resistance = fg_materialParams2[lc].b;
float rock_strata = fg_materialParams2[lc].a;
// Mix texture is material texture 12, which is mapped to the b channel of fg_textureLookup1
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;} // Disable if no index found
// 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);
// 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);
detail_texel = texture(textureArray, vec3(gl_TexCoord[0].st * 1.3, tex2));
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;
// 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
@ -517,16 +658,45 @@ 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) );
}
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
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);
if (flag == 1)
{
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;
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 );
//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
@ -539,7 +709,11 @@ float mix_factor;
// first the second texture overlay
// transition model 0: random patch overlay without any gradient information
// 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 = 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);
@ -550,7 +724,9 @@ float mix_factor;
// then the detail texture overlay
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));
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)));
@ -560,7 +736,9 @@ float mix_factor;
}
// 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)));
local_autumn_factor = texel.a;
}
@ -571,7 +749,9 @@ float mix_factor;
float stratnoise_50m;
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_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));
@ -580,6 +760,7 @@ float mix_factor;
}
// 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_2m * detail_fade(0.1 * dot_size, view_angle,dist));
@ -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 + (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();
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;
@ -749,7 +934,6 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
if (dist > 0.04 * mvisibility)
{
alt = eye_alt;
float transmission;
@ -760,8 +944,6 @@ if ((dist < 5000.0) && (combined_wetness>0.0))
float transmission_arg;
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
if (delta_z > 0.0) // we're inside the layer
{
@ -902,7 +1084,7 @@ 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);
@ -916,4 +1098,5 @@ if (remove_haze_and_lighting == 1)
gl_FragColor = texel;
}
}

View file

@ -16,7 +16,6 @@
#define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2
//attribute vec2 orthophotoTexCoord;
// The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha
@ -25,11 +24,11 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec3 rawPos;
varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos;
varying vec3 ecViewdir;
varying vec2 grad_dir;
//varying vec2 orthoTexCoord;
varying vec4 ecPosition;
// Sent packed into alpha channels
@ -77,10 +76,8 @@ const float terminator_width = 200000.0;
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
//x = x - 0.5;
// use the asymptotics to shorten computations
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
@ -103,12 +100,18 @@ void main()
float vertex_alt;
float scattering;
rawPos = (fg_zUpTransform * gl_Vertex).xyz;
worldPos = fg_modelOffset + gl_Vertex.xyz;
// The ALS code assumes that units are in meters - e.g. model space vertices (gl_Vertex) are in meters
// WS30 model space, Nov 21, 2021:
// Coordinate axes are the same for geocentric, but not the origin.
// +z direction points from the Earth center to North pole.
// +x direction points from the Earth center to longitude = 0 on the equator.
// +y direction points from the Earth center to logntitude = East on the equator.
// Model space origin is at sea level. Units are in meters.
// Each tile, for each LoD level, its own model origin
// modelOffset is the model origin relative to the Earth center. It is in a geocentric
// space with the same axes, but with the Earth center as the origin. Units are in meters.
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
grad_dir = normalize(gl_Normal.xy);
vec4 pos = gl_Vertex;
if (raise_vertex)
@ -124,25 +127,88 @@ void main()
ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//orthoTexCoord = orthophotoTexCoord;
normal = gl_NormalMatrix * gl_Normal;
///////////////////////////////////////////
// Test phase code:
//
// Coords for ground textures
// Due to precision issues coordinates should restart (i.e. go to zero) every 5000m or so.
const float restart_dist_m = 5000.0;
// Model position
vec3 mp = gl_Vertex.xyz;
// Temporary approximation to get shaders to compile:
ground_tex_coord = gl_TexCoord[0].st;
//
// End test phase code
///////////////////////////////////////////
// WS2:
// first current altitude of eye position in model space
// vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
//relPos = gl_Vertex.xyz - ep.xyz;
// Transform for frame of reference where:
// +z is in the up direction.
// The orientation of x and y axes are unknown currently.
// The origin is at the same position as the model space origin.
// The units are in meters.
mat4 viewSpaceToZUpSpace = fg_zUpTransform * gl_ModelViewMatrixInverse;
vec4 vertexZUp = fg_zUpTransform * gl_Vertex;
// WS2: rawPos = gl_Vertex.xy;
rawPos = vertexZUp.xy;
// WS2: worldPos = (osg_ViewMatrixInverse *gl_ModelViewMatrix * gl_Vertex).xyz;
worldPos = fg_modelOffset + gl_Vertex.xyz;
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
// Gradient direction used for small scale noise. In the same space as noise coords, rawpos.xy.
grad_dir = normalize(gl_Normal.xy);
// here start computations for the haze layer
// we need several geometrical quantities
// Eye position in z up space
vec4 epZUp = viewSpaceToZUpSpace * vec4(0.0,0.0,0.0,1.0);
// Position of vertex relative to the eye position in z up space
vec3 relPosZUp = (vertexZUp - epZUp).xyz;
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
relPos = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
ecViewdir = (gl_ModelViewMatrix * (ep - gl_Vertex)).xyz;
// Eye position in model space
vec4 epMS = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
/*
//old: and relative position to vector. This is also used for cloud shadow positioning.
relPosOld = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
if (any(notEqual(relPosOld, relPosZUp))) relPos = vec3(1000000.0);
*/
relPos = relPosZUp;
ecViewdir = (gl_ModelViewMatrix * (epMS - gl_Vertex)).xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again
float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m
vertex_alt = max(rawPos.z,100.0);
// Altitude of the vertex above mean sea level in meters.
// This is equal to vertexZUp.z as the model space origin is at mean sea level.
// Somehow zero leads to artefacts, so ensure it is at least 100m.
//WS2: vertex_alt = max(gl_Vertex.z,100.0);
vertex_alt = max(vertexZUp.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
@ -150,15 +216,11 @@ void main()
if (terminator < 1000000.0) // the full, sunrise and sunset computation
{
// establish coordinates relative to sun position
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction
yprime = -dot(relPos, lightHorizon);
@ -179,8 +241,6 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
{mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
@ -228,7 +288,7 @@ else
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
} // End if (terminator < 1000000.0)
else // the faster, full-day version without lightfields
{
//vertex_alt = max(gl_Vertex.z,100.0);
@ -237,11 +297,12 @@ else // the faster, full-day version without lightfields
mie_angle = 1.0;
if (terminator > 3000000.0)
{light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0); }
{
light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0);
}
else
{
lightArg = (terminator/100000.0 - 10.0)/20.0;
light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.g = 0.907 + lightArg * 0.091;
@ -258,7 +319,8 @@ else // the faster, full-day version without lightfields
light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
} //End the faster, full-day version without lightfields
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so

View file

@ -43,6 +43,7 @@
varying vec4 light_diffuse_comp;
varying vec3 normal;
varying vec3 relPos;
varying vec2 ground_tex_coord;
uniform sampler2D landclass;
uniform sampler2DArray textureArray;
@ -144,21 +145,33 @@ int get_random_landclass(in vec2 co, in vec2 tile_size);
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
// the stretching of different textures, so that the correct mip-map level is looked
// up and there are no seams.
// Texture types: 0: base texture, 1: grain texture, 2: gradient texture, 3 dot texture,
// 4: mix texture, 5: detail texture.
vec4 lookup_ground_texture_array(in vec2 tile_coord, in int landclass_id, in vec2 dx, in vec2 dy);
vec4 lookup_ground_texture_array(in int texture_type, in vec2 ground_texture_coord, in int landclass_id,
in vec4 dFdx_and_dFdy);
// Look up the landclass id [0 .. 255] for this particular fragment.
// Lookup id of any neighbouring landclass that is within the search distance.
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
// Create a mix factor werighting the influences of nearby landclasses
void get_landclass_id(in vec2 tile_coord,
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
void get_landclass_id(in vec2 tile_coord, in vec4 dFdx_and_dFdy,
out int landclass_id, out ivec4 neighbor_landclass_ids,
out int num_unique_neighbors,out vec4 mix_factor
);
// Look up the texel of the specified texture type (e.g. grain or detail textures) for this fragment
// and any neighbor texels, then mix.
vec4 get_mixed_texel(in int texture_type, in vec2 g_texture_coord,
in int landclass_id, in int num_unique_neighbors,
in ivec4 neighbor_texel_landclass_ids, in vec4 neighbor_mix_factors,
in vec4 dFdx_and_dFdy
);
// End Test-phase code
////////////////////////
@ -209,16 +222,15 @@ void main()
vec4 mfact;
const float landclass_texel_size_m = 25.0;
// Partial derivatives of s and t for this fragment,
// with respect to window (screen space) x and y axes.
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
vec2 dx = dFdx(tile_coord);
vec2 dy = dFdy(tile_coord);
// dFdx and dFdy are packed in a vec4 so multiplying
// to scale takes 1 instruction slot.
vec4 dxdy_gc = vec4(dFdx(tile_coord) , dFdy(tile_coord));
get_landclass_id(tile_coord, landclass_texel_size_m, dx, dy,
lc, lc_n, num_unique_neighbors, mfact);
get_landclass_id(tile_coord, dxdy_gc, lc, lc_n, num_unique_neighbors, mfact);
// The landclass id is used to index into arrays containing
// material parameters and textures for the landclass as
@ -230,6 +242,15 @@ void main()
vec4 mat_diffuse, mat_ambient, mat_specular;
float mat_shininess;
// Calculate texture coords for ground textures
// Textures are stretched along the ground to different
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters.
vec2 stretch_dimensions = fg_dimensionsArray[lc].st;
vec2 tileSize = vec2(fg_tileWidth, fg_tileHeight);
vec2 texture_scaling = tileSize.yx / stretch_dimensions.st;
vec2 st = texture_scaling.st * ground_tex_coord.st;
if (fg_photoScenery) {
mat_ambient = vec4(1.0,1.0,1.0,1.0);
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));
} else {
// Color Mode is always AMBIENT_AND_DIFFUSE, which means
// using a base colour of white for ambient/diffuse,
// rather than the material color from ambientArray/diffuseArray.
@ -251,30 +273,9 @@ void main()
// lengths along each axes as set by <xsize> and <ysize>
// regional definitions parameters
// Look up texture coordinates and scale of ground textures
// Landclass for this fragment
texel = lookup_ground_texture_array(tile_coord, lc, dx, dy);
// Lookup the base texture texel for this fragment and any neighbors, with mixing
texel = get_mixed_texel(0, ground_tex_coord, lc, num_unique_neighbors, lc_n, mfact, dxdy_gc);
// Mix texels - to work consistently it needs a more preceptual interpolation than mix()
if (num_unique_neighbors != 0)
{
// Closest neighbor landclass
vec4 texel_closest = lookup_ground_texture_array(tile_coord, lc_n[0], dx, dy);
// Neighbor contributions
vec4 texel_nc=texel_closest;
if (num_unique_neighbors > 1)
{
// 2nd Closest neighbor landclass
vec4 texel_2nd_closest = lookup_ground_texture_array(tile_coord, lc_n[1],
dx, dy);
texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]);
}
texel = mix(texel, texel_nc, mfact[0]);
}
}
vec4 color = mat_ambient * (gl_LightModel.ambient + gl_LightSource[0].ambient);

View file

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

View file

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

View file

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