fteqw/engine/shaders/glsl/altwater.glsl

132 lines
3.3 KiB
GLSL

!!cvarf r_glsl_turbscale
//modifier: REFLECT (s_t2 is a reflection instead of diffusemap)
//modifier: STRENGTH (0.1 = fairly gentle, 0.2 = big waves)
//modifier: FRESNEL (5=water)
//modifier: TXSCALE (0.2 - wave strength)
//modifier: RIPPLEMAP (s_t3 contains a ripplemap
//modifier: TINT (some colour value)
#ifndef FRESNEL
#define FRESNEL 5.0
#endif
#ifndef STRENGTH
#define STRENGTH 0.1
#endif
#ifndef TXSCALE
#define TXSCALE 0.2
#endif
#ifndef TINT
#define TINT vec3(0.7, 0.8, 0.7)
#endif
#ifndef FOGTINT
#define FOGTINT vec3(0.2, 0.3, 0.2)
#endif
varying vec2 tc;
varying vec4 tf;
varying vec3 norm;
varying vec3 eye;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
attribute vec3 v_normal;
uniform vec3 e_eyepos;
void main (void)
{
tc = v_texcoord.st;
tf = ftetransform();
norm = v_normal;
eye = e_eyepos - v_position.xyz;
gl_Position = tf;
}
#endif
#ifdef FRAGMENT_SHADER
#define s_refract s_t0
#define s_reflect s_t1
#define s_ripplemap s_t2
#define s_refractdepth s_t3
uniform float cvar_r_glsl_turbscale;
uniform sampler2D s_refract; //refract
uniform sampler2D s_reflect; //reflection
uniform sampler2D s_refractdepth; //refraction depth
uniform sampler2D s_ripplemap; //ripplemap
uniform float e_time;
void main (void)
{
vec2 stc, ntc;
vec3 n, refr, refl;
float fres;
float depth;
stc = (1.0 + (tf.xy / tf.w)) * 0.5;
//hack the texture coords slightly so that there are no obvious gaps
stc.t -= 1.5*norm.z/1080.0;
//apply q1-style warp, just for kicks
ntc.s = tc.s + sin(tc.t+e_time)*0.125;
ntc.t = tc.t + sin(tc.s+e_time)*0.125;
//generate the two wave patterns from the normalmap
n = (texture2D(s_normalmap, TXSCALE*tc + vec2(e_time*0.1, 0.0)).xyz);
n += (texture2D(s_normalmap, TXSCALE*tc - vec2(0, e_time*0.097)).xyz);
n -= 1.0 - 4.0/256.0;
#ifdef RIPPLEMAP
n += texture2D(s_ripplemap, stc).rgb*3.0;
#endif
//the fresnel term decides how transparent the water should be
fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), float(FRESNEL));
#ifdef DEPTH
float far = #include "cvar/gl_maxdist";
float near = #include "cvar/gl_mindist";
//get depth value at the surface
float sdepth = gl_FragCoord.z;
sdepth = (2.0*near) / (far + near - sdepth * (far - near));
sdepth = mix(near, far, sdepth);
//get depth value at the ground beyond the surface.
float gdepth = texture2D(s_refractdepth, stc).x;
gdepth = (2.0*near) / (far + near - gdepth * (far - near));
if (gdepth >= 0.5)
{
gdepth = sdepth;
depth = 0.0;
}
else
{
gdepth = mix(near, far, gdepth);
depth = gdepth - sdepth;
}
//reduce the normals in shallow water (near walls, reduces the pain of linear sampling)
if (depth < 100.0)
n *= depth/100.0;
#else
depth = 1.0;
#endif
//refraction image (and water fog, if possible)
refr = texture2D(s_refract, stc + n.st*STRENGTH*cvar_r_glsl_turbscale).rgb * TINT;
#ifdef DEPTH
refr = mix(refr, FOGTINT, min(depth/4096.0, 1.0));
#endif
//reflection/diffuse
#ifdef REFLECT
refl = texture2D(s_reflect, stc - n.st*STRENGTH*cvar_r_glsl_turbscale).rgb;
#else
refl = texture2D(s_diffuse, ntc).xyz;
#endif
//FIXME: add specular
//interplate by fresnel
refr = mix(refr, refl, fres);
//done
gl_FragColor = vec4(refr, 1.0);
}
#endif