aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
blob: e0e79e95ba063f564c26a7c940cbabbd7e6c981d (plain)
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;
}