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