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); float dist = length(viewVec); //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); wavef = normalize(wavef); //wavef = vec3(0.0, 0.0, 1.0); //get base fresnel component float df = dot(viewVec,wavef); //translate and flip fresnel df = 1.0-clamp(-df,0.0,1.0); //set output alpha based on fresnel color.a = clamp((1.0-df+da)*0.5,0.0,1.0); //calculate reflection vector vec3 refnorm = vec3(wavef.x*0.5, wavef.y*0.5, wavef.z*2.0); //ramp normal towards eye for far view stuff float ramp = dist/256.0; refnorm -= viewVec * ramp; vec3 ref = reflect(viewVec.xyz, normalize(refnorm)); ref.z /= sqrt(dist); //get diffuse component float diff = clamp(dot(ref, wavef),0.0,1.0)*0.9; //fudge diffuse for extra contrast and ambience diff *= diff; diff += 0.4; vec3 fog = gl_TexCoord[5].rgb*0.5; //read from reflection map vec3 refcol = textureCube(environmentMap, ref).rgb; //tint reflection by fresnal, bias by z component of view vec color.rgb = refcol*(df*df*dcol.x*dcol.y); //add diffuse contribution (fake blue water, yay!) vec3 blue = vec3(0.1, 0.3, 0.6); color.rgb += (diff/(max(ramp, 1.0)))*vec3(fog.r*blue.r, fog.g*blue.g, fog.b*blue.b); //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 = da*color.rgb + (1.0-da)*fb.rgb; //render as solid (previous pixel color already present) color.a = 1.0; //apply fog applyScatter(color.rgb); gl_FragColor = color; }