1
0
Fork 0
fgdata/Shaders/grass-ALS.frag
Fernando García Liñán a3a8f9123e Make Compositor default
- Remove all Compositor Effects and Shaders.
- Unify the low-spec and ALS pipelines in a single pipeline called 'Classic'.
- Readd shadow mapping.
- Move the WS30 Effect and fragment shader out of the Compositor-specific directories.
2020-11-16 13:46:30 +01:00

175 lines
5.6 KiB
C++

// -*-C++-*-
#version 120
#define BLADE_FRACTION 0.1
#define MAX_LAYERS 20
#define MAX_DISTANCE 1000.0
uniform float visibility;
uniform float scattering;
uniform float overlay_bias;
uniform float season;
uniform float max_height;
uniform float grass_density;
uniform float grass_modulate_height_min;
uniform float wind_x;
uniform float wind_y;
uniform float wash_x;
uniform float wash_y;
uniform float wash_strength;
uniform int grass_modulate_by_overlay;
uniform int grass_groups;
uniform int wind_effects;
uniform sampler2D colorTex;
uniform sampler2D densityTex;
uniform float osg_SimulationTime;
varying vec2 g_rawpos; // Horizontal position in model space
varying float g_distance_to_eye; // Distance to the camera. Layers were disregarded
varying float g_layer; // The layer where the fragment lives (0-1 range)
float rand2D(in vec2 co);
float Noise2D(in vec2 co, in float wavelength);
vec3 filter_combined (in vec3 color) ;
float getShadowing();
float map(float s, float a1, float a2, float b1, float b2)
{
return b1+(s-a1)*(b2-b1)/(a2-a1);
}
float decodeBinary(float n, float layer)
{
return float(mod(floor(n*pow(0.5, layer)), 2.0));
}
float bladeNoise2D(in float x, in float y, in float dDensity, in float layer, in float d_factor, in float h_factor)
{
float integer_x = x - fract(x);
float fractional_x = x - integer_x;
float integer_y = y - fract(y);
float fractional_y = y - integer_y;
if (rand2D(vec2(integer_x+1.0, integer_y +1.0)) > dDensity)
{return 0.0;}
float hfact = 0.7 + 0.3 * (rand2D(vec2(integer_x, integer_y + 2.0)));
hfact *= h_factor;
if (layer > hfact) {return 0.0;}
float xoffset = (rand2D(vec2(integer_x, integer_y)) -0.5);
float yoffset = (rand2D(vec2(integer_x+1.0, integer_y)) - 0.5);
float xbend = (rand2D(vec2(integer_x+1.0, integer_y + 1.0)) - 0.5);
float ybend = (rand2D(vec2(integer_x, integer_y + 1.0)) - 0.5);
float fraction = BLADE_FRACTION * (0.5 + 0.5 * (1.0 - smoothstep(0.5, 1.0, layer)));
float bend = 0.5 * layer * layer;
vec2 truePos = vec2 (0.5 + xoffset * (1.0 - 2.0 * BLADE_FRACTION) + xbend * bend, 0.5 + yoffset * (1.0 -2.0 * BLADE_FRACTION) + ybend * bend);
float distance = length(truePos - vec2(fractional_x, fractional_y));
return 1.0 - step (fraction * d_factor, distance);
}
float BladeNoise2D(in vec2 coord, in float wavelength, in float dDensity, in float layer, in float d_factor, in float h_factor)
{
return bladeNoise2D(coord.x/wavelength, coord.y/wavelength, dDensity, layer, d_factor, h_factor);
}
void main()
{
if (season > 1.6) {discard;}
if (g_distance_to_eye > MAX_DISTANCE) {discard;}
vec2 texCoord = gl_TexCoord[0].st;
if (wind_effects > 1)
{
vec2 eyePos = (gl_ModelViewMatrixInverse * vec4 (0.0, 0.0, 0.0, 1.0)).xy;
vec2 washDir = vec2 (wash_x, wash_y) - (g_rawpos - eyePos);
float washStrength = 20.0 * min(14.0 * wash_strength/(length(washDir) + 1.0), 1.0);
washStrength *= (1.0 - 0.8 * sin(20.0 * osg_SimulationTime + length(washDir) + dot(normalize(washDir), vec2(1.0, 0.0))));
vec2 windDir = normalize(vec2 (max(wind_x, 0.1), wind_y) + washStrength * vec2 (-washDir.y, washDir.x));
float windStrength = 0.5 * length(vec2 (wind_x, wind_y)) + washStrength;
float windAmplitude = 1.0 + 0.3 * windStrength;
float sineTerm = sin(0.7 * windStrength * osg_SimulationTime + 0.05 * (g_rawpos.x + g_rawpos.y));
sineTerm = sineTerm + sin(0.6 * windStrength * osg_SimulationTime + 0.04 * (g_rawpos.x + g_rawpos.y));
sineTerm = sineTerm + sin(0.44 * windStrength * osg_SimulationTime + 0.05 * (g_rawpos.x + g_rawpos.y));
sineTerm = sineTerm/3.0;
sineTerm = 5.0 * sineTerm * sineTerm;
float windDisplacement = pow(g_layer/32.0, 2.0) * clamp((windStrength + windAmplitude * sineTerm), -35.0, 35.0);
texCoord += (windDisplacement * windDir);
}
float noise_1m = Noise2D(g_rawpos.xy, 1.0);
float noise_2m = Noise2D(g_rawpos.xy, 2.0); ;
float noise_10m = Noise2D(g_rawpos.xy, 10.0);
float h_factor;
float overlay_mix = smoothstep(0.45, 0.65, overlay_bias + (0.5 * noise_1m + 0.1 * noise_2m + 0.4 * noise_10m));
if (grass_modulate_by_overlay == 1)
{h_factor = grass_modulate_height_min + (1.0 - grass_modulate_height_min) * (1.0 - overlay_mix) ;}
else
{h_factor = 1.0;}
float value = 0.0;
float d_fade =smoothstep(100.0, MAX_DISTANCE, g_distance_to_eye);
float d_factor = 1.0 + 1.0 * d_fade;
d_factor *= clamp(max_height/0.3,0.5, 1.0);
float bladeFlag = BladeNoise2D(texCoord, 0.015, grass_density, g_layer, d_factor, h_factor);
if (grass_groups >1) {bladeFlag += BladeNoise2D(texCoord, 0.01, grass_density, g_layer, d_factor, h_factor);}
if (grass_groups >2) {bladeFlag += BladeNoise2D(texCoord, 0.007, grass_density, g_layer, d_factor, h_factor);}
if (bladeFlag > 0.0) {value = 1.0;}
else {discard;}
vec3 texel = texture2D(colorTex, texCoord).rgb;
// autumn coloring
texel.r = min(1.0, (1.0 + 2.5 * 0.1 * season) * texel.r);
texel.g = texel.g;
texel.b = max(0.0, (1.0 - 4.0 * 0.1 * season) * texel.b);
float intensity = length(texel.rgb) * (1.0 - 0.5 * smoothstep(1.1,2.0,season)) * mix(0.3, 1.0, getShadowing());
texel.rgb = intensity * normalize(mix(texel.rgb, vec3(0.23,0.17,0.08), smoothstep(1.1,2.0, season)));
float base_alpha = clamp(0.4 * max_height/0.3, 0.4, 1.0);
value*= base_alpha * (1.0 - d_fade);
value *= 1.0 - smoothstep(visibility* 0.5, visibility, g_distance_to_eye);
value= clamp(value, 0.0, 1.0);
texel *= length(gl_LightSource[0].diffuse.rgb)/1.73 * scattering;
texel = clamp(texel, 0.0, 1.0);
vec4 fragColor = vec4 (texel, value);
fragColor.rgb = filter_combined(fragColor.rgb);
gl_FragColor = fragColor;
}