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 @@ -32,8 +32,12 @@ varying vec3 v; varying vec4 normalCoords; +#if USE_REFLECTION varying vec3 reflectionCoords; +#endif +#if USE_REFRACTION varying vec3 refractionCoords; +#endif varying vec2 losCoords; varying float fwaviness; @@ -53,7 +57,9 @@ uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement -uniform sampler2D reflectionMap; +#if USE_REFLECTION + uniform sampler2D reflectionMap; +#endif #if USE_REFRACTION uniform sampler2D refractionMap; @@ -181,9 +187,9 @@ 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 + #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). @@ -192,100 +198,99 @@ 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; - - // 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)); - - float undisto_z_b = texture2D(depthTex, (gl_FragCoord.xy) / screenSize).x; - 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); - - // 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_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 + // Don't change these two. They should match the values in the config (TODO: dec uniforms). + float zNear = 2.0; + float zFar = 4096.0; + + // 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)); + + float undisto_z_b = texture2D(depthTex, (gl_FragCoord.xy) / screenSize).x; + 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); -#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 + // 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); - if (waterDepth < 0.0) - depth = 0.0; -#endif + #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; - - // Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red. - // If we get a pure red fragment, use an undistorted/less distorted coord instead. - // blur the refraction map, distoring using n so that it looks more random than it really is - // and thus looks much better. - float blur = (0.3 + clamp(n.x, -0.1, 0.1)) / refractionCoords.z; - - vec4 blurColor = vec4(refColor, 1.0); - - vec4 tex = texture2D(refractionMap, refrCoords + vec2(blur + n.x, blur + n.z)); - blurColor += vec4(tex.rgb * tex.a, tex.a); - tex = texture2D(refractionMap, refrCoords + vec2(-blur, blur + n.z)); - blurColor += vec4(tex.rgb * tex.a, tex.a); - tex = texture2D(refractionMap, refrCoords + vec2(-blur, -blur + n.x)); - blurColor += vec4(tex.rgb * tex.a, tex.a); - tex = texture2D(refractionMap, refrCoords + vec2(blur + n.z, -blur)); - blurColor += vec4(tex.rgb * tex.a, tex.a); - blurColor /= blurColor.a; - float blurFactor = (distoFactor / 7.0); - refColor = (refColor + blurColor.rgb * blurFactor) / (1.0 + blurFactor); - - // Apply water tint and murk color. - float extFact = max(0.0, 1.0 - (depth * fixedVy / murky)); - float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky)); - vec3 colll = mix(refColor * tint, refColor, ColextFact); + #if USE_FANCY_EFFECTS + depth = max(depth, fancyeffects.a); + if (waterDepth < 0.0) + depth = 0.0; + #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; + + // Note, the refraction map is cleared using (255, 0, 0), so pixels outside of the water plane are pure red. + // If we get a pure red fragment, use an undistorted/less distorted coord instead. + // blur the refraction map, distoring using n so that it looks more random than it really is + // and thus looks much better. + float blur = (0.3 + clamp(n.x, -0.1, 0.1)) / refractionCoords.z; + + vec4 blurColor = vec4(refColor, 1.0); + + vec4 tex = texture2D(refractionMap, refrCoords + vec2(blur + n.x, blur + n.z)); + blurColor += vec4(tex.rgb * tex.a, tex.a); + tex = texture2D(refractionMap, refrCoords + vec2(-blur, blur + n.z)); + blurColor += vec4(tex.rgb * tex.a, tex.a); + tex = texture2D(refractionMap, refrCoords + vec2(-blur, -blur + n.x)); + blurColor += vec4(tex.rgb * tex.a, tex.a); + tex = texture2D(refractionMap, refrCoords + vec2(blur + n.z, -blur)); + blurColor += vec4(tex.rgb * tex.a, tex.a); + blurColor /= blurColor.a; + float blurFactor = (distoFactor / 7.0); + refColor = (refColor + blurColor.rgb * blurFactor) / (1.0 + blurFactor); + + // Apply water tint and murk color. + float extFact = max(0.0, 1.0 - (depth * fixedVy / murky)); + float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky)); + vec3 colll = mix(refColor * tint, refColor, ColextFact); + + refrColor = mix(color, colll, extFact); + #else - refrColor = mix(color, colll, extFact); -#else + #if USE_FANCY_EFFECTS + depth = max(depth, fancyeffects.a); + #endif -#if USE_FANCY_EFFECTS - depth = max(depth, fancyeffects.a); -#endif + // Apply water tint and murk color only. + float extFact = max(0.0, 1.0 - (depth * fixedVy / murky)); + float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky)); + vec3 colll = mix(color * tint, color, ColextFact); + + refrColor = mix(color, colll, extFact); + #endif - // Apply water tint and murk color only. - float extFact = max(0.0, 1.0 - (depth * fixedVy / murky)); - float ColextFact = max(0.0, 1.0 - (depth * fixedVy / murky)); - vec3 colll = mix(color * tint, color, ColextFact); - - refrColor = mix(color, colll, extFact); -#endif // Reflections // 3 level of settings: @@ -296,82 +301,81 @@ float reflMod = 0.75; vec3 eye = reflect(v, n); -#if USE_REFLECTION || USE_REFRACTION -#if USE_REFLECTION - float refVY = clamp(v.y * 2.0, 0.05, 1.0); - - // Distort the reflection coords based on waves. - reflCoords = (0.5 * reflectionCoords.xy - 15.0 * n.zx / refVY) / reflectionCoords.z + 0.5; - vec4 refTex = texture2D(reflectionMap, reflCoords); + #if USE_REFLECTION || USE_REFRACTION + #if USE_REFLECTION + float refVY = clamp(v.y * 2.0, 0.05, 1.0); + + // Distort the reflection coords based on waves. + reflCoords = (0.5 * reflectionCoords.xy - 15.0 * n.zx / refVY) / reflectionCoords.z + 0.5; + vec4 refTex = texture2D(reflectionMap, reflCoords); - reflColor = refTex.rgb; + reflColor = refTex.rgb; - if (refTex.a < 0.99) - { -#endif - - // Calculate where we intersect with the skycube. - Ray myRay = Ray(vec3(worldPos.x / 4.0, worldPos.y, worldPos.z / 4.0), eye); - vec3 start = vec3(-1500.0 + mapSize / 2.0, -100.0, -1500.0 + mapSize / 2.0); - vec3 end = vec3(1500.0 + mapSize / 2.0, 500.0, 1500.0 + mapSize / 2.0); - float tmin = IntersectBox(myRay, start, end); - vec4 newpos = vec4(-worldPos.x / 4.0, worldPos.y, -worldPos.z / 4.0, 1.0) + vec4(eye * tmin, 0.0) - vec4(-mapSize / 2.0, worldPos.y, -mapSize / 2.0, 0.0); - newpos *= skyBoxRot; - newpos.y *= 4.0; -#if !USE_REFLECTION - reflColor = textureCube(skyCube, newpos.rgb).rgb; -#else - // Interpolate between the sky color and nearby objects. - reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a); - } - // reflMod is used to reduce the intensity of sky reflections, which otherwise are too extreme. - reflMod = max(refTex.a, 0.75); -#endif + if (refTex.a < 0.99) + { + #endif + // Calculate where we intersect with the skycube. + Ray myRay = Ray(vec3(worldPos.x / 4.0, worldPos.y, worldPos.z / 4.0), eye); + vec3 start = vec3(-1500.0 + mapSize / 2.0, -100.0, -1500.0 + mapSize / 2.0); + vec3 end = vec3(1500.0 + mapSize / 2.0, 500.0, 1500.0 + mapSize / 2.0); + float tmin = IntersectBox(myRay, start, end); + vec4 newpos = vec4(-worldPos.x / 4.0, worldPos.y, -worldPos.z / 4.0, 1.0) + vec4(eye * tmin, 0.0) - vec4(-mapSize / 2.0, worldPos.y, -mapSize / 2.0, 0.0); + newpos *= skyBoxRot; + newpos.y *= 4.0; + #if !USE_REFLECTION + reflColor = textureCube(skyCube, newpos.rgb).rgb; + #else + // Interpolate between the sky color and nearby objects. + reflColor = mix(textureCube(skyCube, (vec4(eye, 0.0) * skyBoxRot).xyz).rgb, refTex.rgb, refTex.a); + } + // reflMod is used to reduce the intensity of sky reflections, which otherwise are too extreme. + reflMod = max(refTex.a, 0.75); + #endif -#else - // Simplest case for reflection, return a gradient of blue based on Y component. - reflColor = mix(vec3(0.76, 0.84, 0.92), vec3(0.24, 0.43, 0.71), -eye.y); -#endif + #else + // Simplest case for reflection, return a gradient of blue based on Y component. + reflColor = mix(vec3(0.76, 0.84, 0.92), vec3(0.24, 0.43, 0.71), -eye.y); + #endif losMod = texture2D(losMap, losCoords.st).a; losMod = losMod < 0.03 ? 0.0 : losMod; vec3 color; -#if USE_SHADOWS_ON_WATER && USE_SHADOW - float fresShadow = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2); - color = mix(refrColor, reflColor, fresShadow * reflMod); -#else - color = mix(refrColor, reflColor, fresnel * reflMod); -#endif + #if USE_SHADOWS_ON_WATER && USE_SHADOW + float fresShadow = mix(fresnel, fresnel * shadow, 0.05 + murkiness * 0.2); + color = mix(refrColor, reflColor, fresShadow * reflMod); + #else + color = mix(refrColor, reflColor, fresnel * reflMod); + #endif -#if USE_SHADOWS_ON_WATER && USE_SHADOW - color += shadow * specular; -#else - color += specular; -#endif + #if USE_SHADOWS_ON_WATER && USE_SHADOW + color += shadow * specular; + #else + color += specular; + #endif color = get_fog(color); -#if USE_FANCY_EFFECTS - vec4 FoamEffects = texture2D(waterEffectsTexOther, gl_FragCoord.xy / screenSize); + #if USE_FANCY_EFFECTS + vec4 FoamEffects = texture2D(waterEffectsTexOther, gl_FragCoord.xy / screenSize); - vec3 foam1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; - vec3 foam2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; - vec3 foam3 = texture2D(normalMap, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; - vec3 foam4 = texture2D(normalMap2, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; - vec3 foaminterp = mix(foam1, foam2, moddedTime); - foaminterp *= mix(foam3, foam4, moddedTime); + vec3 foam1 = texture2D(normalMap, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; + vec3 foam2 = texture2D(normalMap2, (normalCoords.st + normalCoords.zw * BigMovement * waviness / 10.0) * (baseScale - waviness / wavyEffect)).aaa; + vec3 foam3 = texture2D(normalMap, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; + vec3 foam4 = texture2D(normalMap2, normalCoords.st / 6.0 - normalCoords.zw * 0.02).aaa; + vec3 foaminterp = mix(foam1, foam2, moddedTime); + foaminterp *= mix(foam3, foam4, moddedTime); - foam1.x = foaminterp.x * WindCosSin.x - foaminterp.z * WindCosSin.y; + foam1.x = foaminterp.x * WindCosSin.x - foaminterp.z * WindCosSin.y; - color += FoamEffects.r * FoamEffects.a * 0.4 + pow(foam1.x * (5.0 + waviness), (2.6 - waviness / 5.5)); -#endif + color += FoamEffects.r * FoamEffects.a * 0.4 + pow(foam1.x * (5.0 + waviness), (2.6 - waviness / 5.5)); + #endif float alpha = clamp(depth, 0.0, 1.0); -#if !USE_REFRACTION - alpha = (1.4 - extFact) * alpha; -#endif + #if !USE_REFRACTION + alpha = (1.4 - extFact) * alpha; + #endif gl_FragColor = vec4(color * losMod, alpha); } Index: binaries/data/mods/public/shaders/glsl/water_high.vs =================================================================== --- binaries/data/mods/public/shaders/glsl/water_high.vs +++ binaries/data/mods/public/shaders/glsl/water_high.vs @@ -29,8 +29,12 @@ varying vec3 v; varying vec4 normalCoords; +#if USE_REFLECTION varying vec3 reflectionCoords; +#endif +#if USE_REFRACTION varying vec3 refractionCoords; +#endif varying vec2 losCoords; varying float fwaviness; @@ -58,8 +62,12 @@ normalCoords = vec4(newX, newY, time, 0.0); normalCoords.xy *= repeatScale; // Projective texturing +#if USE_REFLECTION reflectionCoords = (reflectionMatrix * vec4(a_vertex, 1.0)).rga; +#endif +#if USE_REFRACTION refractionCoords = (refractionMatrix * vec4(a_vertex, 1.0)).rga; +#endif losCoords = (losMatrix * vec4(a_vertex, 1.0)).rg; #if USE_SHADOW && USE_SHADOWS_ON_WATER Index: source/renderer/TerrainRenderer.cpp =================================================================== --- source/renderer/TerrainRenderer.cpp +++ source/renderer/TerrainRenderer.cpp @@ -756,8 +756,8 @@ if (WaterMgr->m_WaterRefraction) m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture); - - m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture); + if (WaterMgr->m_WaterReflection) + m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture); m->fancyWaterShader->BindTexture(str_losMap, losTexture.GetTextureSmooth()); const CLightEnv& lightEnv = g_Renderer.GetLightEnv(); @@ -773,6 +773,11 @@ skyBoxRotation.SetIdentity(); skyBoxRotation.RotateY(M_PI + lightEnv.GetRotation()); m->fancyWaterShader->Uniform(str_skyBoxRot, skyBoxRotation); + + if (WaterMgr->m_WaterRefraction) + m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix); + if (WaterMgr->m_WaterReflection) + m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix); } m->fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir()); m->fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor); @@ -782,8 +787,6 @@ m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness); m->fancyWaterShader->Uniform(str_windAngle, WaterMgr->m_WindAngle); m->fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod); - m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix); - m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix); m->fancyWaterShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix()); m->fancyWaterShader->Uniform(str_cameraPos, camPos); m->fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor);