174 lines
5.6 KiB
GLSL
174 lines
5.6 KiB
GLSL
|
// -*-C++-*-
|
||
|
#version 120
|
||
|
|
||
|
#define BLADE_FRACTION 0.1
|
||
|
#define MAX_LAYERS 30
|
||
|
#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 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));
|
||
|
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;
|
||
|
}
|