1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
void applyScatter(inout vec3 color);
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
uniform samplerCube environmentMap; //: TEXUNIT4, // Environment map texture
uniform sampler2D screenTex; // : TEXUNIT5
uniform vec3 lightDir;
uniform vec3 specular;
uniform float lightExp;
uniform vec2 fbScale;
uniform float refScale;
float msin(float x) {
float k = sin(x)+1.0;
k *= 0.5;
k *= k;
return 2.0 * k;
}
float mcos(float x) {
float k = cos(x)+1.0;
k *= 0.5;
k *= k;
return 2.0 * k;
}
float waveS(vec2 v, float t, float a, float f, vec2 d, float s, sampler1D sinMap)
{
return texture1D(sinMap, (dot(d, v)*f + t*s)*f).r*a;
}
float waveC(vec2 v, float t, float a, float f, vec2 d, float s, sampler1D sinMap)
{
return texture1D(sinMap, (dot(d, v)*f + t*s)*f).g*a*2.0-1.0;
}
float magnitude(vec3 vec) {
return sqrt(dot(vec,vec));
}
vec3 mreflect(vec3 i, vec3 n) {
return i + n * 2.0 * abs(dot(n,i))+vec3(0.0,0.0,0.5);
}
void main()
{
vec2 texCoord = gl_TexCoord[0].xy; // Texture coordinates
vec2 littleWave1 = gl_TexCoord[0].zw;
vec2 littleWave2 = gl_TexCoord[1].xy;
vec2 bigWave = gl_TexCoord[1].zw;
vec3 viewVec = gl_TexCoord[2].xyz;
vec4 refCoord = gl_TexCoord[3];
vec4 col = gl_Color;
vec4 color;
//get color from alpha map (alpha denotes water depth), rgb denotes water color
vec4 wcol = texture2D(diffuseMap, texCoord.xy);
//store texture alpha
float da = wcol.a;
//modulate by incoming water color
//wcol.a *= refCoord.w;
//scale wcol.a (water depth) for steep transition
wcol.a *= wcol.a;
//normalize view vector
viewVec = normalize(viewVec);
//get bigwave normal
vec3 wavef = texture2D(bumpMap, bigWave).xyz*2.0;
vec3 view = vec3(viewVec.x, viewVec.y, viewVec.z);
float dx = 1.0-(dot(wavef*2.0-vec3(1.0), view))*da;
dx *= 0.274;
//get detail normals
vec3 dcol = texture2D(bumpMap, littleWave1+dx*view.xy).rgb*0.75;
dcol += texture2D(bumpMap, littleWave2+view.xy*dx*0.1).rgb*1.25;
//interpolate between big waves and little waves (big waves in deep water)
wavef = wavef*wcol.a + dcol*(1.0-wcol.a);
//crunch normal to range [-1,1]
wavef -= vec3(1,1,1);
//get base fresnel component
float df = dot(viewVec,wavef);
//reposition fresnel to latter half of [0,1]
df = 1.0-clamp(df,0.0,1.0);
//set output alpha based on fresnel
color.a = clamp((df+da)*0.5,0.0,1.0);
//calculate reflection vector
vec3 ref = reflect(viewVec.xyz, wavef);
//get specular component
float spec = clamp(dot(lightDir, normalize(ref)),0.0,1.0);
//fudge reflection to be more noisy at good angles
ref.z = ref.z*ref.z+df*df*0.5;
//get diffuse component
float diff = clamp((abs(dot(ref, wavef))),0.0,1.0)*0.9;
//fudge diffuse for extra contrast and ambience
diff *= diff;
diff += 0.4;
//set diffuse color contribution
color.rgb = textureCube(environmentMap, ref).rgb*diff;
//harden specular
spec = pow(spec, lightExp);
//add specular color contribution
color.rgb += spec * specular;
//figure out distortion vector (ripply)
vec2 distort = clamp(((refCoord.xy/refCoord.z) * 0.5 + 0.5 + wavef.xy*refScale),0.0,0.99);
//read from framebuffer (offset)
vec4 fb = texture2D(screenTex, distort*fbScale);
//tint by framebuffer
color.rgb = color.a*color.rgb + (1.0-color.a)*fb.rgb;
//apply fog
applyScatter(color.rgb);
gl_FragColor = color;
}
|