1
0
Fork 0

WS30: MR #267: Improved texture lookups from VS

Squashed commit of the following:

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

    WS30 effects and shaders:

    Changelog:

    ws30-ALS-ultra.frag:

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

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

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

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

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

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

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

    ----

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

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

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

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

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

    ----

    WS30-overlay effect (Inactive):

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

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

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

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

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

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

    ----

    Changes after the multi-texture support commit:

    ws30-ALS-ultra.vert

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

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

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

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

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

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

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

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

    ----

    Changes after sending material parameters in uniform arrays commit:

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

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,6 @@
#define MODE_DIFFUSE 1 #define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2 #define MODE_AMBIENT_AND_DIFFUSE 2
//attribute vec2 orthophotoTexCoord;
// The constant term of the lighting equation that doesn't depend on // The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha // the surface normal is passed in gl_{Front,Back}Color. The alpha
@ -25,11 +24,11 @@
varying vec4 light_diffuse_comp; varying vec4 light_diffuse_comp;
varying vec3 normal; varying vec3 normal;
varying vec3 relPos; varying vec3 relPos;
varying vec3 rawPos; varying vec2 ground_tex_coord;
varying vec2 rawPos;
varying vec3 worldPos; varying vec3 worldPos;
varying vec3 ecViewdir; varying vec3 ecViewdir;
varying vec2 grad_dir; varying vec2 grad_dir;
//varying vec2 orthoTexCoord;
varying vec4 ecPosition; varying vec4 ecPosition;
// Sent packed into alpha channels // Sent packed into alpha channels
@ -76,227 +75,290 @@ const float terminator_width = 200000.0;
float light_func (in float x, in float a, in float b, in float c, in float d, in float e) float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{ {
//x = x - 0.5; //x = x - 0.5;
// use the asymptotics to shorten computations
// use the asymptotics to shorten computations if (x < -15.0) {return 0.0;}
if (x < -15.0) {return 0.0;} return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
} }
void main() void main()
{ {
vec4 light_diffuse; vec4 light_diffuse;
vec4 light_ambient; vec4 light_ambient;
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88); vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight + vec3 (0.005, 0.005, 0.005); vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight + vec3 (0.005, 0.005, 0.005);
moonLightColor = moonlight_perception (moonLightColor); moonLightColor = moonlight_perception (moonLightColor);
//float yprime_alt; //float yprime_alt;
float yprime; float yprime;
float lightArg; float lightArg;
float intensity; float intensity;
float vertex_alt; float vertex_alt;
float scattering; float scattering;
// The ALS code assumes that units are in meters - e.g. model space vertices (gl_Vertex) are in meters
// WS30 model space, Nov 21, 2021:
// Coordinate axes are the same for geocentric, but not the origin.
// +z direction points from the Earth center to North pole.
// +x direction points from the Earth center to longitude = 0 on the equator.
// +y direction points from the Earth center to logntitude = East on the equator.
// Model space origin is at sea level. Units are in meters.
// Each tile, for each LoD level, its own model origin
// modelOffset is the model origin relative to the Earth center. It is in a geocentric
// space with the same axes, but with the Earth center as the origin. Units are in meters.
rawPos = (fg_zUpTransform * gl_Vertex).xyz;
vec4 pos = gl_Vertex;
if (raise_vertex)
{
pos.z+=0.1;
gl_Position = gl_ModelViewProjectionMatrix * pos;
}
else gl_Position = ftransform();
// this code is copied from default.vert
ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
normal = gl_NormalMatrix * gl_Normal;
///////////////////////////////////////////
// Test phase code:
//
// Coords for ground textures
// Due to precision issues coordinates should restart (i.e. go to zero) every 5000m or so.
const float restart_dist_m = 5000.0;
// Model position
vec3 mp = gl_Vertex.xyz;
// Temporary approximation to get shaders to compile:
ground_tex_coord = gl_TexCoord[0].st;
//
// End test phase code
///////////////////////////////////////////
// WS2:
// first current altitude of eye position in model space
// vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
//relPos = gl_Vertex.xyz - ep.xyz;
// Transform for frame of reference where:
// +z is in the up direction.
// The orientation of x and y axes are unknown currently.
// The origin is at the same position as the model space origin.
// The units are in meters.
mat4 viewSpaceToZUpSpace = fg_zUpTransform * gl_ModelViewMatrixInverse;
vec4 vertexZUp = fg_zUpTransform * gl_Vertex;
// WS2: rawPos = gl_Vertex.xy;
rawPos = vertexZUp.xy;
// WS2: worldPos = (osg_ViewMatrixInverse *gl_ModelViewMatrix * gl_Vertex).xyz;
worldPos = fg_modelOffset + gl_Vertex.xyz; worldPos = fg_modelOffset + gl_Vertex.xyz;
steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
grad_dir = normalize(gl_Normal.xy);
vec4 pos = gl_Vertex; steepness = dot(normalize(vec3(fg_zUpTransform * vec4(gl_Normal,1.0))), vec3 (0.0, 0.0, 1.0));
if (raise_vertex) // Gradient direction used for small scale noise. In the same space as noise coords, rawpos.xy.
{ grad_dir = normalize(gl_Normal.xy);
pos.z+=0.1;
gl_Position = gl_ModelViewProjectionMatrix * pos; // here start computations for the haze layer
} // we need several geometrical quantities
else gl_Position = ftransform();
// Eye position in z up space
vec4 epZUp = viewSpaceToZUpSpace * vec4(0.0,0.0,0.0,1.0);
// Position of vertex relative to the eye position in z up space
vec3 relPosZUp = (vertexZUp - epZUp).xyz;
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// Eye position in model space
vec4 epMS = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
/*
//old: and relative position to vector. This is also used for cloud shadow positioning.
relPosOld = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
if (any(notEqual(relPosOld, relPosZUp))) relPos = vec3(1000000.0);
*/
relPos = relPosZUp;
ecViewdir = (gl_ModelViewMatrix * (epMS - gl_Vertex)).xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again
float dist = length(relPos);
// Altitude of the vertex above mean sea level in meters.
// This is equal to vertexZUp.z as the model space origin is at mean sea level.
// Somehow zero leads to artefacts, so ensure it is at least 100m.
//WS2: vertex_alt = max(gl_Vertex.z,100.0);
vertex_alt = max(vertexZUp.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// this code is copied from default.vert // branch dependent on daytime
ecPosition = gl_ModelViewMatrix * gl_Vertex;
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
//orthoTexCoord = orthophotoTexCoord;
normal = gl_NormalMatrix * gl_Normal;
// here start computations for the haze layer
// we need several geometrical quantities
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
relPos = (fg_zUpTransform * vec4(gl_Vertex - ep)).xyz;
ecViewdir = (gl_ModelViewMatrix * (ep - gl_Vertex)).xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again
float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m
vertex_alt = max(rawPos.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// branch dependent on daytime
if (terminator < 1000000.0) // the full, sunrise and sunset computation if (terminator < 1000000.0) // the full, sunrise and sunset computation
{ {
// establish coordinates relative to sun position // establish coordinates relative to sun position
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz; vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0)); vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction // yprime is the distance of the vertex into sun direction
yprime = -dot(relPos, lightHorizon); yprime = -dot(relPos, lightHorizon);
// this gets an altitude correction, higher terrain gets to see the sun earlier // this gets an altitude correction, higher terrain gets to see the sun earlier
yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt); yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
// two times terminator width governs how quickly light fades into shadow // two times terminator width governs how quickly light fades into shadow
// now the light-dimming factor // now the light-dimming factor
earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4; earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
// parametrized version of the Flightgear ground lighting function // parametrized version of the Flightgear ground lighting function
lightArg = (terminator-yprime_alt)/100000.0; lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun // directional scattering for low sun
if (lightArg < 10.0) if (lightArg < 10.0)
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;} {mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else else
{mie_angle = 1.0;} {mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
light_diffuse.a = 1.0;
light_diffuse = light_diffuse * scattering;
//light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
//light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
light_ambient.g = light_ambient.r * 0.4/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.4);
light_ambient.b = light_ambient.r * 0.5/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.5);
light_ambient.a = 1.0;
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0); // correct ambient light intensity and hue before sunrise
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0); if (earthShade < 0.5)
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0); {
light_diffuse.a = 1.0; intensity = length(light_ambient.rgb);
light_diffuse = light_diffuse * scattering; light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.8,earthShade) ));
light_ambient.rgb = light_ambient.rgb + moonLightColor * (1.0 - smoothstep(0.4, 0.5, earthShade));
//light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
//light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4); intensity = length(light_diffuse.rgb);
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33); light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) ));
light_ambient.g = light_ambient.r * 0.4/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.4); }
light_ambient.b = light_ambient.r * 0.5/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.5);
light_ambient.a = 1.0;
// the haze gets the light at the altitude of the haze top if the vertex in view is below
// but the light at the vertex if the vertex is above
vertex_alt = max(vertex_alt,hazeLayerAltitude);
if (vertex_alt > hazeLayerAltitude)
// correct ambient light intensity and hue before sunrise {
if (earthShade < 0.5) if (dist > 0.8 * avisibility)
{ {
intensity = length(light_ambient.rgb); vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.8,earthShade) )); yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
light_ambient.rgb = light_ambient.rgb + moonLightColor * (1.0 - smoothstep(0.4, 0.5, earthShade)); }
}
intensity = length(light_diffuse.rgb); else
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) )); {
} vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
// the haze gets the light at the altitude of the haze top if the vertex in view is below
// but the light at the vertex if the vertex is above } // End if (terminator < 1000000.0)
else // the faster, full-day version without lightfields
vertex_alt = max(vertex_alt,hazeLayerAltitude); {
if (vertex_alt > hazeLayerAltitude)
{
if (dist > 0.8 * avisibility)
{
vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else
{
vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else // the faster, full-day version without lightfields
{
//vertex_alt = max(gl_Vertex.z,100.0); //vertex_alt = max(gl_Vertex.z,100.0);
earthShade = 1.0; earthShade = 1.0;
mie_angle = 1.0; mie_angle = 1.0;
if (terminator > 3000000.0) if (terminator > 3000000.0)
{light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0); {
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0); } light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0);
}
else else
{ {
lightArg = (terminator/100000.0 - 10.0)/20.0;
lightArg = (terminator/100000.0 - 10.0)/20.0; light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.b = 0.78 + lightArg * 0.21; light_diffuse.g = 0.907 + lightArg * 0.091;
light_diffuse.g = 0.907 + lightArg * 0.091; light_diffuse.r = 0.904 + lightArg * 0.092;
light_diffuse.r = 0.904 + lightArg * 0.092; light_diffuse.a = 1.0;
light_diffuse.a = 1.0;
//light_ambient.b = 0.41 + lightArg * 0.08;
//light_ambient.g = 0.333 + lightArg * 0.06;
light_ambient.r = 0.316 + lightArg * 0.016;
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.0;
}
//light_ambient.b = 0.41 + lightArg * 0.08;
//light_ambient.g = 0.333 + lightArg * 0.06;
light_ambient.r = 0.316 + lightArg * 0.016;
light_ambient.g = light_ambient.r * 0.4/0.33;
light_ambient.b = light_ambient.r * 0.5/0.33;
light_ambient.a = 1.0;
}
light_diffuse = light_diffuse * scattering; light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude); yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
} //End the faster, full-day version without lightfields
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so // a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
// steep faces end up shaded more // steep faces end up shaded more
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2);
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2); // deeper shadows when there is lots of direct light
// deeper shadows when there is lots of direct light float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smoothstep(0.1,0.5,overcast)) * smoothstep(0.4,1.5,earthShade);
float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smoothstep(0.1,0.5,overcast)) * smoothstep(0.4,1.5,earthShade); light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth); if (use_IR_vision)
{
if (use_IR_vision) light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5));
{ }
light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5));
}
// default lighting based on texture and material using the light we have just computed // default lighting based on texture and material using the light we have just computed
light_diffuse_comp = light_diffuse; light_diffuse_comp = light_diffuse;
//Testing phase code: ambient colours are not sent to fragement shader yet. //Testing phase code: ambient colours are not sent to fragement shader yet.
// They are all default except for water/ocean etc. currently // They are all default except for water/ocean etc. currently
// Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0) // Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0)
//To do: Fix this once ambient colour becomes available in the fragment shaders. //To do: Fix this once ambient colour becomes available in the fragment shaders.
//const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0); //const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
const vec4 ambient_color = vec4(1.0); const vec4 ambient_color = vec4(1.0);
vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient); vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient);
light_diffuse_comp.a = yprime_alt; light_diffuse_comp.a = yprime_alt;
gl_FrontColor.rgb = constant_term.rgb; // gl_FrontColor.a = 1.0; gl_FrontColor.rgb = constant_term.rgb; // gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; // gl_BackColor.a = 0.0; gl_BackColor.rgb = constant_term.rgb; // gl_BackColor.a = 0.0;
gl_FrontColor.a = mie_angle; gl_FrontColor.a = mie_angle;
gl_BackColor.a = mie_angle; gl_BackColor.a = mie_angle;
setupShadows(ecPosition); setupShadows(ecPosition);
} }

View file

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

View file

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

View file

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

View file

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