113 lines
3 KiB
Text
113 lines
3 KiB
Text
|
!!cvarf r_glsl_turbscale=1
|
||
|
!!cvarf gl_maxdist=8192
|
||
|
!!cvarf gl_mindist=4
|
||
|
!!samps normalmap diffuse 4
|
||
|
!!argb reflect=0 //s_t1 is a reflection instead of diffusemap
|
||
|
!!argf strength=0.1 //0.1 = fairly gentle, 0.2 = big waves
|
||
|
!!argf fresnel=5.0 //water should be around 5
|
||
|
!!argf txscale=0.2 //wave strength
|
||
|
!!argb ripplemap=0 //s_t2 contains a ripplemap
|
||
|
!!arg3f tint=0.7 0.8 0.7 //some colour value
|
||
|
!!argb depth=0 //s_t3 is a depth image
|
||
|
!!arg3f fogtint=0.2 0.3 0.2 //tints as it gets deeper
|
||
|
|
||
|
|
||
|
#include "sys/defs.h"
|
||
|
|
||
|
layout(location=0) varying vec2 tc;
|
||
|
layout(location=1) varying vec4 tf;
|
||
|
layout(location=2) varying vec3 norm;
|
||
|
layout(location=3) varying vec3 eye;
|
||
|
#ifdef VERTEX_SHADER
|
||
|
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
|
||
|
|
||
|
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, arg_txscale*tc + vec2(e_time*0.1, 0.0)).xyz);
|
||
|
n += (texture2D(s_normalmap, arg_txscale*tc - vec2(0, e_time*0.097)).xyz);
|
||
|
n -= 1.0 - 4.0/256.0;
|
||
|
|
||
|
if (arg_ripplemap)
|
||
|
n += texture2D(s_ripplemap, stc).rgb*3.0;
|
||
|
|
||
|
//the fresnel term decides how transparent the water should be
|
||
|
fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), arg_fresnel);
|
||
|
|
||
|
if (arg_depth)
|
||
|
{
|
||
|
float far = cvar_gl_maxdist;
|
||
|
float near = 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;
|
||
|
|
||
|
|
||
|
//refraction image (and water fog, if possible)
|
||
|
refr = texture2D(s_refract, stc + n.st*arg_strength*cvar_r_glsl_turbscale).rgb * arg_tint;
|
||
|
if (arg_depth)
|
||
|
refr = mix(refr, arg_fogtint, min(depth/4096.0, 1.0));
|
||
|
|
||
|
//reflection/diffuse
|
||
|
if (arg_reflect)
|
||
|
refl = texture2D(s_reflect, stc - n.st*arg_strength*cvar_r_glsl_turbscale).rgb;
|
||
|
else
|
||
|
refl = texture2D(s_diffuse, ntc).xyz;
|
||
|
|
||
|
//FIXME: add specular tints
|
||
|
|
||
|
//interplate by fresnel
|
||
|
refr = mix(refr, refl, fres);
|
||
|
|
||
|
//done
|
||
|
gl_FragColor = vec4(refr, 1.0);
|
||
|
}
|
||
|
#endif
|