Waterflow
Visualize water in terrain
src/shaders/shallowwatershader.frag
Go to the documentation of this file.
00001 
00002 
00003 
00004 #version 430
00005 
00006 // ===== Uniform Buffers =====
00007 
00013 struct LightParam {
00014     vec3 pos;       
00015     float isDir;    
00016     vec3 color;     
00017     float specExp;  
00018 };
00019 
00020 layout(std140, binding = 0) uniform LightInfo 
00021 {
00022     LightParam lights[2];
00023 };
00024 
00025 
00026 // ===== Uniforms =====
00027 
00028 uniform vec3 camPos;                
00029 uniform vec3 size;                  
00030 uniform float time;                 
00031 uniform float transparency;         
00032 uniform sampler2D terr_texUnit;     
00033 uniform sampler2D height_texUnit;   
00034 uniform samplerCube sky_texUnit;    
00035 
00036 
00037 // ===== In/Out params =====
00038 
00039 in vec3 out_Normal;                 
00040 in vec2 out_TexCoord;               
00041 in vec3 out_ObjPos;                 
00042 
00043 out vec4 out_Color;                 
00044 
00045 
00046 // ===== Variables needed =====
00047 
00048 // Light vectors
00049 vec3 r;                             
00050 vec3 s;                             
00051 vec3 eye;                           
00052 vec3 Normal;                        
00053 vec3 re;                            
00054 vec3 right;                         
00055 
00056 // Lighting (the Phong model with extras).
00057 float kamb;                         
00058 float kdiff;                        
00059 float ktransr;                      
00060 float ktransg;                      
00061 float ktransb;                      
00062 float krefl;                        
00063 float kblue;                        
00064 
00065 vec3 ambLight;                      
00066 vec3 diffLight;                     
00067 vec3 specLight;                     
00068 vec3 reflLight;                     
00069 vec3 surfaceLight;                  
00070 vec3 bottomLight;                   
00071 
00072 // Snell's law angles.
00073 float theta1;                       
00074 float theta2;                       
00075 
00076 // Underwater triangulation components.
00077 float depth;                        
00078 vec3 displacementDirection;         
00079 float bottomDisplacement1;          
00080 vec3 displacement1;                 
00081 float depthAtDis1;                  
00082 float h;                            
00083 float alpha;                        
00084 float bottomDisplacement2;          
00085 vec3 displacement2;                 
00086 float depthAtDis2;                  
00087 float wdist;                        
00088 
00089 vec3 bottomPos;                     
00090 vec3 bottomNormal;                  
00091 
00092 // Texture lookups.
00093 vec4 terrainDataUnderSurface;       
00094 vec4 terrainDataAtDis1;             
00095 vec4 terrainDataAtBottom;           
00096 vec4 texDataAtBottom;               
00097 vec3 skyrefl;                       
00098 
00099 // Constants
00100 const float waterRefInd = 1.34451;  
00101 const float airRefInd = 1.0;        
00102 const vec3 up = vec3(0.0, 1.0, 0.0);
00103 
00104 void main(void)
00105 {
00106     // eye vector is calculated.
00107     eye = normalize(camPos - out_ObjPos);
00108 
00109     // Get the normal
00110     Normal = normalize(out_Normal);
00111 
00112     // Incident and reflected light is calculated for the light source.
00113     s = normalize(lights[0].pos - (1 - lights[0].isDir) * out_ObjPos);
00114     r = normalize(2 * Normal * dot(s, Normal) - s);
00115 
00116     right = cross(Normal, eye);
00117     // Snell's law
00118     // Since asin is not that cheap, approximations could be made here.
00119     theta1 = asin(length(right));
00120     theta2 = asin(airRefInd * sin(theta1) / waterRefInd);
00121 
00122     // Texture lookup at fragment.
00123     terrainDataUnderSurface = texture(height_texUnit, out_TexCoord);
00124 
00125     // Depth at fragment.
00126     depth = out_ObjPos.y - size.y * terrainDataUnderSurface.a;
00127     
00128     if (depth < 0 || out_ObjPos.z < 1 || out_ObjPos.x < 1 )
00129     {
00130         discard;
00131     }
00132 
00133     // To find the fragment at the bottom corresponding to what would be seen after refraction
00134     // at the water surface, a crude displacement approximation in the xz-plane from the surface
00135     // fragment to the approximated fragment at the bottom is calculated.
00136     vec3 s2 = airRefInd / waterRefInd * cross(Normal, cross(Normal, eye)) - Normal * sqrt(1 - pow(airRefInd / waterRefInd, 2) * dot(cross(Normal, eye), cross(Normal, eye)));
00137     displacementDirection = normalize(s2 - dot(s2, -up) * -up);
00138     bottomDisplacement1 = tan(theta2) * depth;
00139     displacement1 = bottomDisplacement1 * displacementDirection;
00140 
00141     // Texture lookup at approximation.
00142     terrainDataAtDis1 = texture(height_texUnit, out_TexCoord + vec2(displacement1.x / size.x, displacement1.z / size.z));
00143 
00144     // "Depth" at approximation.
00145     depthAtDis1 = out_ObjPos.y - size.y * terrainDataAtDis1.a;
00146     // Height at approximation (y distance from fragment bottom to approximation bottom).
00147     h = depth - depthAtDis1;
00148     // To minimize visual errors caused by irregular terrain, a better approximation is made.
00149     alpha = abs(atan(h / bottomDisplacement1));
00150     bottomDisplacement2 = cos(alpha) * depth * sin(theta2) / cos(alpha - theta2);
00151     displacement2 = bottomDisplacement2 * displacementDirection;
00152 
00153     // Texture lookups at better approximation.
00154     terrainDataAtBottom = texture(height_texUnit, out_TexCoord + vec2(displacement2.x / size.x, displacement2.z / size.z));
00155     texDataAtBottom = texture(terr_texUnit, out_TexCoord + vec2(displacement2.x / size.x, displacement2.z / size.z));
00156     // "Depth" at better approximation.
00157     depthAtDis2 = out_ObjPos.y - size.y * terrainDataAtBottom.a;
00158 
00159     // Coordinates and normal of seen position of bottom.
00160     bottomPos = out_ObjPos + displacement2 - vec3(0, depthAtDis2, 0);
00161     bottomNormal = normalize(terrainDataAtBottom.rgb);
00162 
00163     // Distance from surface to seen position of bottom.
00164     wdist = length(bottomPos - out_ObjPos);
00165     
00166     // Skybox reflection.
00167     // Reflected eye vector.
00168     re = 2 * dot(eye, Normal) * Normal - eye;
00169     skyrefl = texture(sky_texUnit, re).rgb;
00170     // Light components, water surface.
00171     kamb = 0.1;
00172     krefl = clamp((1 - eye.y), 0.2, 0.7);
00173     // Ambient light.
00174     ambLight = kamb * vec3(1.0, 1.0, 1.0);
00175     reflLight = vec3(0.0, 0.0, 0.0);
00176     // Reflected light.
00177     reflLight += krefl * skyrefl;
00178     
00179     surfaceLight = vec3(0.0, 0.0, 0.0);
00180     // The light components are added to the total surface light.
00181     surfaceLight += ambLight;
00182     surfaceLight += reflLight;
00183 
00184     ktransr = clamp((1 - reflLight.r) * pow((1 + wdist), -1.8 * transparency), 0.0, 0.5);
00185     ktransg = clamp((1 - reflLight.g) * pow((1 + wdist), -1.7 * transparency), 0.0, 0.5);
00186     ktransb = clamp((1 - reflLight.b) * pow((1 + wdist), -1.5 * transparency), 0.0, 0.5);
00187     kblue = 1 - eye.y;
00188 
00189     // Calculating bottom light.
00190     // Phong shading for the bottom.
00191     s = normalize(lights[1].pos - (1 - lights[1].isDir) * bottomPos);
00192     r = normalize(2 * bottomNormal * dot(s, bottomNormal) - s);
00193 
00194     // eye vector is calculated (note: from bottom to surface, not to camera).
00195     eye = normalize(out_ObjPos - bottomPos);
00196 
00197     // Light according to the Phong model.
00198     kamb = 0.1;
00199     kdiff = 0.5;
00200     krefl = 0.5;
00201     ambLight = kamb * vec3(1.0, 1.0, 1.0);
00202     diffLight = vec3(0.0, 0.0, 0.0);
00203     specLight = vec3(0.0, 0.0, 0.0);
00204     // Diffuse light.
00205     diffLight += kdiff * lights[1].color * max(0.0, dot(s, bottomNormal));
00206     // Specular light.
00207     specLight += krefl * lights[1].color * max(0.0, pow(dot(r, eye), lights[1].specExp));
00208 
00209     bottomLight = vec3(0.0, 0.0, 0.0);
00210     // The light components are added to the total bottom light.
00211     bottomLight += ambLight;
00212     bottomLight += diffLight;
00213     bottomLight += specLight;
00214     
00215     bottomLight *= texDataAtBottom.rgb;
00216     //Color dependant attenuation.
00217     bottomLight = vec3(bottomLight.r * ktransr, bottomLight.g * ktransg, bottomLight.b * ktransb);
00218 
00219     if (out_ObjPos.y > 35.0f || out_ObjPos.y < 0.000000005f) {
00220         vec3 brown = vec3(250, 184,173);
00221         brown = 0.3*normalize(brown);
00222         out_Color = vec4(brown,1);
00223     }
00224     else{
00225         out_Color = vec4(bottomLight + surfaceLight, 1.0);
00226     }
00227 }
 All Classes Files Functions Variables Enumerations