WS30 shaders:
Add WS3 detailed technique using the "6" slot. Port the ALS haze, lighting, and math parts of the detailed and ultra shaders. The texture lookups are left out. Shader selection based on terrain quality setting: - Ultra - ws30-ALS-ultra frag/vert. - High and Medium - ws30-ALS-detailed frag/vert. The shaders switch code paths based on quality level uniform. - Low - ws30-ALS frag/vert. Changelog: ws30-ALS vertex shaders: - Ambient colour material colour doesn't seem to be used in the vertex shader, and isn't sent to fragment shaders currently. Regional materials only define non-default ambient colour of vec4(0.0) for water, ocean etc. Otherwise the default value of vec4(0.2, 0.2, 0.2, 1.0) is used. ws30-ALS.frag: - Set alpha of color to diffuse_term.a, to be consistent with WS2 implementation. ws30-ALS-ultra.frag and ws30-ALS-detailed.frag - World pos is assigned a value to allow noise functions to compile. - Swatch_size is temporarily set to 2000m instead of the xsize texture dimension to allow noise math to run while landclass search and texture arrays are being looked up. Swatch_size is used to adjust the wavelength of multiple overlay mixing noise wavelengths based on how far the textures are stretched (WiP WS2 feature). There are some noise calculations that could run while the first landclass lookup happens. If this is not enough, the selection of calculated noise wavelengths to add could change based on how far the textures are stretched, instead of changing the wavelengths at calculation time. - Move photoscenery technique no "4" after technique no "7" without changing the index (in case the low index is needed for photoscenery). This makes viewing a diff with the WS2 effect easier. Performance: Currently there's only 1 ground texture lookup and landclass transitions for that texture. The ultra shader looks up 5 more textures. Probably transitions for 1 more texture need to be supported, as often a base and overlay texture are mixed contributing heavily to visible colour. The math overhead is mostly present, except for noise math being better hidden than in the eventual version. Some of the texture array lookups in the full version may be hidden by the math - depending on GPU memory handling compared to calculation speed.
This commit is contained in:
parent
851f47f576
commit
64e5abda41
7 changed files with 2892 additions and 486 deletions
996
Effects/ws30.eff
996
Effects/ws30.eff
File diff suppressed because it is too large
Load diff
749
Shaders/ws30-ALS-detailed.frag
Normal file
749
Shaders/ws30-ALS-detailed.frag
Normal file
|
@ -0,0 +1,749 @@
|
|||
// WS30 FRAGMENT SHADER
|
||||
|
||||
// -*-C++-*-
|
||||
#version 130
|
||||
#extension GL_EXT_texture_array : enable
|
||||
// written by Thorsten Renk, Oct 2011, based on default.frag
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// TEST PHASE TOGGLES AND CONTROLS
|
||||
//
|
||||
|
||||
// Development tools:
|
||||
// Reduce haze to almost zero, while preserving lighting. Useful for observing distant tiles.
|
||||
// Keeps the calculation overhead. This can be used for profiling.
|
||||
// Possible values: 0:Normal, 1:Reduced haze.
|
||||
const int reduce_haze_without_removing_calculation_overhead = 0;
|
||||
|
||||
// Remove haze and lighting and shows just the texture.
|
||||
// Useful for checking texture rendering and scenery.
|
||||
// The compiler will likely optimise out the haze and lighting calculations.
|
||||
// Possible values: 0:Normal, 1:Just the texture.
|
||||
const int remove_haze_and_lighting = 0;
|
||||
|
||||
//
|
||||
// End of test phase controls
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// written by Thorsten Renk, Oct 2011, based on default.frag
|
||||
// Ambient term comes in gl_Color.rgb.
|
||||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
varying vec3 relPos;
|
||||
varying vec2 rawPos;
|
||||
//varying vec3 worldPos;
|
||||
// Testing code:
|
||||
vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
|
||||
//varying vec2 orthoTexCoord;
|
||||
varying vec4 eyePos;
|
||||
|
||||
|
||||
uniform sampler2D landclass;
|
||||
uniform sampler2DArray textureArray;
|
||||
uniform sampler1D dimensionsArray;
|
||||
uniform sampler1D diffuseArray;
|
||||
uniform sampler1D specularArray;
|
||||
uniform sampler2D perlin;
|
||||
|
||||
//varying float yprime_alt;
|
||||
//varying float mie_angle;
|
||||
varying float steepness;
|
||||
|
||||
|
||||
uniform float visibility;
|
||||
uniform float avisibility;
|
||||
uniform float scattering;
|
||||
uniform float terminator;
|
||||
uniform float terrain_alt;
|
||||
uniform float hazeLayerAltitude;
|
||||
uniform float overcast;
|
||||
uniform float eye_alt;
|
||||
uniform float snowlevel;
|
||||
uniform float dust_cover_factor;
|
||||
uniform float lichen_cover_factor;
|
||||
uniform float wetness;
|
||||
uniform float fogstructure;
|
||||
uniform float snow_thickness_factor;
|
||||
uniform float cloud_self_shading;
|
||||
uniform float season;
|
||||
// Used by regional definitions
|
||||
uniform float transition_model;
|
||||
uniform float hires_overlay_bias;
|
||||
|
||||
uniform int quality_level;
|
||||
uniform int tquality_level;
|
||||
|
||||
//uniform bool orthophotoAvailable;
|
||||
|
||||
const float EarthRadius = 5800000.0;
|
||||
const float terminator_width = 200000.0;
|
||||
|
||||
//Testing phase: Why are these in global scope in WS2 shaders?
|
||||
float alt;
|
||||
float eShade;
|
||||
float yprime_alt;
|
||||
float mie_angle;
|
||||
|
||||
float shadow_func (in float x, in float y, in float noise, in float dist);
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dot_density);
|
||||
float Noise2D(in vec2 coord, in float wavelength);
|
||||
float Noise3D(in vec3 coord, in float wavelength);
|
||||
float SlopeLines2D(in vec2 coord, in vec2 gradDir, in float wavelength, in float steepness);
|
||||
float Strata3D(in vec3 coord, in float wavelength, in float variation);
|
||||
float fog_func (in float targ, in float alt);
|
||||
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt);
|
||||
float alt_factor(in float eye_alt, in float vertex_alt);
|
||||
float light_distance_fading(in float dist);
|
||||
float fog_backscatter(in float avisibility);
|
||||
|
||||
vec3 rayleigh_out_shift(in vec3 color, in float outscatter);
|
||||
vec3 get_hazeColor(in float light_arg);
|
||||
vec3 searchlight();
|
||||
vec3 landing_light(in float offset, in float offsetv);
|
||||
vec3 filter_combined (in vec3 color) ;
|
||||
|
||||
float getShadowing();
|
||||
vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////
|
||||
// Test-phase code:
|
||||
|
||||
|
||||
// These should be sent as uniforms
|
||||
|
||||
// Tile dimensions in meters
|
||||
// vec2 tile_size = vec2(tile_width , tile_height);
|
||||
// Testing: texture coords are sent flipped right now:
|
||||
|
||||
// Note tile_size is defined in the shader include: ws30-landclass-search-functions.frag.
|
||||
// vec2 tile_size = vec2(tile_height , tile_width);
|
||||
|
||||
// From noise.frag
|
||||
float rand2D(in vec2 co);
|
||||
|
||||
// These functions, and other function they depend on, are defined
|
||||
// in ws30-ALS-landclass-search.frag.
|
||||
|
||||
|
||||
// Create random landclasses without a texture lookup to stress test.
|
||||
// Each square of square_size in m is assigned a random landclass value.
|
||||
int get_random_landclass(in vec2 co, in vec2 tile_size);
|
||||
|
||||
|
||||
// Lookup a ground texture at a point based on the landclass at that point, without visible
|
||||
// seams at coordinate discontinuities or at landclass boundaries where texture are switched.
|
||||
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
|
||||
// the stretching of different textures, so that the correct mip-map level is looked
|
||||
// up and there are no seams.
|
||||
|
||||
vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int landclass_id,
|
||||
in vec2 dx, in vec2 dy);
|
||||
|
||||
|
||||
// Look up the landclass id [0 .. 255] for this particular fragment.
|
||||
// Lookup id of any neighbouring landclass that is within the search distance.
|
||||
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
|
||||
// Create a mix factor werighting the influences of nearby landclasses
|
||||
void get_landclass_id(in vec2 tile_coord,
|
||||
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
|
||||
out int landclass_id, out ivec4 neighbor_landclass_ids,
|
||||
out int num_unique_neighbors,out vec4 mix_factor
|
||||
);
|
||||
|
||||
|
||||
// End Test-phase code
|
||||
////////////////////////
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
|
||||
yprime_alt = light_diffuse_comp.a;
|
||||
//diffuse_term.a = 1.0;
|
||||
mie_angle = gl_Color.a;
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
|
||||
// distance to fragment
|
||||
|
||||
float dist = length(relPos);
|
||||
// angle of view vector with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
|
||||
|
||||
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
// this is taken from default.frag
|
||||
vec3 n;
|
||||
float NdotL, NdotHV, fogFactor;
|
||||
vec3 lightDir = gl_LightSource[0].position.xyz;
|
||||
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
|
||||
//vec3 halfVector = normalize(normalize(lightDir) + normalize(ecViewdir));
|
||||
vec4 texel;
|
||||
vec4 snow_texel;
|
||||
vec4 detail_texel;
|
||||
vec4 mix_texel;
|
||||
vec4 fragColor;
|
||||
vec4 specular = vec4(0.0);
|
||||
float intensity;
|
||||
|
||||
|
||||
// get noise at different wavelengths
|
||||
|
||||
// used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow
|
||||
// 50m: detail texel
|
||||
// 250m: detail texel
|
||||
// 500m: distortion and overlay
|
||||
// 1500m: overlay, detail, dust, fog
|
||||
// 2000m: overlay, detail, snow, fog
|
||||
|
||||
float noise_10m;
|
||||
float noise_5m;
|
||||
noise_10m = Noise2D(rawPos.xy, 10.0);
|
||||
noise_5m = Noise2D(rawPos.xy ,5.0);
|
||||
|
||||
float noisegrad_10m;
|
||||
float noisegrad_5m;
|
||||
|
||||
float noise_50m = Noise2D(rawPos.xy, 50.0);;
|
||||
|
||||
|
||||
float noise_250m = Noise3D(worldPos.xyz,250.0);
|
||||
float noise_500m = Noise3D(worldPos.xyz, 500.0);
|
||||
float noise_1500m = Noise3D(worldPos.xyz, 1500.0);
|
||||
float noise_2000m = Noise3D(worldPos.xyz, 2000.0);
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
// get the texels
|
||||
|
||||
// Oct 27 2021:
|
||||
// Geometry is in the form of roughly rectangular 'tiles'
|
||||
// with a mesh forming a grid with regular spacing.
|
||||
// Each vertex in the mesh is given an elevation
|
||||
|
||||
// Tile dimensions in m
|
||||
// Testing: created from two float uniforms in global scope. Should be sent as a vec2
|
||||
// vec2 tile_size
|
||||
|
||||
// Tile texture coordinates range [0..1] over the tile 'rectangle'
|
||||
vec2 tile_coord = gl_TexCoord[0].st;
|
||||
|
||||
// Test phase: Constants and toggles for transitions between landlcasses are defined at
|
||||
// the top of this file.
|
||||
|
||||
// Look up the landclass id [0 .. 255] for this particular fragment
|
||||
// and any neighbouring landclass that is close.
|
||||
// Each tile has 1 texture containing landclass ids stetched over it.
|
||||
|
||||
// Landclass for current fragment, and up-to 4 neighboring landclasses - 2 used currently
|
||||
int lc;
|
||||
ivec4 lc_n;
|
||||
|
||||
int num_unique_neighbors = 0;
|
||||
|
||||
// Mix factor of base textures for 2 neighbour landclass(es)
|
||||
vec4 mfact;
|
||||
|
||||
|
||||
const float landclass_texel_size_m = 25.0;
|
||||
|
||||
// Partial derivatives of s and t for this fragment,
|
||||
// with respect to window (screen space) x and y axes.
|
||||
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
|
||||
vec2 dx = dFdx(tile_coord);
|
||||
vec2 dy = dFdy(tile_coord);
|
||||
|
||||
get_landclass_id(tile_coord, landclass_texel_size_m, dx, dy,
|
||||
lc, lc_n, num_unique_neighbors, mfact);
|
||||
|
||||
// The landclass id is used to index into arrays containing
|
||||
// material parameters and textures for the landclass as
|
||||
// defined in the regional definitions
|
||||
float index = float(lc)/512.0;
|
||||
vec4 index_n = vec4(lc_n)/512.0;
|
||||
|
||||
float mat_shininess = texture(dimensionsArray, index).z;
|
||||
vec4 mat_diffuse = texture(diffuseArray, index);
|
||||
vec4 mat_specular = texture(specularArray, index);
|
||||
|
||||
vec4 color = gl_Color;
|
||||
color.a = 1.0;
|
||||
|
||||
|
||||
|
||||
// Testing code:
|
||||
// Use rlc even when looking up textures to recreate the extra performance hit
|
||||
// so any performance difference between the two is due to the texture lookup
|
||||
// color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
|
||||
|
||||
|
||||
|
||||
|
||||
// Look up ground textures by indexing into the texture array.
|
||||
// Different textures are stretched along the ground to different
|
||||
// lengths along each axes as set by <xsize> and <ysize>
|
||||
// regional definitions parameters
|
||||
|
||||
// Look up texture coordinates and scale of ground textures
|
||||
|
||||
// Landclass for this fragment
|
||||
|
||||
texel = lookup_ground_texture_array(index, 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(index_n[0], 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(index_n[1], tile_coord, lc_n[1],
|
||||
dx, dy);
|
||||
|
||||
|
||||
texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]);
|
||||
}
|
||||
|
||||
texel = mix(texel, texel_nc, mfact[0]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Testing code: mix with green to show values of variables at each point
|
||||
//vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
|
||||
//texel = mix(texel, green, (mfact[2]));
|
||||
|
||||
// Testing code: temp
|
||||
mix_texel = texel;
|
||||
detail_texel = texel;
|
||||
|
||||
int flag = 1;
|
||||
int mix_flag = 1;
|
||||
|
||||
|
||||
float local_autumn_factor = texel.a;
|
||||
/*
|
||||
if (orthophotoAvailable) {
|
||||
vec4 sat_texel = texture2D(orthophotoTexture, orthoTexCoord);
|
||||
if (sat_texel.a > 0) {
|
||||
texel.rgb = sat_texel.rgb;
|
||||
flag = 0;
|
||||
mix_flag = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
float distortion_factor = 1.0;
|
||||
vec2 stprime;
|
||||
|
||||
float noise_term;
|
||||
float snow_alpha;
|
||||
|
||||
//float view_angle = abs(dot(normal, normalize(ecViewdir)));
|
||||
|
||||
if ((quality_level > 3)&&(relPos.z + eye_alt +500.0 > snowlevel))
|
||||
{
|
||||
float sfactor;
|
||||
snow_texel = vec4 (0.95, 0.95, 0.95, 1.0) * (0.9 + 0.1* noise_500m + 0.1* (1.0 - noise_10m) );
|
||||
snow_texel.r = snow_texel.r * (0.9 + 0.05 * (noise_10m + noise_5m));
|
||||
snow_texel.g = snow_texel.g * (0.9 + 0.05 * (noise_10m + noise_5m));
|
||||
snow_texel.a = 1.0;
|
||||
noise_term = 0.1 * (noise_500m-0.5);
|
||||
sfactor = sqrt(2.0 * (1.0-steepness)/0.03) + abs(ct)/0.15;
|
||||
noise_term = noise_term + 0.2 * (noise_50m -0.5) * (1.0 - smoothstep(18000.0*sfactor, 40000.0*sfactor, dist) ) ;
|
||||
noise_term = noise_term + 0.3 * (noise_10m -0.5) * (1.0 - smoothstep(4000.0 * sfactor, 8000.0 * sfactor, dist) ) ;
|
||||
if (dist < 3000.0*sfactor){ 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*(relPos.z +eye_alt -snowlevel) );
|
||||
|
||||
}
|
||||
|
||||
if ((tquality_level > 2) && (mix_flag == 1))
|
||||
{
|
||||
//mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3); // temp
|
||||
if (mix_texel.a <0.1) {mix_flag = 0;}
|
||||
}
|
||||
|
||||
|
||||
if (tquality_level > 3 && (flag == 1))
|
||||
{
|
||||
stprime = vec2 (0.86*gl_TexCoord[0].s + 0.5*gl_TexCoord[0].t, 0.5*gl_TexCoord[0].s - 0.86*gl_TexCoord[0].t);
|
||||
//distortion_factor = 0.9375 + (1.0 * nvL[2]);
|
||||
distortion_factor = 0.97 + 0.06 * noise_500m;
|
||||
stprime = stprime * distortion_factor * 15.0;
|
||||
if (quality_level > 4)
|
||||
{
|
||||
stprime = stprime + normalize(relPos).xy * 0.02 * (noise_10m + 0.5 * noise_5m - 0.75);
|
||||
}
|
||||
//detail_texel = texture2D(detail_texture, stprime); // temp
|
||||
if (detail_texel.a <0.1) {flag = 0;}
|
||||
}
|
||||
|
||||
|
||||
// texture preparation according to detail level
|
||||
|
||||
// mix in hires texture patches
|
||||
|
||||
float dist_fact;
|
||||
float nSum;
|
||||
float mix_factor;
|
||||
|
||||
if (tquality_level > 2)
|
||||
{
|
||||
// first the second texture overlay
|
||||
// transition model 0: random patch overlay without any gradient information
|
||||
// transition model 1: only gradient-driven transitions, no randomness
|
||||
|
||||
|
||||
if (mix_flag == 1)
|
||||
{
|
||||
nSum = 0.18 * (2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
|
||||
nSum = mix(nSum, 0.5, max(0.0, 2.0 * (transition_model - 0.5)));
|
||||
nSum = nSum + 0.4 * (1.0 -smoothstep(0.9,0.95, abs(steepness)+ 0.05 * (noise_50m - 0.5))) * min(1.0, 2.0 * transition_model);
|
||||
mix_factor = smoothstep(0.5, 0.54, nSum);
|
||||
texel = mix(texel, mix_texel, mix_factor);
|
||||
local_autumn_factor = texel.a;
|
||||
}
|
||||
|
||||
// then the detail texture overlay
|
||||
}
|
||||
|
||||
if (tquality_level > 3)
|
||||
{
|
||||
if (dist < 40000.0)
|
||||
{
|
||||
if (flag == 1)
|
||||
{
|
||||
//noise_50m = Noise2D(rawPos.xy, 50.0);
|
||||
//noise_250m = Noise2D(rawPos.xy, 250.0);
|
||||
dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist));
|
||||
nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0;
|
||||
nSum = nSum - 0.08 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
|
||||
mix_factor = smoothstep(0.47, 0.54, nSum +hires_overlay_bias - dist_fact);
|
||||
if (mix_factor > 0.8) {mix_factor = 0.8;}
|
||||
texel = mix(texel, detail_texel,mix_factor);
|
||||
local_autumn_factor = texel.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// autumn colors
|
||||
|
||||
float autumn_factor = season * 2.0 * (1.0 - local_autumn_factor) ;
|
||||
|
||||
|
||||
texel.r = min(1.0, (1.0 + 2.5 * autumn_factor) * texel.r);
|
||||
texel.g = texel.g;
|
||||
texel.b = max(0.0, (1.0 - 4.0 * autumn_factor) * texel.b);
|
||||
|
||||
|
||||
if (local_autumn_factor < 1.0)
|
||||
{
|
||||
intensity = length(texel.rgb) * (1.0 - 0.5 * smoothstep(1.1,2.0,season));
|
||||
texel.rgb = intensity * normalize(mix(texel.rgb, vec3(0.23,0.17,0.08), smoothstep(1.1,2.0, season)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
const vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
|
||||
const vec4 lichen_color = vec4 (0.17, 0.20, 0.06, 1.0);;
|
||||
//float snow_alpha;
|
||||
|
||||
if (quality_level > 3)
|
||||
{
|
||||
|
||||
// mix vegetation
|
||||
texel = mix(texel, lichen_color, 0.4 * lichen_cover_factor + 0.8 * lichen_cover_factor * 0.5 * (noise_10m + (1.0 - noise_5m)) );
|
||||
// mix dust
|
||||
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
|
||||
|
||||
// mix snow
|
||||
if (relPos.z + eye_alt +500.0 > snowlevel)
|
||||
{
|
||||
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
|
||||
//texel = mix(texel, snow_texel, texel_snow_fraction);
|
||||
texel = mix(texel, snow_texel, snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (relPos.z + eye_alt)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
|
||||
}
|
||||
}
|
||||
else if (relPos.z + eye_alt +500.0 > snowlevel)
|
||||
{
|
||||
float snow_alpha = 0.5+0.5* smoothstep(0.2,0.8, 0.3 + snow_thickness_factor +0.0001*(relPos.z +eye_alt -snowlevel) );
|
||||
// texel = vec4(dot(vec3(0.2989, 0.5870, 0.1140), texel.rgb));
|
||||
texel = mix(texel, vec4(1.0), snow_alpha* smoothstep(snowlevel, snowlevel+200.0, (relPos.z + eye_alt)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get distribution of water when terrain is wet
|
||||
|
||||
float water_threshold1;
|
||||
float water_threshold2;
|
||||
float water_factor =0.0;
|
||||
|
||||
|
||||
if ((dist < 5000.0)&& (quality_level > 3) && (wetness>0.0))
|
||||
{
|
||||
water_threshold1 = 1.0-0.5* wetness;
|
||||
water_threshold2 = 1.0 - 0.3 * wetness;
|
||||
water_factor = smoothstep(water_threshold1, water_threshold2 , (0.3 * (2.0 * (1.0-noise_10m) + (1.0 -noise_5m)) * (1.0 - smoothstep(2000.0, 5000.0, dist))) - 5.0 * (1.0 -steepness));
|
||||
}
|
||||
|
||||
// darken wet terrain
|
||||
|
||||
texel.rgb = texel.rgb * (1.0 - 0.6 * wetness);
|
||||
|
||||
|
||||
// light computations
|
||||
|
||||
|
||||
vec4 light_specular = gl_LightSource[0].specular;
|
||||
|
||||
// If gl_Color.a == 0, this is a back-facing polygon and the
|
||||
// normal should be reversed.
|
||||
//n = (2.0 * gl_Color.a - 1.0) * normal;
|
||||
n = normal;//vec3 (nvec.x, nvec.y, sqrt(1.0 -pow(nvec.x,2.0) - pow(nvec.y,2.0) ));
|
||||
n = normalize(n);
|
||||
|
||||
NdotL = dot(n, lightDir);
|
||||
if ((tquality_level > 3) && (mix_flag ==1)&& (dist < 2000.0) && (quality_level > 4))
|
||||
{
|
||||
noisegrad_10m = (noise_10m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0))/0.05;
|
||||
noisegrad_5m = (noise_5m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),5.0))/0.05;
|
||||
NdotL = NdotL + 1.0 * (noisegrad_10m + 0.5* noisegrad_5m) * mix_factor/0.8 * (1.0 - smoothstep(1000.0, 2000.0, dist));
|
||||
}
|
||||
|
||||
|
||||
if (NdotL > 0.0) {
|
||||
float shadowmap = getShadowing();
|
||||
vec4 diffuse_term = light_diffuse_comp * mat_diffuse;
|
||||
color += diffuse_term * NdotL * shadowmap;
|
||||
NdotHV = max(dot(n, halfVector), 0.0);
|
||||
if (mat_shininess > 0.0)
|
||||
specular.rgb = (mat_specular.rgb
|
||||
* light_specular.rgb
|
||||
* pow(NdotHV, mat_shininess)
|
||||
* shadowmap);
|
||||
}
|
||||
color.a = 1.0;//diffuse_term.a;
|
||||
// This shouldn't be necessary, but our lighting becomes very
|
||||
// saturated. Clamping the color before modulating by the texture
|
||||
// is closer to what the OpenGL fixed function pipeline does.
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
|
||||
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(eyePos.xyz, n, texel.rgb);
|
||||
|
||||
// here comes the terrain haze model
|
||||
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
|
||||
|
||||
if (dist > 0.04 * min(visibility,avisibility))
|
||||
//if ((gl_FragCoord.y > ylimit) || (gl_FragCoord.x < zlimit1) || (gl_FragCoord.x > zlimit2))
|
||||
//if (dist > 40.0)
|
||||
{
|
||||
|
||||
alt = eye_alt;
|
||||
|
||||
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
|
||||
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
|
||||
if (delta_z > 0.0) // we're inside the layer
|
||||
{
|
||||
if (ct < 0.0) // we look down
|
||||
{
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
else // we may look through upper layer edge
|
||||
{
|
||||
H = dist * ct;
|
||||
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
|
||||
else {distance_in_layer = dist;}
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
|
||||
float eqColorFactor;
|
||||
|
||||
|
||||
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
if (quality_level > 3)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/visibility);
|
||||
}
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quality_level > 3)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
|
||||
}
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 - effective_scattering);
|
||||
}
|
||||
|
||||
transmission = fog_func(transmission_arg, alt);
|
||||
|
||||
// there's always residual intensity, we should never be driven to zero
|
||||
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
|
||||
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
|
||||
// Mie-like factor
|
||||
|
||||
if (lightArg < 10.0)
|
||||
{
|
||||
intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
intensity = length(hazeColor);
|
||||
|
||||
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
|
||||
{
|
||||
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
|
||||
// blue hue of haze
|
||||
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
|
||||
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
float shadow = mix( min(1.0 + dot(n,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
{
|
||||
transmission = 1.0 - (transmission/1000000.0);
|
||||
}
|
||||
|
||||
fragColor.rgb = mix(clamp(hazeColor,0.0,1.0) , clamp(fragColor.rgb,0.0,1.0),transmission);
|
||||
|
||||
}
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
|
||||
|
||||
|
||||
// Testing phase controls:
|
||||
if (remove_haze_and_lighting == 1)
|
||||
{
|
||||
gl_FragColor = texel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
296
Shaders/ws30-ALS-detailed.vert
Normal file
296
Shaders/ws30-ALS-detailed.vert
Normal file
|
@ -0,0 +1,296 @@
|
|||
// WS30 VERTEX SHADER
|
||||
// -*-C++-*-
|
||||
#version 120
|
||||
|
||||
// Shader that uses OpenGL state values to do per-pixel lighting
|
||||
//
|
||||
// The only light used is gl_LightSource[0], which is assumed to be
|
||||
// directional.
|
||||
//
|
||||
// Colors are not assigned in this shader, as they will come from
|
||||
// the landclass lookup in the fragment shader.
|
||||
// Haze part added by Thorsten Renk, Oct. 2011
|
||||
|
||||
|
||||
#define MODE_OFF 0
|
||||
#define MODE_DIFFUSE 1
|
||||
#define MODE_AMBIENT_AND_DIFFUSE 2
|
||||
|
||||
attribute vec2 orthophotoTexCoord;
|
||||
|
||||
// The constant term of the lighting equation that doesn't depend on
|
||||
// the surface normal is passed in gl_{Front,Back}Color. The alpha
|
||||
// component is set to 1 for front, 0 for back in order to work around
|
||||
// bugs with gl_FrontFacing in the fragment shader.
|
||||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
varying vec3 relPos;
|
||||
varying vec2 rawPos;
|
||||
varying vec3 worldPos;
|
||||
//varying vec2 orthoTexCoord;
|
||||
varying vec4 eyePos;
|
||||
|
||||
// Sent packed into alpha channels
|
||||
//varying float yprime_alt;
|
||||
varying float mie_angle;
|
||||
|
||||
varying float steepness;
|
||||
|
||||
uniform int colorMode;
|
||||
uniform float hazeLayerAltitude;
|
||||
uniform float terminator;
|
||||
uniform float terrain_alt;
|
||||
uniform float avisibility;
|
||||
uniform float visibility;
|
||||
uniform float overcast;
|
||||
uniform float ground_scattering;
|
||||
uniform float eye_alt;
|
||||
uniform float moonlight;
|
||||
|
||||
uniform bool use_IR_vision;
|
||||
|
||||
uniform mat4 osg_ViewMatrixInverse;
|
||||
|
||||
float earthShade;
|
||||
float yprime_alt;
|
||||
//float mie_angle;
|
||||
|
||||
|
||||
// This is the value used in the skydome scattering shader - use the same here for consistency?
|
||||
const float EarthRadius = 5800000.0;
|
||||
const float terminator_width = 200000.0;
|
||||
|
||||
vec3 moonlight_perception (in vec3 light);
|
||||
void setupShadows(vec4 eyeSpacePos);
|
||||
|
||||
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
|
||||
{
|
||||
//x = x - 0.5;
|
||||
|
||||
// use the asymptotics to shorten computations
|
||||
if (x < -15.0) {return 0.0;}
|
||||
|
||||
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
vec4 light_diffuse;
|
||||
vec4 light_ambient;
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight;
|
||||
moonLightColor = moonlight_perception (moonLightColor);
|
||||
|
||||
|
||||
//float yprime_alt;
|
||||
float yprime;
|
||||
float lightArg;
|
||||
float intensity;
|
||||
float vertex_alt;
|
||||
float scattering;
|
||||
|
||||
rawPos = gl_Vertex.xy;
|
||||
eyePos = gl_ModelViewMatrix * gl_Vertex;
|
||||
worldPos = (osg_ViewMatrixInverse * eyePos).xyz;
|
||||
steepness = dot(normalize(gl_Normal), vec3 (0.0, 0.0, 1.0));
|
||||
|
||||
|
||||
// this code is copied from default.vert
|
||||
|
||||
//vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||
//orthoTexCoord = orthophotoTexCoord;
|
||||
normal = gl_NormalMatrix * gl_Normal;
|
||||
//nvec = (gl_NormalMatrix * gl_Normal).xy;
|
||||
|
||||
// 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 = gl_Vertex.xyz - 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(gl_Vertex.z,100.0);
|
||||
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
|
||||
|
||||
|
||||
// early culling of vertices which can't be seen due to ground haze despite being in aloft visibility range
|
||||
|
||||
//float delta_z = hazeLayerAltitude - eye_alt;
|
||||
//if (((dist * (relPos.z - delta_z)/relPos.z > visibility ) && (relPos.z < 0.0) && (delta_z < 0.0) && (dist > 30000.0)))
|
||||
if (0==1)
|
||||
{
|
||||
gl_Position = vec4(0.0, 0.0, -1000.0, 1.0); // move outside of view frustrum, gets culled before reaching fragment shader
|
||||
earthShade = 1.0;
|
||||
mie_angle = 1.0;
|
||||
yprime_alt = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
// branch dependent on daytime
|
||||
|
||||
if (terminator < 1000000.0) // the full, sunrise and sunset computation
|
||||
{
|
||||
|
||||
|
||||
// establish coordinates relative to sun position
|
||||
|
||||
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
|
||||
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
|
||||
|
||||
|
||||
|
||||
// yprime is the distance of the vertex into sun direction
|
||||
yprime = -dot(relPos, lightHorizon);
|
||||
|
||||
// this gets an altitude correction, higher terrain gets to see the sun earlier
|
||||
yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
|
||||
|
||||
// two times terminator width governs how quickly light fades into shadow
|
||||
// now the light-dimming factor
|
||||
earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
|
||||
|
||||
// parametrized version of the Flightgear ground lighting function
|
||||
lightArg = (terminator-yprime_alt)/100000.0;
|
||||
|
||||
// directional scattering for low sun
|
||||
if (lightArg < 10.0)
|
||||
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
|
||||
else
|
||||
{mie_angle = 1.0;}
|
||||
|
||||
|
||||
|
||||
|
||||
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
|
||||
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
|
||||
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
|
||||
light_diffuse.a = 1.0;
|
||||
light_diffuse = light_diffuse * scattering;
|
||||
|
||||
//light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
|
||||
//light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
|
||||
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
|
||||
light_ambient.g = light_ambient.r * 0.4/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.4);
|
||||
light_ambient.b = light_ambient.r * 0.5/0.33; //light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.5);
|
||||
light_ambient.a = 1.0;
|
||||
|
||||
|
||||
|
||||
|
||||
// correct ambient light intensity and hue before sunrise
|
||||
if (earthShade < 0.5)
|
||||
{
|
||||
intensity = length(light_ambient.rgb);
|
||||
light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.8,earthShade) ));
|
||||
light_ambient.rgb = light_ambient.rgb + moonLightColor * (1.0 - smoothstep(0.4, 0.5, earthShade));
|
||||
|
||||
intensity = length(light_diffuse.rgb);
|
||||
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) ));
|
||||
}
|
||||
|
||||
|
||||
// the haze gets the light at the altitude of the haze top if the vertex in view is below
|
||||
// but the light at the vertex if the vertex is above
|
||||
|
||||
vertex_alt = max(vertex_alt,hazeLayerAltitude);
|
||||
|
||||
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);
|
||||
|
||||
earthShade = 1.0;
|
||||
mie_angle = 1.0;
|
||||
|
||||
if (terminator > 3000000.0)
|
||||
{light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
|
||||
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0); }
|
||||
else
|
||||
{
|
||||
|
||||
lightArg = (terminator/100000.0 - 10.0)/20.0;
|
||||
light_diffuse.b = 0.78 + lightArg * 0.21;
|
||||
light_diffuse.g = 0.907 + lightArg * 0.091;
|
||||
light_diffuse.r = 0.904 + lightArg * 0.092;
|
||||
light_diffuse.a = 1.0;
|
||||
|
||||
//light_ambient.b = 0.41 + lightArg * 0.08;
|
||||
//light_ambient.g = 0.333 + lightArg * 0.06;
|
||||
light_ambient.r = 0.316 + lightArg * 0.016;
|
||||
light_ambient.g = light_ambient.r * 0.4/0.33;
|
||||
light_ambient.b = light_ambient.r * 0.5/0.33;
|
||||
light_ambient.a = 1.0;
|
||||
}
|
||||
|
||||
light_diffuse = light_diffuse * scattering;
|
||||
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
|
||||
}
|
||||
|
||||
|
||||
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
|
||||
// steep faces end up shaded more
|
||||
|
||||
light_ambient = light_ambient * ((1.0+steepness)/2.0 * 1.2 + (1.0-steepness)/2.0 * 0.2);
|
||||
|
||||
// deeper shadows when there is lots of direct light
|
||||
|
||||
float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smoothstep(0.1,0.5,overcast)) * smoothstep(0.4,1.5,earthShade);
|
||||
|
||||
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
|
||||
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
|
||||
|
||||
if (use_IR_vision)
|
||||
{
|
||||
light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5));
|
||||
}
|
||||
|
||||
|
||||
// default lighting based on texture and material using the light we have just computed
|
||||
|
||||
light_diffuse_comp = light_diffuse;
|
||||
//Testing phase code: ambient colours are not sent to fragement shader yet.
|
||||
// They are all default except for water/ocean etc. currently
|
||||
// Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0)
|
||||
//To do: Fix this once ambient colour becomes available in the fragment shaders.
|
||||
//const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
|
||||
const vec4 ambient_color = vec4(1.0);
|
||||
vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient);
|
||||
|
||||
light_diffuse_comp.a = yprime_alt;
|
||||
gl_FrontColor.rgb = constant_term.rgb; // gl_FrontColor.a = 1.0;
|
||||
gl_BackColor.rgb = constant_term.rgb; // gl_BackColor.a = 0.0;
|
||||
gl_FrontColor.a = mie_angle;
|
||||
gl_BackColor.a = mie_angle;
|
||||
}
|
||||
|
||||
setupShadows(eyePos);
|
||||
}
|
|
@ -38,11 +38,20 @@
|
|||
|
||||
|
||||
|
||||
|
||||
// written by Thorsten Renk, Oct 2011, based on default.frag
|
||||
// Ambient term comes in gl_Color.rgb.
|
||||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
varying vec3 relPos;
|
||||
varying vec2 rawPos;
|
||||
//varying vec3 worldPos;
|
||||
// Testing code:
|
||||
vec3 worldPos = vec3(5000.0, 6000.0, 7000.0) + vec3(vec2(rawPos), 600.0); // vec3(100.0, 10.0, 3.0);
|
||||
varying vec3 ecViewdir;
|
||||
varying vec2 grad_dir;
|
||||
//varying vec2 orthoTexCoord;
|
||||
varying vec4 ecPosition;
|
||||
|
||||
|
||||
uniform sampler2D landclass;
|
||||
uniform sampler2DArray textureArray;
|
||||
|
@ -51,9 +60,10 @@ uniform sampler1D diffuseArray;
|
|||
uniform sampler1D specularArray;
|
||||
uniform sampler2D perlin;
|
||||
|
||||
varying float yprime_alt;
|
||||
varying float mie_angle;
|
||||
varying vec4 ecPosition;
|
||||
|
||||
varying float steepness;
|
||||
|
||||
|
||||
|
||||
uniform float visibility;
|
||||
uniform float avisibility;
|
||||
|
@ -63,22 +73,50 @@ uniform float terrain_alt;
|
|||
uniform float hazeLayerAltitude;
|
||||
uniform float overcast;
|
||||
uniform float eye_alt;
|
||||
uniform float snowlevel;
|
||||
uniform float dust_cover_factor;
|
||||
uniform float lichen_cover_factor;
|
||||
uniform float wetness;
|
||||
uniform float fogstructure;
|
||||
uniform float snow_thickness_factor;
|
||||
uniform float cloud_self_shading;
|
||||
uniform float season;
|
||||
uniform float air_pollution;
|
||||
// Used by regional definitions
|
||||
uniform float grain_strength;
|
||||
uniform float intrinsic_wetness;
|
||||
uniform float transition_model;
|
||||
uniform float hires_overlay_bias;
|
||||
uniform float dot_density;
|
||||
uniform float dot_size;
|
||||
uniform float dust_resistance;
|
||||
|
||||
// Passed from VPBTechnique, not the Effect
|
||||
uniform int tile_level;
|
||||
uniform float tile_width;
|
||||
uniform float tile_height;
|
||||
uniform float WindE;
|
||||
uniform float WindN;
|
||||
uniform float landing_light1_offset;
|
||||
uniform float landing_light2_offset;
|
||||
uniform float landing_light3_offset;
|
||||
uniform float osg_SimulationTime;
|
||||
|
||||
uniform int wind_effects;
|
||||
uniform int cloud_shadow_flag;
|
||||
uniform int rock_strata;
|
||||
uniform int use_searchlight;
|
||||
uniform int use_landing_light;
|
||||
uniform int use_alt_landing_light;
|
||||
// Testing code: Currently hardcoded to 2000, to allow noise functions to run while waiting for landclass lookup(s)
|
||||
uniform int swatch_size; //in metres, typically 1000 or 2000
|
||||
|
||||
//uniform bool orthophotoAvailable;
|
||||
|
||||
const float EarthRadius = 5800000.0;
|
||||
const float terminator_width = 200000.0;
|
||||
|
||||
float alt;
|
||||
// Testing phase: Why are these in global scope in WS2 shaders?
|
||||
//float alt;
|
||||
float eShade;
|
||||
|
||||
float fog_func (in float targ, in float alt);
|
||||
vec3 get_hazeColor(in float light_arg);
|
||||
vec3 filter_combined (in vec3 color) ;
|
||||
float yprime_alt;
|
||||
float mie_angle;
|
||||
|
||||
float shadow_func (in float x, in float y, in float noise, in float dist);
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dot_density);
|
||||
|
@ -101,12 +139,15 @@ vec3 filter_combined (in vec3 color) ;
|
|||
float getShadowing();
|
||||
vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
|
||||
|
||||
// Not used
|
||||
float luminance(vec3 color)
|
||||
{
|
||||
return dot(vec3(0.212671, 0.715160, 0.072169), color);
|
||||
}
|
||||
|
||||
// a fade function for procedural scales which are smaller than a pixel
|
||||
|
||||
float detail_fade (in float scale, in float angle, in float dist)
|
||||
{
|
||||
float fade_dist = 2000.0 * scale * angle/max(pow(steepness,4.0), 0.1);
|
||||
|
||||
return 1.0 - smoothstep(0.5 * fade_dist, fade_dist, dist);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Test-phase code:
|
||||
|
@ -160,21 +201,135 @@ void get_landclass_id(in vec2 tile_coord,
|
|||
|
||||
void main()
|
||||
{
|
||||
float alt;
|
||||
|
||||
yprime_alt = light_diffuse_comp.a;
|
||||
//diffuse_term.a = 1.0;
|
||||
mie_angle = gl_Color.a;
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
|
||||
// distance to fragment
|
||||
|
||||
float dist = length(relPos);
|
||||
// angle of view vector with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
// float altitude of fragment above sea level
|
||||
float msl_altitude = (relPos.z + eye_alt);
|
||||
|
||||
|
||||
// vec3 shadedFogColor = vec3(0.65, 0.67, 0.78);
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
// this is taken from default.frag
|
||||
vec3 n;
|
||||
float NdotL, NdotHV, fogFactor;
|
||||
vec3 lightDir = gl_LightSource[0].position.xyz;
|
||||
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
|
||||
vec3 halfVector = normalize(normalize(lightDir) + normalize(ecViewdir));
|
||||
|
||||
vec4 texel;
|
||||
vec4 snow_texel;
|
||||
vec4 detail_texel;
|
||||
vec4 mix_texel;
|
||||
vec4 grain_texel;
|
||||
vec4 dot_texel;
|
||||
vec4 gradient_texel;
|
||||
//vec4 foam_texel;
|
||||
|
||||
vec4 fragColor;
|
||||
vec4 specular = vec4(0.0);
|
||||
float intensity;
|
||||
|
||||
|
||||
|
||||
// Wind motion of the overlay noise simulating movement of vegetation and loose debris
|
||||
|
||||
vec2 windPos;
|
||||
|
||||
if (wind_effects > 1)
|
||||
{
|
||||
float windSpeed = length(vec2 (WindE,WindN)) /3.0480;
|
||||
// interfering sine wave wind pattern
|
||||
float sineTerm = sin(0.35 * windSpeed * osg_SimulationTime + 0.05 * (rawPos.x + rawPos.y));
|
||||
sineTerm = sineTerm + sin(0.3 * windSpeed * osg_SimulationTime + 0.04 * (rawPos.x + rawPos.y));
|
||||
sineTerm = sineTerm + sin(0.22 * windSpeed * osg_SimulationTime + 0.05 * (rawPos.x + rawPos.y));
|
||||
sineTerm = sineTerm/3.0;
|
||||
// non-linear amplification to simulate gusts
|
||||
sineTerm = sineTerm * sineTerm;//smoothstep(0.2, 1.0, sineTerm);
|
||||
|
||||
// wind starts moving dust and leaves at around 8 m/s
|
||||
float timeArg = 0.01 * osg_SimulationTime * windSpeed * smoothstep(8.0, 15.0, windSpeed);
|
||||
timeArg = timeArg + 0.02 * sineTerm;
|
||||
|
||||
windPos = vec2 (rawPos.x + WindN * timeArg, rawPos.y + WindE * timeArg);
|
||||
}
|
||||
else
|
||||
{
|
||||
windPos = rawPos.xy;
|
||||
}
|
||||
|
||||
|
||||
// get noise at different wavelengths in units of swatch_size
|
||||
// original assumed 4km texture.
|
||||
|
||||
// used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow
|
||||
// 50m: detail texel
|
||||
// 250m: detail texel
|
||||
// 500m: distortion and overlay
|
||||
// 1500m: overlay, detail, dust, fog
|
||||
// 2000m: overlay, detail, snow, fog
|
||||
|
||||
// Perlin noise
|
||||
|
||||
float noise_10m = Noise2D(rawPos.xy, 10.0);
|
||||
float noise_5m = Noise2D(rawPos.xy ,5.0);
|
||||
float noise_2m = Noise2D(rawPos.xy ,2.0);
|
||||
float noise_1m = Noise2D(rawPos.xy ,1.0);
|
||||
float noise_01m = Noise2D(windPos.xy, 0.1);
|
||||
|
||||
float noisegrad_10m;
|
||||
float noisegrad_5m;
|
||||
float noisegrad_2m;
|
||||
float noisegrad_1m;
|
||||
|
||||
// Noise relative to swatch size
|
||||
|
||||
float noise_25m = Noise2D(rawPos.xy, swatch_size*0.000625);
|
||||
float noise_50m = Noise2D(rawPos.xy, swatch_size*0.00125);
|
||||
|
||||
|
||||
float noise_250m = Noise3D(worldPos.xyz,swatch_size*0.0625);
|
||||
float noise_500m = Noise3D(worldPos.xyz, swatch_size*0.125);
|
||||
float noise_1500m = Noise3D(worldPos.xyz, swatch_size*0.3750);
|
||||
float noise_2000m = Noise3D(worldPos.xyz, swatch_size*0.5);
|
||||
float noise_4000m = Noise3D(worldPos.xyz, swatch_size);
|
||||
|
||||
// dot noise
|
||||
|
||||
float dotnoise_2m = DotNoise2D(rawPos.xy, 2.0 * dot_size,0.5, dot_density);
|
||||
float dotnoise_10m = DotNoise2D(rawPos.xy, 10.0 * dot_size, 0.5, dot_density);
|
||||
float dotnoise_15m = DotNoise2D(rawPos.xy, 15.0 * dot_size, 0.33, dot_density);
|
||||
|
||||
float dotnoisegrad_10m;
|
||||
|
||||
|
||||
// slope noise
|
||||
|
||||
float slopenoise_50m = SlopeLines2D(rawPos, grad_dir, 50.0, steepness);
|
||||
float slopenoise_100m = SlopeLines2D(rawPos, grad_dir, 100.0, steepness);
|
||||
|
||||
float snownoise_25m = mix(noise_25m, slopenoise_50m, clamp(3.0*(1.0-steepness),0.0,1.0));
|
||||
float snownoise_50m = mix(noise_50m, slopenoise_100m, clamp(3.0*(1.0-steepness),0.0,1.0));
|
||||
|
||||
// get the texels
|
||||
|
||||
|
||||
|
||||
float distortion_factor = 1.0;
|
||||
vec2 stprime;
|
||||
int flag = 1;
|
||||
int mix_flag = 1;
|
||||
float noise_term;
|
||||
float snow_alpha;
|
||||
|
||||
// Oct 27 2021:
|
||||
// Geometry is in the form of roughly rectangular 'tiles'
|
||||
// with a mesh forming a grid with regular spacing.
|
||||
|
@ -226,38 +381,17 @@ void main()
|
|||
vec4 mat_specular = texture(specularArray, index);
|
||||
|
||||
vec4 color = gl_Color;
|
||||
color.a = 1.0;
|
||||
|
||||
|
||||
|
||||
// Testing code:
|
||||
// Use rlc even when looking up textures to recreate the extra performance hit
|
||||
// so any performance difference between the two is due to the texture lookup
|
||||
// color = color+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
|
||||
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
|
||||
vec4 light_specular = gl_LightSource[0].specular;
|
||||
|
||||
// If gl_Color.a == 0, this is a back-facing polygon and the
|
||||
// normal should be reversed.
|
||||
//n = (2.0 * gl_Color.a - 1.0) * normal;
|
||||
n = normalize(normal);
|
||||
// color.rgb = color.rgb+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
|
||||
|
||||
|
||||
|
||||
NdotL = dot(n, lightDir);
|
||||
if (NdotL > 0.0) {
|
||||
float shadowmap = getShadowing();
|
||||
color += (light_diffuse_comp * mat_diffuse) * NdotL * shadowmap;
|
||||
NdotHV = max(dot(n, halfVector), 0.0);
|
||||
if (mat_shininess > 0.0)
|
||||
specular.rgb = (mat_specular.rgb
|
||||
* light_specular.rgb
|
||||
* pow(NdotHV, gl_FrontMaterial.shininess)
|
||||
* shadowmap);
|
||||
}
|
||||
color.a = light_diffuse_comp.a;
|
||||
// This shouldn't be necessary, but our lighting becomes very
|
||||
// saturated. Clamping the color before modulating by the texture
|
||||
// is closer to what the OpenGL fixed function pipeline does.
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
|
||||
// Look up ground textures by indexing into the texture array.
|
||||
|
@ -302,12 +436,289 @@ void main()
|
|||
//texel = mix(texel, green, (mfact[2]));
|
||||
|
||||
|
||||
// Testing: temp values
|
||||
dot_texel = texel;// texture2D(dot_texture, vec2 (stprime.y, stprime.x) );
|
||||
detail_texel = texel;
|
||||
mix_texel = texel;
|
||||
grain_texel = texel;
|
||||
gradient_texel = texel;
|
||||
|
||||
// Testing: WS2 code after this
|
||||
|
||||
float local_autumn_factor = texel.a;
|
||||
|
||||
|
||||
|
||||
// we need to fade procedural structures when they get smaller than a single pixel, for this we need
|
||||
// to know under what angle we see the surface
|
||||
|
||||
float view_angle = abs(dot(normalize(normal), normalize(ecViewdir)));
|
||||
float sfactor = sqrt(2.0 * (1.0-steepness)/0.03) + abs(ct)/0.15;
|
||||
|
||||
|
||||
// the snow texel is generated procedurally
|
||||
if (msl_altitude +500.0 > snowlevel)
|
||||
{
|
||||
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.g = snow_texel.g * (0.9 + 0.05 * (noise_10m + noise_5m));
|
||||
snow_texel.a = 1.0;
|
||||
noise_term = 0.1 * (noise_500m-0.5) ;
|
||||
noise_term = noise_term + 0.2 * (snownoise_50m -0.5) * detail_fade(50.0, view_angle, 0.5*dist) ;
|
||||
noise_term = noise_term + 0.2 * (snownoise_25m -0.5) * detail_fade(25.0, view_angle, 0.5*dist) ;
|
||||
noise_term = noise_term + 0.3 * (noise_10m -0.5) * detail_fade(10.0, view_angle, 0.8*dist) ;
|
||||
noise_term = noise_term + 0.3 * (noise_5m - 0.5) * detail_fade(5.0, view_angle, dist);
|
||||
noise_term = noise_term + 0.15 * (noise_2m -0.5) * detail_fade(2.0, view_angle, dist);
|
||||
noise_term = noise_term + 0.08 * (noise_1m -0.5) * detail_fade(1.0, view_angle, 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*(msl_altitude -snowlevel) );
|
||||
}
|
||||
|
||||
// the mixture/gradient texture
|
||||
if (mix_flag == 1) {
|
||||
//mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3); // temp
|
||||
if (mix_texel.a <0.1) {mix_flag = 0;}
|
||||
}
|
||||
|
||||
// the hires overlay texture is loaded with parallax mapping
|
||||
|
||||
if (flag == 1) {
|
||||
stprime = vec2 (0.86*gl_TexCoord[0].s + 0.5*gl_TexCoord[0].t, 0.5*gl_TexCoord[0].s - 0.86*gl_TexCoord[0].t);
|
||||
distortion_factor = 0.97 + 0.06 * noise_500m;
|
||||
stprime = stprime * distortion_factor * 15.0;
|
||||
stprime = stprime + normalize(relPos).xy * 0.022 * (noise_10m + 0.5 * noise_5m +0.25 * noise_2m - 0.875 );
|
||||
|
||||
//detail_texel = texture2D(detail_texture, stprime); // temp
|
||||
if (detail_texel.a <0.1) {flag = 0;}
|
||||
}
|
||||
|
||||
// texture preparation according to detail level
|
||||
|
||||
// mix in hires texture patches
|
||||
|
||||
float dist_fact;
|
||||
float nSum;
|
||||
float mix_factor;
|
||||
|
||||
// first the second texture overlay
|
||||
// transition model 0: random patch overlay without any gradient information
|
||||
// transition model 1: only gradient-driven transitions, no randomness
|
||||
|
||||
|
||||
if (mix_flag == 1)
|
||||
{
|
||||
nSum = 0.167 * (noise_4000m + 2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
|
||||
nSum = mix(nSum, 0.5, max(0.0, 2.0 * (transition_model - 0.5)));
|
||||
nSum = nSum + 0.4 * (1.0 -smoothstep(0.9,0.95, abs(steepness)+ 0.05 * (noise_50m - 0.5))) * min(1.0, 2.0 * transition_model);
|
||||
mix_factor = smoothstep(0.5, 0.54, nSum);
|
||||
texel = mix(texel, mix_texel, mix_factor);
|
||||
local_autumn_factor = texel.a;
|
||||
}
|
||||
|
||||
// then the detail texture overlay
|
||||
|
||||
mix_factor = 0.0;
|
||||
if (dist < 40000.0)
|
||||
{
|
||||
if (flag == 1)
|
||||
{
|
||||
dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist));
|
||||
nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0;
|
||||
nSum = nSum - 0.08 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
|
||||
mix_factor = smoothstep(0.47, 0.54, nSum +hires_overlay_bias- dist_fact);
|
||||
if (mix_factor > 0.8) {mix_factor = 0.8;}
|
||||
texel = mix(texel, detail_texel,mix_factor);
|
||||
}
|
||||
}
|
||||
|
||||
// rock for very steep gradients
|
||||
|
||||
if (gradient_texel.a > 0.0)
|
||||
{
|
||||
texel = mix(texel, gradient_texel, 1.0 - smoothstep(0.75,0.8,abs(steepness)+ 0.00002* msl_altitude + 0.05 * (noise_50m - 0.5)));
|
||||
local_autumn_factor = texel.a;
|
||||
}
|
||||
|
||||
|
||||
// strata noise
|
||||
|
||||
float stratnoise_50m;
|
||||
float stratnoise_10m;
|
||||
|
||||
if (rock_strata==1)
|
||||
{
|
||||
stratnoise_50m = Strata3D(vec3 (rawPos.x, rawPos.y, msl_altitude), 50.0, 0.2);
|
||||
stratnoise_10m = Strata3D(vec3 (rawPos.x, rawPos.y, msl_altitude), 10.0, 0.2);
|
||||
stratnoise_50m = mix(stratnoise_50m, 1.0, smoothstep(0.8,0.9, steepness));
|
||||
stratnoise_10m = mix(stratnoise_10m, 1.0, smoothstep(0.8,0.9, steepness));
|
||||
texel *= (0.4 + 0.4 * stratnoise_50m + 0.2 * stratnoise_10m);
|
||||
}
|
||||
|
||||
// the dot vegetation texture overlay
|
||||
|
||||
texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * (dotnoise_10m + dotnoise_15m) * detail_fade(1.0 * (dot_size * (1.0 +0.1*dot_size)), view_angle,dist));
|
||||
texel.rgb = mix(texel.rgb, dot_texel.rgb, dot_texel.a * dotnoise_2m * detail_fade(0.1 * dot_size, view_angle,dist));
|
||||
|
||||
|
||||
// then the grain texture overlay
|
||||
|
||||
texel.rgb = mix(texel.rgb, grain_texel.rgb, grain_strength * grain_texel.a * (1.0 - mix_factor) * (1.0-smoothstep(2000.0,5000.0, dist)));
|
||||
|
||||
// for really hires, add procedural noise overlay
|
||||
texel.rgb = texel.rgb * (1.0 + 0.4 * (noise_01m-0.5) * detail_fade(0.1, view_angle, dist)) ;
|
||||
|
||||
// autumn colors
|
||||
|
||||
float autumn_factor = season * 2.0 * (1.0 - local_autumn_factor) ;
|
||||
|
||||
|
||||
texel.r = min(1.0, (1.0 + 2.5 * autumn_factor) * texel.r);
|
||||
texel.g = texel.g;
|
||||
texel.b = max(0.0, (1.0 - 4.0 * autumn_factor) * texel.b);
|
||||
|
||||
|
||||
if (local_autumn_factor < 1.0)
|
||||
{
|
||||
intensity = length(texel.rgb) * (1.0 - 0.5 * smoothstep(1.1,2.0,season));
|
||||
texel.rgb = intensity * normalize(mix(texel.rgb, vec3(0.23,0.17,0.08), smoothstep(1.1,2.0, season)));
|
||||
}
|
||||
|
||||
// slope line overlay
|
||||
texel.rgb = texel.rgb * (1.0 - 0.12 * slopenoise_50m - 0.08 * slopenoise_100m);
|
||||
|
||||
//const vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
|
||||
const vec4 dust_color = vec4 (0.76, 0.65, 0.45, 1.0);
|
||||
const vec4 lichen_color = vec4 (0.17, 0.20, 0.06, 1.0);
|
||||
|
||||
// mix vegetation
|
||||
float gradient_factor = smoothstep(0.5, 1.0, steepness);
|
||||
texel = mix(texel, lichen_color, gradient_factor * (0.4 * lichen_cover_factor + 0.8 * lichen_cover_factor * 0.5 * (noise_10m + (1.0 - noise_5m))) );
|
||||
// mix dust
|
||||
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor *dust_resistance + 3.0 * dust_cover_factor * dust_resistance *(((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
|
||||
|
||||
|
||||
// mix snow
|
||||
float snow_mix_factor = 0.0;
|
||||
|
||||
if (msl_altitude +500.0 > snowlevel)
|
||||
{
|
||||
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
|
||||
snow_mix_factor = snow_texel.a* smoothstep(snowlevel, snowlevel+200.0, snow_alpha * msl_altitude+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0);
|
||||
texel = mix(texel, snow_texel, snow_mix_factor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// get distribution of water when terrain is wet
|
||||
|
||||
float combined_wetness = min(1.0, wetness + intrinsic_wetness);
|
||||
float water_threshold1;
|
||||
float water_threshold2;
|
||||
float water_factor =0.0;
|
||||
|
||||
|
||||
if ((dist < 5000.0) && (combined_wetness>0.0))
|
||||
{
|
||||
water_threshold1 = 1.0-0.5* combined_wetness;
|
||||
water_threshold2 = 1.0 - 0.3 * combined_wetness;
|
||||
water_factor = smoothstep(water_threshold1, water_threshold2 , (0.3 * (2.0 * (1.0-noise_10m) + (1.0 -noise_5m)) * (1.0 - smoothstep(2000.0, 5000.0, dist))) - 5.0 * (1.0 -steepness));
|
||||
}
|
||||
|
||||
// darken wet terrain
|
||||
|
||||
texel.rgb = texel.rgb * (1.0 - 0.6 * combined_wetness);
|
||||
|
||||
|
||||
|
||||
// light computations
|
||||
vec4 light_specular = gl_LightSource[0].specular;
|
||||
|
||||
// If gl_Color.a == 0, this is a back-facing polygon and the
|
||||
// normal should be reversed.
|
||||
//n = (2.0 * gl_Color.a - 1.0) * normal;
|
||||
n = normal;//vec3 (nvec.x, nvec.y, sqrt(1.0 -pow(nvec.x,2.0) - pow(nvec.y,2.0) ));
|
||||
n = normalize(n);
|
||||
|
||||
NdotL = dot(n, lightDir);
|
||||
|
||||
noisegrad_10m = (noise_10m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0))/0.05;
|
||||
noisegrad_5m = (noise_5m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),5.0))/0.05;
|
||||
noisegrad_2m = (noise_2m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),2.0))/0.05;
|
||||
noisegrad_1m = (noise_1m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),1.0))/0.05;
|
||||
|
||||
dotnoisegrad_10m = (dotnoise_10m - DotNoise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0 * dot_size,0.5, dot_density))/0.05;
|
||||
|
||||
|
||||
NdotL = NdotL + (noisegrad_10m * detail_fade(10.0, view_angle,dist) + 0.5* noisegrad_5m * detail_fade(5.0, view_angle,dist)) * mix_factor/0.8;
|
||||
NdotL = NdotL + 0.15 * noisegrad_2m * mix_factor/0.8 * detail_fade(2.0,view_angle,dist);
|
||||
NdotL = NdotL + 0.1 * noisegrad_2m * detail_fade(2.0,view_angle,dist);
|
||||
NdotL = NdotL + 0.05 * noisegrad_1m * detail_fade(1.0, view_angle,dist);
|
||||
NdotL = NdotL + (1.0-snow_mix_factor) * 0.3* dot_texel.a * (0.5* dotnoisegrad_10m * detail_fade(1.0 * dot_size, view_angle, dist) +0.5 * dotnoisegrad_10m * noise_01m * detail_fade(0.1, view_angle, dist)) ;
|
||||
|
||||
if (NdotL > 0.0) {
|
||||
float shadowmap = getShadowing();
|
||||
if (cloud_shadow_flag == 1) {NdotL = NdotL * shadow_func(relPos.x, relPos.y, 0.3 * noise_250m + 0.5 * noise_500m+0.2 * noise_1500m, dist);}
|
||||
vec4 diffuse_term = light_diffuse_comp * mat_diffuse;
|
||||
color += diffuse_term * NdotL * shadowmap;
|
||||
NdotHV = max(dot(n, halfVector), 0.0);
|
||||
if (mat_shininess > 0.0)
|
||||
specular.rgb = ((mat_specular.rgb * 0.1 + (water_factor * vec3 (1.0, 1.0, 1.0)))
|
||||
* light_specular.rgb
|
||||
* pow(NdotHV, mat_shininess + (20.0 * water_factor))
|
||||
* shadowmap);
|
||||
}
|
||||
color.a = 1.0;//diffuse_term.a; // as gl_Color.a and light_diffuse.comp.a were packed with other values
|
||||
// This shouldn't be necessary, but our lighting becomes very
|
||||
// saturated. Clamping the color before modulating by the texture
|
||||
// is closer to what the OpenGL fixed function pipeline does.
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
vec3 secondary_light = vec3 (0.0,0.0,0.0);
|
||||
|
||||
if (use_searchlight == 1)
|
||||
{
|
||||
secondary_light += searchlight();
|
||||
}
|
||||
if (use_landing_light == 1)
|
||||
{
|
||||
secondary_light += landing_light(landing_light1_offset, landing_light3_offset);
|
||||
}
|
||||
if (use_alt_landing_light == 1)
|
||||
{
|
||||
secondary_light += landing_light(landing_light2_offset, landing_light3_offset);
|
||||
}
|
||||
color.rgb +=secondary_light * light_distance_fading(dist);
|
||||
|
||||
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
|
||||
|
||||
// here comes the terrain haze model
|
||||
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
|
||||
|
||||
// Rayleigh color shift due to out-scattering
|
||||
float rayleigh_length = 0.5 * avisibility * (2.5 - 1.9 * air_pollution)/alt_factor(eye_alt, eye_alt+relPos.z);
|
||||
float outscatter = 1.0-exp(-dist/rayleigh_length);
|
||||
fragColor.rgb = rayleigh_out_shift(fragColor.rgb,outscatter);
|
||||
|
||||
// Rayleigh color shift due to in-scattering
|
||||
|
||||
float rShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt + 420000.0);
|
||||
//float lightIntensity = length(diffuse_term.rgb)/1.73 * rShade;
|
||||
float lightIntensity = length(hazeColor * effective_scattering) * rShade;
|
||||
vec3 rayleighColor = vec3 (0.17, 0.52, 0.87) * lightIntensity;
|
||||
float rayleighStrength = rayleigh_in_func(dist, air_pollution, avisibility/max(lightIntensity,0.05), eye_alt, eye_alt + relPos.z);
|
||||
fragColor.rgb = mix(fragColor.rgb, rayleighColor,rayleighStrength);
|
||||
|
||||
|
||||
// here comes the terrain haze model
|
||||
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
float dist = length(relPos);
|
||||
|
||||
float mvisibility = min(visibility,avisibility);
|
||||
|
||||
|
@ -323,8 +734,7 @@ void main()
|
|||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
// angle with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
|
||||
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
|
@ -346,22 +756,38 @@ void main()
|
|||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
// blur of the haze layer edge
|
||||
|
||||
float blur_thickness = 50.0;
|
||||
float cphi = dot(vec3(0.0, 1.0, 0.0), relPos)/dist;
|
||||
float ctlayer = delta_z/dist-0.01 + 0.02 * Noise2D(vec2(cphi,1.0),0.1) -0.01;
|
||||
float ctblur = 0.035 ;
|
||||
|
||||
float blur_dist;
|
||||
|
||||
if (abs(delta_z) < 400.0)
|
||||
{
|
||||
blur_dist = dist * (1.0-smoothstep(0.0,300.0,-delta_z)) * smoothstep(-400.0,-200.0, -delta_z);
|
||||
blur_dist = blur_dist * smoothstep(ctlayer-4.0*ctblur, ctlayer-ctblur, ct) * (1.0-smoothstep(ctlayer+0.5*ctblur, ctlayer+ctblur, ct));
|
||||
distance_in_layer = max(distance_in_layer, blur_dist);
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
|
@ -369,44 +795,45 @@ void main()
|
|||
|
||||
float eqColorFactor;
|
||||
|
||||
|
||||
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/visibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -effective_scattering);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -effective_scattering);
|
||||
}
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 - effective_scattering);
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 - effective_scattering);
|
||||
}
|
||||
|
||||
transmission = fog_func(transmission_arg, alt);
|
||||
|
||||
// there's always residual intensity, we should never be driven to zero
|
||||
if (eqColorFactor < 0.2) {eqColorFactor = 0.2;}
|
||||
// there's always residual intensity, we should never be driven to zero
|
||||
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
|
||||
|
||||
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
// Mie-like factor
|
||||
if (lightArg < 10.0)
|
||||
{intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
// Mie-like factor
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
if (lightArg < 10.0)
|
||||
{
|
||||
intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
intensity = length(hazeColor);
|
||||
|
||||
if (intensity > 0.0) // this needs to be a condition, because otherwise hazeColor doesn't come out correctly
|
||||
{
|
||||
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
|
||||
// blue hue of haze
|
||||
|
||||
|
@ -419,25 +846,27 @@ void main()
|
|||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
//intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
float shadow = mix( min(1.0 + dot(n,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
}
|
||||
|
||||
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
// determine the right mix of transmission and haze
|
||||
hazeColor.rgb *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
// finally, mix fog in
|
||||
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
|
@ -446,8 +875,8 @@ transmission = 1.0 - (transmission/1000000.0);
|
|||
}
|
||||
|
||||
|
||||
fragColor.rgb = mix(hazeColor+secondary_light * fog_backscatter(mvisibility) , fragColor.rgb,transmission);
|
||||
|
||||
fragColor.rgb = mix(hazeColor, fragColor.rgb,transmission);
|
||||
}
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
@ -463,5 +892,6 @@ if (remove_haze_and_lighting == 1)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define MODE_DIFFUSE 1
|
||||
#define MODE_AMBIENT_AND_DIFFUSE 2
|
||||
|
||||
attribute vec2 orthophotoTexCoord;
|
||||
//attribute vec2 orthophotoTexCoord;
|
||||
|
||||
// The constant term of the lighting equation that doesn't depend on
|
||||
// the surface normal is passed in gl_{Front,Back}Color. The alpha
|
||||
|
@ -25,13 +25,23 @@ attribute vec2 orthophotoTexCoord;
|
|||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
varying vec3 relPos;
|
||||
varying vec2 orthoTexCoord;
|
||||
varying vec2 rawPos;
|
||||
varying vec3 worldPos;
|
||||
varying vec3 ecViewdir;
|
||||
varying vec2 grad_dir;
|
||||
//varying vec2 orthoTexCoord;
|
||||
varying vec4 ecPosition;
|
||||
|
||||
varying float yprime_alt;
|
||||
// Sent packed into alpha channels
|
||||
//varying float yprime_alt;
|
||||
varying float mie_angle;
|
||||
|
||||
varying float steepness;
|
||||
|
||||
uniform int colorMode;
|
||||
|
||||
uniform bool raise_vertex;
|
||||
|
||||
uniform float hazeLayerAltitude;
|
||||
uniform float terminator;
|
||||
uniform float terrain_alt;
|
||||
|
@ -39,8 +49,18 @@ uniform float avisibility;
|
|||
uniform float visibility;
|
||||
uniform float overcast;
|
||||
uniform float ground_scattering;
|
||||
uniform float eye_alt;
|
||||
uniform float moonlight;
|
||||
|
||||
uniform bool use_IR_vision;
|
||||
|
||||
uniform mat4 osg_ViewMatrixInverse;
|
||||
|
||||
float earthShade;
|
||||
float yprime_alt;
|
||||
|
||||
vec3 moonlight_perception (in vec3 light);
|
||||
|
||||
void setupShadows(vec4 eyeSpacePos);
|
||||
|
||||
// This is the value used in the skydome scattering shader - use the same here for consistency?
|
||||
|
@ -48,7 +68,7 @@ const float EarthRadius = 5800000.0;
|
|||
const float terminator_width = 200000.0;
|
||||
|
||||
|
||||
float earthShade;
|
||||
|
||||
|
||||
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
|
||||
{
|
||||
|
@ -67,7 +87,9 @@ void main()
|
|||
vec4 light_diffuse;
|
||||
vec4 light_ambient;
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight;
|
||||
vec3 moonLightColor = vec3 (0.095, 0.095, 0.15) * moonlight + vec3 (0.005, 0.005, 0.005);
|
||||
|
||||
moonLightColor = moonlight_perception (moonLightColor);
|
||||
|
||||
|
||||
//float yprime_alt;
|
||||
|
@ -77,12 +99,28 @@ void main()
|
|||
float vertex_alt;
|
||||
float scattering;
|
||||
|
||||
rawPos = gl_Vertex.xy;
|
||||
worldPos = (osg_ViewMatrixInverse *gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
|
||||
|
||||
steepness = dot(normalize(gl_Normal), vec3 (0.0, 0.0, 1.0));
|
||||
grad_dir = normalize(gl_Normal.xy);
|
||||
|
||||
vec4 pos = gl_Vertex;
|
||||
if (raise_vertex)
|
||||
{
|
||||
pos.z+=0.1;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * pos;
|
||||
}
|
||||
else gl_Position = ftransform();
|
||||
|
||||
|
||||
// this code is copied from default.vert
|
||||
|
||||
ecPosition = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_Position = ftransform();
|
||||
//gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||
orthoTexCoord = orthophotoTexCoord;
|
||||
//orthoTexCoord = orthophotoTexCoord;
|
||||
normal = gl_NormalMatrix * gl_Normal;
|
||||
|
||||
// here start computations for the haze layer
|
||||
|
@ -93,7 +131,8 @@ void main()
|
|||
|
||||
// and relative position to vector
|
||||
relPos = gl_Vertex.xyz - 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);
|
||||
|
@ -144,10 +183,11 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
|
|||
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_ambient.b = light_ambient.r * 0.5/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;
|
||||
|
||||
|
||||
|
@ -156,13 +196,11 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
|
|||
// correct ambient light intensity and hue before sunrise
|
||||
if (earthShade < 0.5)
|
||||
{
|
||||
//light_ambient = light_ambient * (0.7 + 0.3 * smoothstep(0.2, 0.5, earthShade));
|
||||
intensity = length(light_ambient.xyz);
|
||||
|
||||
intensity = length(light_ambient.rgb);
|
||||
light_ambient.rgb = intensity * normalize(mix(light_ambient.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.8,earthShade) ));
|
||||
light_ambient.rgb = light_ambient.rgb + moonLightColor * (1.0 - smoothstep(0.4, 0.5, earthShade));
|
||||
|
||||
intensity = length(light_diffuse.xyz);
|
||||
intensity = length(light_diffuse.rgb);
|
||||
light_diffuse.rgb = intensity * normalize(mix(light_diffuse.rgb, shadedFogColor, 1.0 -smoothstep(0.4, 0.7,earthShade) ));
|
||||
}
|
||||
|
||||
|
@ -195,8 +233,8 @@ else // the faster, full-day version without lightfields
|
|||
mie_angle = 1.0;
|
||||
|
||||
if (terminator > 3000000.0)
|
||||
{light_diffuse = vec4 (1.0, 1.0, 1.0, 0.0);
|
||||
light_ambient = vec4 (0.33, 0.4, 0.5, 0.0); }
|
||||
{light_diffuse = vec4 (1.0, 1.0, 1.0, 1.0);
|
||||
light_ambient = vec4 (0.33, 0.4, 0.5, 1.0); }
|
||||
else
|
||||
{
|
||||
|
||||
|
@ -206,6 +244,8 @@ else // the faster, full-day version without lightfields
|
|||
light_diffuse.r = 0.904 + lightArg * 0.092;
|
||||
light_diffuse.a = 1.0;
|
||||
|
||||
//light_ambient.b = 0.41 + lightArg * 0.08;
|
||||
//light_ambient.g = 0.333 + lightArg * 0.06;
|
||||
light_ambient.r = 0.316 + lightArg * 0.016;
|
||||
light_ambient.g = light_ambient.r * 0.4/0.33;
|
||||
light_ambient.b = light_ambient.r * 0.5/0.33;
|
||||
|
@ -217,14 +257,40 @@ else // the faster, full-day version without lightfields
|
|||
}
|
||||
|
||||
|
||||
// a sky/earth irradiation map model - the sky creates much more diffuse radiation than the ground, so
|
||||
// steep faces end up shaded more
|
||||
|
||||
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
|
||||
|
||||
float shade_depth = 1.0 * smoothstep (0.6,0.95,ground_scattering) * (1.0-smoothstep(0.1,0.5,overcast)) * smoothstep(0.4,1.5,earthShade);
|
||||
|
||||
light_ambient.rgb = light_ambient.rgb * (1.0 - shade_depth);
|
||||
light_diffuse.rgb = light_diffuse.rgb * (1.0 + 1.2 * shade_depth);
|
||||
|
||||
if (use_IR_vision)
|
||||
{
|
||||
light_ambient.rgb = max(light_ambient.rgb, vec3 (0.5, 0.5, 0.5));
|
||||
}
|
||||
|
||||
|
||||
// default lighting based on texture and material using the light we have just computed
|
||||
|
||||
light_diffuse_comp = light_diffuse;
|
||||
vec4 constant_term = (gl_LightModel.ambient + light_ambient);
|
||||
// Another hack for supporting two-sided lighting without using
|
||||
// gl_FrontFacing in the fragment shader.
|
||||
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
|
||||
gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
|
||||
//Testing phase code: ambient colours are not sent to fragement shader yet.
|
||||
// They are all default except for water/ocean etc. currently
|
||||
// Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0)
|
||||
//To do: Fix this once ambient colour becomes available in the fragment shaders.
|
||||
//const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
|
||||
const vec4 ambient_color = vec4(1.0);
|
||||
vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient);
|
||||
|
||||
light_diffuse_comp.a = yprime_alt;
|
||||
gl_FrontColor.rgb = constant_term.rgb; // gl_FrontColor.a = 1.0;
|
||||
gl_BackColor.rgb = constant_term.rgb; // gl_BackColor.a = 0.0;
|
||||
gl_FrontColor.a = mie_angle;
|
||||
gl_BackColor.a = mie_angle;
|
||||
|
||||
setupShadows(ecPosition);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,42 @@
|
|||
// -*-C++-*-
|
||||
#version 130
|
||||
#extension GL_EXT_texture_array : enable
|
||||
|
||||
// written by Thorsten Renk, Oct 2011, based on default.frag
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// TEST PHASE TOGGLES AND CONTROLS
|
||||
//
|
||||
|
||||
// Development tools:
|
||||
// Reduce haze to almost zero, while preserving lighting. Useful for observing distant tiles.
|
||||
// Keeps the calculation overhead. This can be used for profiling.
|
||||
// Possible values: 0:Normal, 1:Reduced haze.
|
||||
const int reduce_haze_without_removing_calculation_overhead = 0;
|
||||
|
||||
// Remove haze and lighting and shows just the texture.
|
||||
// Useful for checking texture rendering and scenery.
|
||||
// The compiler will likely optimise out the haze and lighting calculations.
|
||||
// Possible values: 0:Normal, 1:Just the texture.
|
||||
const int remove_haze_and_lighting = 0;
|
||||
|
||||
//
|
||||
// End of test phase controls
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Ambient term comes in gl_Color.rgb.
|
||||
varying vec4 light_diffuse_comp;
|
||||
varying vec3 normal;
|
||||
|
@ -46,279 +80,390 @@ float fog_func (in float targ, in float alt);
|
|||
vec3 get_hazeColor(in float light_arg);
|
||||
vec3 filter_combined (in vec3 color) ;
|
||||
|
||||
float shadow_func (in float x, in float y, in float noise, in float dist);
|
||||
float DotNoise2D(in vec2 coord, in float wavelength, in float fractionalMaxDotSize, in float dot_density);
|
||||
float Noise2D(in vec2 coord, in float wavelength);
|
||||
float Noise3D(in vec3 coord, in float wavelength);
|
||||
float SlopeLines2D(in vec2 coord, in vec2 gradDir, in float wavelength, in float steepness);
|
||||
float Strata3D(in vec3 coord, in float wavelength, in float variation);
|
||||
float fog_func (in float targ, in float alt);
|
||||
float rayleigh_in_func(in float dist, in float air_pollution, in float avisibility, in float eye_alt, in float vertex_alt);
|
||||
float alt_factor(in float eye_alt, in float vertex_alt);
|
||||
float light_distance_fading(in float dist);
|
||||
float fog_backscatter(in float avisibility);
|
||||
|
||||
vec3 rayleigh_out_shift(in vec3 color, in float outscatter);
|
||||
vec3 get_hazeColor(in float light_arg);
|
||||
vec3 searchlight();
|
||||
vec3 landing_light(in float offset, in float offsetv);
|
||||
vec3 filter_combined (in vec3 color) ;
|
||||
|
||||
float getShadowing();
|
||||
vec3 getClusteredLightsContribution(vec3 p, vec3 n, vec3 texel);
|
||||
|
||||
// Not used
|
||||
float luminance(vec3 color)
|
||||
{
|
||||
return dot(vec3(0.212671, 0.715160, 0.072169), color);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////
|
||||
// Test-phase code:
|
||||
|
||||
|
||||
// These should be sent as uniforms
|
||||
|
||||
// Tile dimensions in meters
|
||||
// vec2 tile_size = vec2(tile_width , tile_height);
|
||||
// Testing: texture coords are sent flipped right now:
|
||||
|
||||
// Note tile_size is defined in the shader include: ws30-landclass-search-functions.frag.
|
||||
// vec2 tile_size = vec2(tile_height , tile_width);
|
||||
|
||||
// From noise.frag
|
||||
float rand2D(in vec2 co);
|
||||
|
||||
// Create random landclasses without a texture lookup to stress test
|
||||
// Each square of square_size in m is assigned a random landclass value
|
||||
int get_random_landclass(in vec2 co)
|
||||
{
|
||||
float square_size = 200.0;
|
||||
//float r = rand2D( floor(vec2(co.s*tile_width, co.t*tile_height)/square_size) );
|
||||
float r = rand2D( floor(vec2(co.s*tile_height, co.t*tile_width)/square_size) );
|
||||
int lc = int(r*48.0); // only 48 landclasses mapped so far
|
||||
return lc;
|
||||
}
|
||||
// These functions, and other function they depend on, are defined
|
||||
// in ws30-ALS-landclass-search.frag.
|
||||
|
||||
|
||||
// Create random landclasses without a texture lookup to stress test.
|
||||
// Each square of square_size in m is assigned a random landclass value.
|
||||
int get_random_landclass(in vec2 co, in vec2 tile_size);
|
||||
|
||||
|
||||
// Lookup a ground texture at a point based on the landclass at that point, without visible
|
||||
// seams at coordinate discontinuities or at landclass boundaries where texture are switched.
|
||||
// The partial derivatives of the tile_coord at the fragment is needed to adjust for
|
||||
// the stretching of different textures, so that the correct mip-map level is looked
|
||||
// up and there are no seams.
|
||||
|
||||
vec4 lookup_ground_texture_array(in float index, in vec2 tile_coord, in int landclass_id,
|
||||
in vec2 dx, in vec2 dy);
|
||||
|
||||
|
||||
// Look up the landclass id [0 .. 255] for this particular fragment.
|
||||
// Lookup id of any neighbouring landclass that is within the search distance.
|
||||
// Searches are performed in upto 4 directions right now, but only one landclass is looked up
|
||||
// Create a mix factor werighting the influences of nearby landclasses
|
||||
void get_landclass_id(in vec2 tile_coord,
|
||||
const in float landclass_texel_size_m, in vec2 dx, in vec2 dy,
|
||||
out int landclass_id, out ivec4 neighbor_landclass_ids,
|
||||
out int num_unique_neighbors,out vec4 mix_factor
|
||||
);
|
||||
|
||||
|
||||
float Noise2D(in vec2 coord, in float wavelength);
|
||||
// End Test-phase code
|
||||
////////////////////////
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
// this is taken from default.frag
|
||||
vec3 n;
|
||||
float NdotL, NdotHV, fogFactor;
|
||||
vec3 lightDir = gl_LightSource[0].position.xyz;
|
||||
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
|
||||
vec4 texel;
|
||||
vec4 fragColor;
|
||||
vec4 specular = vec4(0.0);
|
||||
float intensity;
|
||||
|
||||
|
||||
vec3 shadedFogColor = vec3(0.55, 0.67, 0.88);
|
||||
// this is taken from default.frag
|
||||
vec3 n;
|
||||
float NdotL, NdotHV, fogFactor;
|
||||
vec3 lightDir = gl_LightSource[0].position.xyz;
|
||||
vec3 halfVector = gl_LightSource[0].halfVector.xyz;
|
||||
vec4 texel;
|
||||
vec4 fragColor;
|
||||
vec4 specular = vec4(0.0);
|
||||
float intensity;
|
||||
|
||||
|
||||
|
||||
// Oct 2021:
|
||||
// Geometry is in the form of roughly rectangular 'tiles'
|
||||
// with a mesh forming a grid with regular spacing.
|
||||
// Each vertex in the mesh is given an elevation
|
||||
// Oct 27 2021:
|
||||
// Geometry is in the form of roughly rectangular 'tiles'
|
||||
// with a mesh forming a grid with regular spacing.
|
||||
// Each vertex in the mesh is given an elevation
|
||||
|
||||
// Tile dimensions in m
|
||||
vec2 tile_size = vec2(tile_width , tile_height);
|
||||
// Temp: sizes are the wrong way around currently
|
||||
tile_size.xy =tile_size.yx;
|
||||
// Tile dimensions in m
|
||||
// Testing: created from two float uniforms in global scope. Should be sent as a vec2
|
||||
// vec2 tile_size
|
||||
|
||||
// Tile texture coordinates range [0..1] over the tile 'rectangle'
|
||||
vec2 tile_coord = gl_TexCoord[0].st;
|
||||
// Tile texture coordinates range [0..1] over the tile 'rectangle'
|
||||
vec2 tile_coord = gl_TexCoord[0].st;
|
||||
|
||||
// Look up the landclass id [0 .. 255] for this particular fragment
|
||||
// Each tile has 1 texture containing landclass ids stetched over it
|
||||
// Test phase: Constants and toggles for transitions between landlcasses are defined at
|
||||
// the top of this file.
|
||||
|
||||
// Testing. Landclass sources: texture or random
|
||||
int tlc = int(texture2D(landclass, tile_coord.st).g * 255.0 + 0.5);
|
||||
//int rlc = get_random_landclass(tile_coord.st);
|
||||
int lc = tlc;
|
||||
// Look up the landclass id [0 .. 255] for this particular fragment
|
||||
// and any neighbouring landclass that is close.
|
||||
// Each tile has 1 texture containing landclass ids stetched over it.
|
||||
|
||||
// The landclass id is used to index into arrays containing
|
||||
// material parameters and textures for the landclass as
|
||||
// defined in the regional definitions
|
||||
float index = float(lc)/512.0;
|
||||
// Landclass for current fragment, and up-to 4 neighboring landclasses - 2 used currently
|
||||
int lc;
|
||||
ivec4 lc_n;
|
||||
|
||||
float mat_shininess = texture(dimensionsArray, index).z;
|
||||
vec4 mat_diffuse = texture(diffuseArray, index);
|
||||
vec4 mat_specular = texture(specularArray, index);
|
||||
int num_unique_neighbors = 0;
|
||||
|
||||
vec4 color = gl_Color;
|
||||
|
||||
// Testing code:
|
||||
// Use rlc even when looking up textures to recreate the extra performance hit
|
||||
// so any performance difference between the two is due to the texture lookup
|
||||
// color = color+0.00001*float(rlc);
|
||||
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
|
||||
vec4 light_specular = gl_LightSource[0].specular;
|
||||
|
||||
// If gl_Color.a == 0, this is a back-facing polygon and the
|
||||
// normal should be reversed.
|
||||
//n = (2.0 * gl_Color.a - 1.0) * normal;
|
||||
n = normalize(normal);
|
||||
// Mix factor of base textures for 2 neighbour landclass(es)
|
||||
vec4 mfact;
|
||||
|
||||
|
||||
NdotL = dot(n, lightDir);
|
||||
if (NdotL > 0.0) {
|
||||
float shadowmap = getShadowing();
|
||||
color += (light_diffuse_comp * mat_diffuse) * NdotL * shadowmap;
|
||||
NdotHV = max(dot(n, halfVector), 0.0);
|
||||
if (mat_shininess > 0.0)
|
||||
specular.rgb = (mat_specular.rgb
|
||||
* light_specular.rgb
|
||||
* pow(NdotHV, gl_FrontMaterial.shininess)
|
||||
* shadowmap);
|
||||
const float landclass_texel_size_m = 25.0;
|
||||
|
||||
// Partial derivatives of s and t for this fragment,
|
||||
// with respect to window (screen space) x and y axes.
|
||||
// Used to pick mipmap LoD levels, and turn off unneeded procedural detail
|
||||
vec2 dx = dFdx(tile_coord);
|
||||
vec2 dy = dFdy(tile_coord);
|
||||
|
||||
get_landclass_id(tile_coord, landclass_texel_size_m, dx, dy,
|
||||
lc, lc_n, num_unique_neighbors, mfact);
|
||||
|
||||
// The landclass id is used to index into arrays containing
|
||||
// material parameters and textures for the landclass as
|
||||
// defined in the regional definitions
|
||||
float index = float(lc)/512.0;
|
||||
vec4 index_n = vec4(lc_n)/512.0;
|
||||
|
||||
float mat_shininess = texture(dimensionsArray, index).z;
|
||||
vec4 mat_diffuse = texture(diffuseArray, index);
|
||||
vec4 mat_specular = texture(specularArray, index);
|
||||
|
||||
vec4 color = gl_Color;
|
||||
|
||||
// Testing code:
|
||||
// Use rlc even when looking up textures to recreate the extra performance hit
|
||||
// so any performance difference between the two is due to the texture lookup
|
||||
// color = color+0.00001*float(get_random_landclass(tile_coord.st, tile_size));
|
||||
|
||||
float effective_scattering = min(scattering, cloud_self_shading);
|
||||
|
||||
vec4 light_specular = gl_LightSource[0].specular;
|
||||
|
||||
// If gl_Color.a == 0, this is a back-facing polygon and the
|
||||
// normal should be reversed.
|
||||
//n = (2.0 * gl_Color.a - 1.0) * normal;
|
||||
n = normalize(normal);
|
||||
|
||||
|
||||
NdotL = dot(n, lightDir);
|
||||
vec4 diffuse_term = light_diffuse_comp * mat_diffuse;
|
||||
if (NdotL > 0.0) {
|
||||
float shadowmap = getShadowing();
|
||||
vec4 diffuse_term = light_diffuse_comp * mat_diffuse;
|
||||
color += diffuse_term * NdotL * shadowmap;
|
||||
NdotHV = max(dot(n, halfVector), 0.0);
|
||||
if (mat_shininess > 0.0)
|
||||
specular.rgb = (mat_specular.rgb
|
||||
* light_specular.rgb
|
||||
* pow(NdotHV, gl_FrontMaterial.shininess)
|
||||
* shadowmap);
|
||||
}
|
||||
color.a = diffuse_term.a;
|
||||
// This shouldn't be necessary, but our lighting becomes very
|
||||
// saturated. Clamping the color before modulating by the texture
|
||||
// is closer to what the OpenGL fixed function pipeline does.
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
|
||||
// Look up ground textures by indexing into the texture array.
|
||||
// Different textures are stretched along the ground to different
|
||||
// lengths along each axes as set by <xsize> and <ysize>
|
||||
// regional definitions parameters
|
||||
|
||||
// Look up texture coordinates and scale of ground textures
|
||||
|
||||
// Landclass for this fragment
|
||||
|
||||
texel = lookup_ground_texture_array(index, 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(index_n[0], 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(index_n[1], tile_coord, lc_n[1],
|
||||
dx, dy);
|
||||
|
||||
|
||||
texel_nc = mix(texel_closest, texel_2nd_closest, mfact[1]);
|
||||
}
|
||||
|
||||
texel = mix(texel, texel_nc, mfact[0]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Testing code: mix with green to show values of variables at each point
|
||||
//vec4 green = vec4(0.0, 0.5, 0.0, 0.0);
|
||||
//texel = mix(texel, green, (mfact[2]));
|
||||
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
|
||||
|
||||
// here comes the terrain haze model
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
float dist = length(relPos);
|
||||
|
||||
float mvisibility = min(visibility,avisibility);
|
||||
|
||||
if (dist > 0.04 * mvisibility)
|
||||
{
|
||||
|
||||
alt = eye_alt;
|
||||
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
// angle with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
if (delta_z > 0.0) // we're inside the layer
|
||||
{
|
||||
if (ct < 0.0) // we look down
|
||||
{
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,mvisibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
color.a = light_diffuse_comp.a;
|
||||
// This shouldn't be necessary, but our lighting becomes very
|
||||
// saturated. Clamping the color before modulating by the texture
|
||||
// is closer to what the OpenGL fixed function pipeline does.
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
else // we may look through upper layer edge
|
||||
{
|
||||
H = dist * ct;
|
||||
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
|
||||
else {distance_in_layer = dist;}
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
|
||||
// Look up ground textures by indexing into the texture array.
|
||||
// Different textures are stretched along the ground to different
|
||||
// lengths along each axes as set by <xsize> and <ysize>
|
||||
// regional definitions parameters
|
||||
|
||||
// Look up stretching dimensions of textures in m - scaled to fit in [0..1], so rescale
|
||||
vec2 g_texture_stretch_dim = 10000.0 * texture(dimensionsArray, index).st;
|
||||
|
||||
vec2 g_texture_scale = tile_size.xy / g_texture_stretch_dim.xy;
|
||||
// Ground texture coords
|
||||
vec2 st = g_texture_scale * tile_coord.st;
|
||||
|
||||
// Rotate texture using the perlin texture as a mask to reduce tiling
|
||||
float pnoise1 = texture(perlin, st / 8.0).r;
|
||||
float pnoise2 = texture(perlin, - st / 16.0).r;
|
||||
|
||||
//Testing: Non texture alternative
|
||||
//float pnoise1 = Noise2D(st, 8.0);
|
||||
//float pnoise2 = Noise2D(-st, 16.0);
|
||||
|
||||
if (pnoise1 >= 0.5) st = g_texture_scale.st * tile_coord.ts;
|
||||
if (pnoise2 >= 0.5) st = -st;
|
||||
|
||||
texel = texture(textureArray, vec3(st, lc));
|
||||
|
||||
fragColor = color * texel + specular;
|
||||
fragColor.rgb += getClusteredLightsContribution(ecPosition.xyz, n, texel.rgb);
|
||||
|
||||
// here comes the terrain haze model
|
||||
float delta_z = hazeLayerAltitude - eye_alt;
|
||||
float dist = length(relPos);
|
||||
|
||||
float mvisibility = min(visibility,avisibility);
|
||||
|
||||
if (dist > 0.04 * mvisibility)
|
||||
{
|
||||
|
||||
alt = eye_alt;
|
||||
|
||||
float transmission;
|
||||
float vAltitude;
|
||||
float delta_zv;
|
||||
float H;
|
||||
float distance_in_layer;
|
||||
float transmission_arg;
|
||||
|
||||
// angle with horizon
|
||||
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
|
||||
|
||||
|
||||
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
|
||||
if (delta_z > 0.0) // we're inside the layer
|
||||
{
|
||||
if (ct < 0.0) // we look down
|
||||
{
|
||||
distance_in_layer = dist;
|
||||
vAltitude = min(distance_in_layer,mvisibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
else // we may look through upper layer edge
|
||||
{
|
||||
H = dist * ct;
|
||||
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
|
||||
else {distance_in_layer = dist;}
|
||||
vAltitude = min(distance_in_layer,visibility) * ct;
|
||||
delta_zv = delta_z - vAltitude;
|
||||
}
|
||||
}
|
||||
else // we see the layer from above, delta_z < 0.0
|
||||
{
|
||||
H = dist * -ct;
|
||||
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
|
||||
{
|
||||
distance_in_layer = 0.0;
|
||||
delta_zv = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vAltitude = H + delta_z;
|
||||
distance_in_layer = vAltitude/H * dist;
|
||||
vAltitude = min(distance_in_layer,visibility) * (-ct);
|
||||
delta_zv = vAltitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ground haze cannot be thinner than aloft visibility in the model,
|
||||
// so we need to use aloft visibility otherwise
|
||||
transmission_arg = (dist-distance_in_layer)/avisibility;
|
||||
|
||||
float eqColorFactor;
|
||||
float eqColorFactor;
|
||||
|
||||
|
||||
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/visibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -effective_scattering);
|
||||
if (visibility < avisibility)
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/visibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -effective_scattering);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -effective_scattering);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
|
||||
// this combines the Weber-Fechner intensity
|
||||
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -effective_scattering);
|
||||
}
|
||||
|
||||
transmission = fog_func(transmission_arg, alt);
|
||||
transmission = fog_func(transmission_arg, alt);
|
||||
|
||||
// there's always residual intensity, we should never be driven to zero
|
||||
if (eqColorFactor < 0.2) {eqColorFactor = 0.2;}
|
||||
// there's always residual intensity, we should never be driven to zero
|
||||
if (eqColorFactor < 0.2) {eqColorFactor = 0.2;}
|
||||
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
float lightArg = (terminator-yprime_alt)/100000.0;
|
||||
vec3 hazeColor = get_hazeColor(lightArg);
|
||||
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
// now dim the light for haze
|
||||
eShade = 1.0 - 0.9 * smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt);
|
||||
|
||||
// Mie-like factor
|
||||
if (lightArg < 10.0)
|
||||
{intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
// Mie-like factor
|
||||
if (lightArg < 10.0)
|
||||
{intensity = length(hazeColor);
|
||||
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
|
||||
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
|
||||
}
|
||||
|
||||
// high altitude desaturation of the haze color
|
||||
// high altitude desaturation of the haze color
|
||||
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
|
||||
|
||||
// blue hue of haze
|
||||
// blue hue of haze
|
||||
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
hazeColor.x = hazeColor.x * 0.83;
|
||||
hazeColor.y = hazeColor.y * 0.9;
|
||||
|
||||
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
// additional blue in indirect light
|
||||
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
|
||||
intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, 1.5* shadedFogColor, 1.0 -smoothstep(0.25, fade_out,eShade) ));
|
||||
|
||||
// change haze color to blue hue for strong fogging
|
||||
//intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
// change haze color to blue hue for strong fogging
|
||||
//intensity = length(hazeColor);
|
||||
hazeColor = intensity * normalize(mix(hazeColor, shadedFogColor, (1.0-smoothstep(0.5,0.9,eqColorFactor))));
|
||||
|
||||
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
// reduce haze intensity when looking at shaded surfaces, only in terminator region
|
||||
|
||||
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
|
||||
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
|
||||
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
// don't let the light fade out too rapidly
|
||||
lightArg = (terminator + 200000.0)/100000.0;
|
||||
float minLightIntensity = min(0.2,0.16 * lightArg + 0.5);
|
||||
vec3 minLight = minLightIntensity * vec3 (0.2, 0.3, 0.4);
|
||||
hazeColor *= eqColorFactor * eShade;
|
||||
hazeColor.rgb = max(hazeColor.rgb, minLight.rgb);
|
||||
|
||||
// determine the right mix of transmission and haze
|
||||
// determine the right mix of transmission and haze
|
||||
|
||||
fragColor.rgb = mix(hazeColor, fragColor.rgb,transmission);
|
||||
}
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
// Testing phase controls
|
||||
if (reduce_haze_without_removing_calculation_overhead == 1)
|
||||
{
|
||||
transmission = 1.0 - (transmission/1000000.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
fragColor.rgb = mix(hazeColor, fragColor.rgb,transmission);
|
||||
}
|
||||
|
||||
fragColor.rgb = filter_combined(fragColor.rgb);
|
||||
|
||||
gl_FragColor = fragColor;
|
||||
|
||||
|
||||
|
||||
// Testing phase controls:
|
||||
if (remove_haze_and_lighting == 1)
|
||||
{
|
||||
gl_FragColor = texel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -220,7 +220,13 @@ else // the faster, full-day version without lightfields
|
|||
// default lighting based on texture and material using the light we have just computed
|
||||
|
||||
light_diffuse_comp = light_diffuse;
|
||||
vec4 constant_term = (gl_LightModel.ambient + light_ambient);
|
||||
//Testing phase code: ambient colours are not sent to fragement shader yet.
|
||||
// They are all default except for water/ocean etc. currently
|
||||
// Emission is all set to the default of vec4(0.0, 0.0, 0.0, 1.0)
|
||||
//To do: Fix this once ambient colour becomes available in the fragment shaders.
|
||||
//const vec4 ambient_color = vec4(0.2, 0.2, 0.2, 1.0);
|
||||
const vec4 ambient_color = vec4(1.0);
|
||||
vec4 constant_term = ambient_color * (gl_LightModel.ambient + light_ambient);
|
||||
// Another hack for supporting two-sided lighting without using
|
||||
// gl_FrontFacing in the fragment shader.
|
||||
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
|
||||
|
|
Loading…
Reference in a new issue