Index: binaries/data/mods/public/shaders/glsl/water_high.fs =================================================================== --- binaries/data/mods/public/shaders/glsl/water_high.fs +++ binaries/data/mods/public/shaders/glsl/water_high.fs @@ -180,18 +180,24 @@ float specIntensity = clamp(pow(abs(dot(specVector, v)), 100.0), 0.0, 1.0); specular = specIntensity*1.2 * mix(vec3(1.5), sunColor,0.5); + +#if USE_SHADOWS_ON_WATER && USE_SHADOW + float shadow = get_shadow(vec4(v_shadow.xy, v_shadow.zw)); +#endif + + // for refraction, we want to adjust the value by v.y slightly otherwise it gets too different between "from above" and "from the sides". + // And it looks weird (again, we are not used to seeing water from above). + float fixedVy = max(v.y,0.01); + + float murky = mix(200.0,0.1,pow(murkiness,0.25)); float depth; #if USE_REAL_DEPTH // Don't change these two. They should match the values in the config (TODO: dec uniforms). float zNear = 2.0; float zFar = 4096.0; - - // Okay so here it's a tad complicated. I want to distort the depth buffer along the waves for a nice effect. - // However this causes a problem around underwater objects (think fishes): on some pixels, the depth will be seen as the same as the fishes' - // and the color will be grass ( cause I don't distort the refraction coord by exactly the same stuff) - // Also, things like towers with the feet in water would cause the buffer to see the depth as actually negative in some places. - // So what I do is first check the undistorted depth, then I compare with the distorted value and fix. + + // Compute real depth at the target point. float water_b = gl_FragCoord.z; float water_n = 2.0 * water_b - 1.0; float waterDBuffer = 2.0 * zNear * zFar / (zFar + zNear - water_n * (zFar - zNear)); @@ -200,37 +206,39 @@ float undisto_z_n = 2.0 * undisto_z_b - 1.0; float waterDepth_undistorted = (2.0 * zNear * zFar / (zFar + zNear - undisto_z_n * (zFar - zNear)) - waterDBuffer); - vec2 depthCoord = clamp((gl_FragCoord.xy) / screenSize - n.xz*clamp( waterDepth_undistorted/400.0,0.0,0.05) , 0.001, 0.999); - - float z_b = texture2D(depthTex, depthCoord).x; - - if (z_b < undisto_z_b) - z_b = undisto_z_b; - float z_n = 2.0 * z_b - 1.0; - - depth = (2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)) - waterDBuffer); + // Set depth to the depth at the undistorted point. + depth = waterDepth_undistorted; #else + // fake depth computation: take the value at the vertex, add some if we are looking at a more oblique angle. depth = waterDepth / (min(0.5,v.y)*1.5*min(0.5,v.y)*2.0); #endif #if USE_FANCY_EFFECTS depth = max(depth,fancyeffects.a); #endif - -#if USE_SHADOWS_ON_WATER && USE_SHADOW - float shadow = get_shadow(vec4(v_shadow.xy, v_shadow.zw)); -#endif - - // for refraction, we want to adjust the value by v.y slightly otherwise it gets too different between "from above" and "from the sides". - // And it looks weird (again, we are not used to seeing water from above). - float fixedVy = max(v.y,0.01); - - float murky = mix(200.0,0.1,pow(murkiness,0.25)); - + #if USE_REFRACTION + // for refraction we want to distort more as depth goes down. + // 1) compute a distortion based on depth at the pixel. + // 2) Re-sample the depth at the target point + // 3) Sample refraction texture + // distoFactor controls the amount of distortion relative to wave normals. float distoFactor = 0.5 + clamp(depth/2.0,0.0,7.0); +#if USE_REAL_DEPTH + vec2 depthCoord = clamp((gl_FragCoord.xy) / screenSize - n.xz * distoFactor / refractionCoords.z, 0.001, 0.999); + float z_b = texture2D(depthTex, depthCoord).x; + float z_n = 2.0 * z_b - 1.0; + float newDepth = (2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)) - waterDBuffer); + + // try to correct for fish. In general they'd look weirder without this fix. + if (depth > newDepth + 3.0) + distoFactor /= 2.0; // this in general will not fall on the fish but still look distorted. + else + depth = newDepth; +#endif + // Distort the texture coords under where the water is to simulate refraction. refrCoords = (0.5 * refractionCoords.xy - n.xz * distoFactor) / refractionCoords.z + 0.5; vec3 refColor = texture2D(refractionMap, refrCoords).rgb; @@ -266,6 +274,7 @@ vec3 colll = mix(refColor*tint,refColor,ColextFact); refrColor = mix(color, colll, extFact); + #else // Apply water tint and murk color only. float extFact = max(0.0,1.0 - (depth*fixedVy/murky));