Make water efect use png textures by default, and rely on their dds counterparts...
[fg:toms-fgdata.git] / Shaders / water.frag
1 // This shader is mostly an adaptation of the shader found at
2 //  http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
3 //  available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
4 //  © Michael Horsch - 2005
5 //  Major update and revisions - 2011-10-07
6 //  © Emilian Huminiuc and Vivian Meazza
7 //  Optimisation - 2012-5-05
8 //  Based on ideas by Thorsten Renk
9 //  © Emilian Huminiuc and Vivian Meazza
10
11 #version 120
12
13 uniform sampler2D water_normalmap;
14 uniform sampler2D water_reflection;
15 uniform sampler2D water_dudvmap;
16 uniform sampler2D water_reflection_grey;
17 uniform sampler2D sea_foam;
18 uniform sampler2D perlin_normalmap;
19
20 uniform float saturation, Overcast, WindE, WindN;
21 uniform float CloudCover0, CloudCover1, CloudCover2, CloudCover3, CloudCover4;
22 uniform float osg_SimulationTime;
23 uniform int Status;
24
25 varying vec4 waterTex1; //moving texcoords
26 varying vec4 waterTex2; //moving texcoords
27 varying vec3 viewerdir;
28 varying vec3 lightdir;
29 varying vec3 normal;
30
31 uniform    float WaveFreq ;
32 uniform    float WaveAmp ;
33 uniform    float WaveSharp ;
34 uniform    float normalmap_dds;
35
36 ////fog "include" /////
37 uniform int fogType;
38
39 vec3 fog_Func(vec3 color, int type);
40 //////////////////////
41
42 /////// functions /////////
43
44 void rotationmatrix(in float angle, out mat4 rotmat)
45     {
46     rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0,
47         sin( angle ),  cos( angle ), 0.0, 0.0,
48         0.0         ,  0.0         , 1.0, 0.0,
49         0.0         ,  0.0         , 0.0, 1.0 );
50     }
51
52 void main(void)
53     {
54     const vec4 sca = vec4(0.005, 0.005, 0.005, 0.005);
55     const vec4 sca2 = vec4(0.02, 0.02, 0.02, 0.02);
56     const vec4 tscale = vec4(0.25, 0.25, 0.25, 0.25);
57
58     mat4 RotationMatrix;
59     // compute direction to viewer
60     vec3 E = normalize(viewerdir);
61
62     // compute direction to light source
63     vec3 L = normalize(lightdir);
64
65     // half vector
66     vec3 H = normalize(L + E);
67
68     vec3 Normal = normalize(normal);
69
70     const float water_shininess = 240.0;
71
72     // approximate cloud cover
73     float cover = 0.0;
74     //bool Status = true;
75
76
77     float windEffect = sqrt( WindE*WindE + WindN*WindN ) * 0.6;                                          //wind speed in kt
78     float windScale = 15.0/(3.0 + windEffect);                                                                                  //wave scale
79     float windEffect_low = 0.3 + 0.7 * smoothstep(0.0, 5.0, windEffect);                                //low windspeed wave filter
80     float waveRoughness = 0.05 + smoothstep(0.0, 20.0, windEffect);                                             //wave roughness filter
81
82     float mixFactor = 0.75 - 0.15 * smoothstep(0.0, 40.0, windEffect);
83     mixFactor = clamp(mixFactor, 0.3, 0.8);
84
85     if (Status == 1){
86         cover = min(min(min(min(CloudCover0, CloudCover1),CloudCover2),CloudCover3),CloudCover4);
87         } else {
88             // hack to allow for Overcast not to be set by Local Weather
89             if (Overcast == 0){
90                 cover = 5;
91                 } else {
92                     cover = Overcast * 5;
93                 }
94         }
95
96     vec4 viewt = vec4(-E, 0.0) * 0.6;
97
98     vec4 disdis = texture2D(water_dudvmap, vec2(waterTex2 * tscale)* windScale) * 2.0 - 1.0;
99
100     vec4 dist   = texture2D(water_dudvmap, vec2(waterTex1 + disdis*sca2)* windScale) * 2.0 - 1.0;
101     dist *= (0.6 + 0.5 * smoothstep(0.0, 15.0, windEffect));
102     vec4 fdist  = normalize(dist);
103     if (normalmap_dds > 0)
104         fdist = -fdist; //dds fix
105     fdist *= sca;
106
107     //normalmaps
108     rotationmatrix(radians(3.0 * windScale + 0.6 * sin(waterTex1.s * 0.2)), RotationMatrix);
109     vec4 nmap   = texture2D(water_normalmap, vec2(waterTex1* RotationMatrix + disdis * sca2) * windScale) * 2.0 - 1.0;
110     vec4 nmap1  = texture2D(perlin_normalmap, vec2(waterTex1/** RotationMatrix*/ + disdis * sca2) * windScale) * 2.0 - 1.0;
111
112     rotationmatrix(radians(-2.0 * windScale -0.4 * sin(waterTex1.s * 0.32)), RotationMatrix);
113     nmap  += texture2D(water_normalmap, vec2(waterTex1* RotationMatrix + disdis * sca2) * windScale * 1.5) * 2.0 - 1.0;
114     //nmap1 += texture2D(perlin_normalmap, vec2(waterTex1* RotationMatrix + disdis * sca2) * windScale) * 2.0 - 1.0;
115     rotationmatrix(radians(1.5 * windScale + 0.3 * sin(waterTex1.s * 0.16)), RotationMatrix);
116     nmap  += texture2D(water_normalmap, vec2(waterTex1* RotationMatrix + disdis * sca2) * windScale * 2.1) * 2.0 - 1.0;
117     rotationmatrix(radians(-0.5 * windScale - 0.45 * sin(waterTex1.s * 0.28)), RotationMatrix);
118     nmap  += texture2D(water_normalmap, vec2(waterTex1* RotationMatrix + disdis * sca2) * windScale * 0.8) * 2.0 - 1.0;
119
120     rotationmatrix(radians(-1.2 * windScale - 0.35 * sin(waterTex1.s * 0.28)), RotationMatrix);
121     nmap  += texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix* tscale) * windScale * 1.7) * 2.0 - 1.0;
122     nmap1 += texture2D(perlin_normalmap, vec2(waterTex2/** RotationMatrix*/ * tscale) * windScale) * 2.0 - 1.0;
123
124     nmap  *= windEffect_low;
125     nmap1 *= windEffect_low;
126     // mix water and noise, modulated by factor
127     vec4 vNorm = normalize(mix(nmap, nmap1, mixFactor) * waveRoughness);
128     if (normalmap_dds > 0)
129         vNorm = -vNorm;         //dds fix
130
131     //load reflection
132     vec4 tmp = vec4(lightdir, 0.0);
133     vec4 refTex = texture2D(water_reflection, vec2(tmp + waterTex1) * 32.0) ;
134     vec4 refTexGrey = texture2D(water_reflection_grey, vec2(tmp + waterTex1) * 32.0) ;
135     vec4 refl ;
136
137     //    cover = 0;
138
139     if(cover >= 1.5){
140         refl = normalize(refTex);
141         refl.a = 1.0;
142         }
143     else
144         {
145         refl = normalize(refTexGrey);
146         refl.r *= (0.75 + 0.15 * cover);
147         refl.g *= (0.80 + 0.15 * cover);
148         refl.b *= (0.875 + 0.125 * cover);
149         refl.a  = 1.0;
150         }
151
152     rotationmatrix(radians(2.1* windScale + 0.25 * sin(waterTex1.s *0.14)), RotationMatrix);
153     vec3 N0 = vec3(texture2D(water_normalmap, vec2(waterTex1* RotationMatrix + disdis * sca2) * windScale * 1.15) * 2.0 - 1.0);
154     vec3 N1 = vec3(texture2D(perlin_normalmap, vec2(waterTex1/** RotationMatrix*/ + disdis * sca) * windScale) * 2.0 - 1.0);
155
156     rotationmatrix(radians(-1.5 * windScale -0.32 * sin(waterTex1.s *0.24)), RotationMatrix);
157     N0 += vec3(texture2D(water_normalmap, vec2(waterTex2* RotationMatrix  * tscale) * windScale * 1.8) * 2.0 - 1.0);
158     N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex2/** RotationMatrix*/ * tscale) * windScale) * 2.0 - 1.0);
159
160     rotationmatrix(radians(3.8 * windScale + 0.45 * sin(waterTex1.s *0.32)), RotationMatrix);
161     N0 += vec3(texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale * 0.85) * 2.0 - 1.0);
162     N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex2/** RotationMatrix*/ * (tscale + sca2))  * windScale) * 2.0 - 1.0);
163
164     rotationmatrix(radians(-2.8 * windScale - 0.38 * sin(waterTex1.s * 0.26)), RotationMatrix);
165     N0 += vec3(texture2D(water_normalmap, vec2(waterTex1 * RotationMatrix + disdis * sca2) * windScale * 2.1) * 2.0 - 1.0);
166     N1 += vec3(texture2D(perlin_normalmap, vec2(waterTex1 /** RotationMatrix*/ + disdis * sca) * windScale) * 2.0 - 1.0);
167
168     N0 *= windEffect_low;
169     N1 *= windEffect_low;
170
171     vec3 N = normalize(mix(Normal + N0, Normal + N1, mixFactor) * waveRoughness);
172
173     if (normalmap_dds > 0)
174         N = -N; //dds fix
175
176     // specular
177     vec3 specular_color = vec3(gl_LightSource[0].diffuse)
178         * pow(max(0.0, dot(N, H)), water_shininess) * 6.0;
179     vec4 specular = vec4(specular_color, 0.5);
180
181     specular = specular * saturation * 0.3 ;
182
183     //calculate fresnel
184     vec4 invfres = vec4( dot(vNorm, viewt) );
185     vec4 fres = vec4(1.0) + invfres;
186     refl *= fres;
187
188     //calculate final colour
189     vec4 ambient_light = gl_LightSource[0].diffuse;
190     vec4 finalColor;
191
192     if(cover >= 1.5){
193         finalColor = refl + specular;
194         } else {
195             finalColor = refl;
196         }
197
198     float foamSlope = 0.10 + 0.1 * windScale;
199
200     vec4 foam_texel = texture2D(sea_foam, vec2(waterTex2 * tscale) * 25.0);
201     float waveSlope = N.g;
202
203     if (windEffect >= 8.0)
204         if (waveSlope >= foamSlope){
205             finalColor = mix(finalColor, max(finalColor, finalColor + foam_texel), smoothstep(0.01, 0.50, N.g));
206             }
207
208
209         finalColor *= ambient_light;
210
211         //gl_FragColor = mix(gl_Fog.color, finalColor, fogFactor);
212         finalColor.rgb = fog_Func(finalColor.rgb, fogType);
213         gl_FragColor = finalColor;
214     }