#version 120
uniform sampler2D heightMap;
uniform sampler2D backBufferMap;
uniform sampler2D depthMap;
uniform sampler2D normalMap;
uniform sampler2D foamMap;
uniform sampler2D reflectionMap;
uniform mat4 proM;
// We need this matrix to restore position in world space
uniform mat4 matViewInverse;
uniform vec3 cameraPos;
float waterLevel = 0.0;
// How fast will colours fade out. You can also think about this
// values as how clear water is. Therefore use smaller values (eg. 0.05f)
// to have crystal clear water and bigger to achieve "muddy" water.
float fadeSpeed = 0.15;
// Timer
float timer = 1.0;
// Normals scaling factor
float normalScale = 1.0;
// R0 is a constant related to the index of refraction (IOR).
// It should be computed on the CPU and passed to the shader.
float R0 = 0.5;
// Maximum waves amplitude
float maxAmplitude = 1.0;
// Direction of the light
vec3 lightDir = vec3(0.0, 1.0, 0.0);
// Colour of the sun
vec3 sunColor = vec3(1.0, 1.0, 1.0);
// The smaller this value is, the more soft the transition between
// shore and water. If you want hard edges use very big value.
// Default is 1.0f.
float shoreHardness = 1.0;
// This value modifies current fresnel term. If you want to weaken
// reflections use bigger value. If you want to empasize them use
// value smaller then 0. Default is 0.0f.
float refractionStrength = 0.0;
//float refractionStrength = -0.3f;
// Modifies 4 sampled normals. Increase first values to have more
// smaller "waves" or last to have more bigger "waves"
vec4 normalModifier = vec4(1.0, 2.0, 4.0, 8.0);
// Strength of displacement along normal.
float displace = 1.7;
// Describes at what depth foam starts to fade out and
// at what it is completely invisible. The fird value is at
// what height foam for waves appear (+ waterLevel).
vec3 foamExistence = vec3(0.65, 1.35, 0.5);
float sunScale = 3.0;
mat4 matReflection = mat4(
0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.0, 0.5,
0.0, 0.0, 0.0, 1.0);
mat4 matViewProj;
float shininess = 0.7;
float specular_intensity = 0.32;
// Colour of the water surface
vec3 depthColour = vec3(0.0078, 0.5176, 0.7);
// Colour of the water depth
vec3 bigDepthColour = vec3(0.0039, 0.00196, 0.145);
vec3 extinction = vec3(7.0, 30.0, 40.0); // Horizontal
// Water transparency along eye vector.
float visibility = 4.0;
// Increase this value to have more smaller waves.
vec2 scale = vec2(0.005, 0.005);
float refractionScale = 0.005;
// Wind force in x and z axes.
vec2 wind = vec2(-0.3, 0.7);
mat3x3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)
{
vec3 dp1 = dFdx(P);
vec3 dp2 = dFdy(P);
vec2 duv1 = dFdx(UV);
vec2 duv2 = dFdy(UV);
mat3x3 M = mat3x3(dp1, dp2, cross(dp1, dp2));
mat2x3 inverseM = mat2x3( cross( M[1], M[2] ), cross( M[2], M[0] ) );
//float3 T = mul(float2(duv1.x, duv2.x), inverseM);
// float3 B = mul(float2(duv1.y, duv2.y), inverseM);
vec3 T = inverseM * vec2(duv1.x, duv2.x); //hier bin ich mir nicht sicher
vec3 B = inverseM * vec2(duv1.y, duv2.y);
return mat3x3(normalize(T), normalize(B), N);
}
// Function calculating fresnel term.
// - normal - normalized normal vector
// - eyeVec - normalized eye vector
float fresnelTerm(vec3 normal, vec3 eyeVec)
{
float angle = 1.0 - clamp(dot(normal, eyeVec), 0.0, 1.0);
float fresnel = angle * angle;
fresnel = fresnel * fresnel;
fresnel = fresnel * angle;
return clamp(fresnel * (1.0 - clamp(R0, 0.0, 1.0)) + R0 - refractionStrength, 0.0, 1.0);
}
//3D Position aus DepthMap ermitteln
vec3 getPosition(vec2 uv) {
float fDepth = texture2D(depthMap, uv).x;
vec4 vVertex;
vVertex.xy = uv * 2.0 - 1.0 ;
vVertex.z = fDepth * 2.0 - 1.0;
vVertex.w = 1.0;
vVertex = proM * vVertex;
vVertex *= 1.0 / vVertex.w;
return vVertex.xyz;
}
void main (void) {
vec3 color2 = texture2D(backBufferMap, gl_TexCoord[0].xy).rgb;
vec3 color = color2;
//vec3 position = mul(float4(tex2D(positionMap, IN.texCoord).xyz, 1.0f), matViewInverse).xyz;
vec3 position = getPosition(gl_TexCoord[0].xy).xyz;
float level = waterLevel;
float depth = 0.0;
// If we are underwater let's leave out complex computations
if(level >= cameraPos.y)
{
gl_FragColor = vec4(color2, 1.0f);
discard;
}
if(position.y <= level + maxAmplitude)
{
vec3 eyeVec = position - cameraPos;
float diff = level - position.y;
float cameraDepth = cameraPos.y - position.y;
// Find intersection with water surface
vec3 eyeVecNorm = normalize(eyeVec);
float t = (level - cameraPos.y) / eyeVecNorm.y;
vec3 surfacePoint = cameraPos + eyeVecNorm * t;
eyeVecNorm = normalize(eyeVecNorm);
vec2 texCoord;
for(int i = 0; i < 10; ++i)
{
texCoord = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * scale + timer * 0.000005 * wind;
float bias = texture2D(heightMap, texCoord).r;
bias *= 0.1;
level += bias * maxAmplitude;
t = (level - cameraPos.y) / eyeVecNorm.y;
surfacePoint = cameraPos + eyeVecNorm * t;
}
depth = length(position - surfacePoint);
float depth2 = surfacePoint.y - position.y;
eyeVecNorm = normalize(cameraPos - surfacePoint);
float normal1 = texture2D(heightMap, (texCoord + vec2(-1.0, 0.0) / 256.0)).r;
float normal2 = texture2D(heightMap, (texCoord + vec2(1.0, 0.0) / 256.0)).r;
float normal3 = texture2D(heightMap, (texCoord + vec2(0.0, -1.0) / 256.0)).r;
float normal4 = texture2D(heightMap, (texCoord + vec2(0.0, 1.0) / 256.0)).r;
vec3 myNormal = normalize(vec3((normal1 - normal2) * maxAmplitude,
normalScale,
(normal3 - normal4) * maxAmplitude));
texCoord = surfacePoint.xz * 1.6 + wind * timer * 0.00016;
mat3x3 tangentFrame = compute_tangent_frame(myNormal, eyeVecNorm, texCoord);
// float3 normal0a = normalize(mul(2.0f * tex2D(normalMap, texCoord) - 1.0f, tangentFrame));
// vec3 normal0a = normalize(mul(2.0 * texture2D(normalMap, texCoord) - 1.0, tangentFrame)); //kein mul() bei GLSL??
vec3 normal0a = normalize(tangentFrame * vec3(texture2D(normalMap, texCoord)).xyz * 2.0 - 1.0);
texCoord = surfacePoint.xz * 0.8 + wind * timer * 0.00008;
tangentFrame = compute_tangent_frame(myNormal, eyeVecNorm, texCoord);
// float3 normal1a = normalize(mul(2.0f * tex2D(normalMap, texCoord) - 1.0f, tangentFrame));
vec3 normal1a = normalize(tangentFrame * vec3(texture2D(normalMap, texCoord)).xyz * 2.0 - 1.0);
texCoord = surfacePoint.xz * 0.4 + wind * timer * 0.00004;
tangentFrame = compute_tangent_frame(myNormal, eyeVecNorm, texCoord);
// float3 normal2a = normalize(mul(2.0f * tex2D(normalMap, texCoord) - 1.0f, tangentFrame));
vec3 normal2a = normalize(tangentFrame * vec3(texture2D(normalMap, texCoord)).xyz * 2.0 - 1.0);
texCoord = surfacePoint.xz * 0.1 + wind * timer * 0.00002;
tangentFrame = compute_tangent_frame(myNormal, eyeVecNorm, texCoord);
// float3 normal3a = normalize(mul(2.0f * tex2D(normalMap, texCoord) - 1.0f, tangentFrame));
vec3 normal3a = normalize(tangentFrame * vec3(texture2D(normalMap, texCoord)).xyz * 2.0 - 1.0);
vec3 normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +
normal2a * normalModifier.z + normal3a * normalModifier.w);
texCoord = gl_TexCoord[0].xy;
texCoord.x += sin(timer * 0.002 + 3.0 * abs(position.y)) * (refractionScale * min(depth2, 1.0));
vec3 refraction = texture2D(backBufferMap, texCoord).rgb;
//if(mul(float4(tex2D(positionMap, texCoord).xyz, 1.0f), matViewInverse).y > level)
// refraction = color2;
if (vec4(matViewInverse * vec4(getPosition(texCoord).xyz, 1.0) ).y > level)
refraction = color2;
mat4x4 matTextureProj = matViewProj * matReflection; //hier auch nicht sicher wegen Mul
vec3 waterPosition = surfacePoint.xyz;
waterPosition.y -= (level - waterLevel);
// vec4 texCoordProj = mul(float4(waterPosition, 1.0f), matTextureProj);
vec4 texCoordProj = matTextureProj * vec4(waterPosition, 1.0);
vec4 dPos;
dPos.x = texCoordProj.x + displace * normal.x;
dPos.z = texCoordProj.z + displace * normal.z;
dPos.yw = texCoordProj.yw;
texCoordProj = dPos;
vec3 reflect = texture2DProj(reflectionMap, texCoordProj).xyz;
float fresnel = fresnelTerm(normal, eyeVecNorm);
vec3 depthN = vec3(depth * fadeSpeed);
vec3 waterCol = vec3(clamp(length(sunColor) / sunScale, 0.0, 1.0));
refraction = mix(mix(refraction, depthColour * waterCol, clamp(depthN / visibility, 0.0, 1.0)),
bigDepthColour * waterCol, clamp(depth2 / extinction, 0.0, 1.0));
float foam = 0.0;
texCoord = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + timer * 0.00001 * wind + sin(timer * 0.001 + position.x) * 0.005;
vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + timer * 0.00002 * wind + sin(timer * 0.001 + position.z) * 0.005;
if(depth2 < foamExistence.x)
foam = (texture2D(foamMap, texCoord).r + texture2D(foamMap, texCoord2).r) * 0.5;
else if(depth2 < foamExistence.y)
{
foam = mix((texture2D(foamMap, texCoord).r + texture2D(foamMap, texCoord2).r) * 0.5, 0.0,
(depth2 - foamExistence.x) / (foamExistence.y - foamExistence.x));
}
if(maxAmplitude - foamExistence.z > 0.0001)
{
foam += (texture2D(foamMap, texCoord) + texture2D(foamMap, texCoord2)) * 0.5 *
clamp((level - (waterLevel + foamExistence.z)) / (maxAmplitude - foamExistence.z), 0.0, 1.0);
}
vec3 specular = vec3(0.0);
vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm);
float dotSpec = clamp(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5, 0.0, 1.0);
specular = (1.0 - fresnel) * clamp(-lightDir.y, 0.0, 1.0) * ((pow(dotSpec, 512.0)) * (shininess * 1.8 + 0.2))* sunColor;
specular += specular * 25.0 * clamp(shininess - 0.05, 0.0, 1.0) * sunColor;
color = mix(refraction, reflect, fresnel);
color = clamp(color + max(specular, foam * sunColor), 0.0, 1.0);
color = mix(refraction, color, clamp(depth * shoreHardness, 0.0, 1.0));
}
if(position.y > level)
color = color2;
gl_FragColor = vec4(color, 1.0);
}