Index: binaries/data/mods/public/gui/options/options.json =================================================================== --- binaries/data/mods/public/gui/options/options.json +++ binaries/data/mods/public/gui/options/options.json @@ -220,14 +220,6 @@ }, { "type": "boolean", - "label": "Real water depth", - "tooltip": "Use actual water depth in rendering calculations.", - "dependencies": ["watereffects"], - "config": "waterrealdepth", - "function": "Renderer_SetWaterRealDepthEnabled" - }, - { - "type": "boolean", "label": "Water reflections", "tooltip": "Allow water to reflect a mirror image.", "dependencies": ["watereffects"], @@ -244,6 +236,14 @@ }, { "type": "boolean", + "label": "Real water depth", + "tooltip": "Use actual water depth in rendering calculations.", + "dependencies": ["watereffects", "waterrefraction"], + "config": "waterrealdepth", + "function": "Renderer_SetWaterRealDepthEnabled" + }, + { + "type": "boolean", "label": "Shadows on water", "tooltip": "Cast shadows on water.", "dependencies": ["watereffects"], 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 @@ -59,11 +59,11 @@ #if USE_REFRACTION uniform sampler2D refractionMap; -#endif #if USE_REAL_DEPTH uniform sampler2D depthTex; - uniform float zNear; - uniform float zFar; + uniform mat4 projInvTransform; + uniform mat4 viewInvTransform; +#endif #endif #if USE_SHADOWS_ON_WATER && USE_SHADOW @@ -213,24 +213,31 @@ return vec4(reflColor, reflMod); } +#if USE_REFRACTION && USE_REAL_DEPTH +vec3 getWorldPositionFromRefractionDepth(vec2 uv) +{ + float depth = texture2D(depthTex, uv).x; + vec4 viewPosition = projInvTransform * (vec4((uv - vec2(0.5)) * 2.0, depth * 2.0 - 1.0, 1.0)); + viewPosition /= viewPosition.w; + vec3 refrWorldPos = (viewInvTransform * viewPosition).xyz; + // Depth buffer precision errors can give heights above the water. + refrWorldPos.y = min(refrWorldPos.y, worldPos.y); + return refrWorldPos; +} +#endif + vec4 getRefraction(vec3 normal, vec3 eyeVec, float depthLimit) { - float depth; -#if USE_REAL_DEPTH +#if USE_REFRACTION && USE_REAL_DEPTH // 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); + vec2 coords = (0.5 * refractionCoords.xy) / refractionCoords.z + 0.5; + vec3 refrWorldPos = getWorldPositionFromRefractionDepth(coords); // Set depth to the depth at the undistorted point. - depth = waterDepth_undistorted; + float depth = distance(refrWorldPos, worldPos); #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, eyeVec.y) * 1.5 * min(0.5, eyeVec.y) * 2.0); + float depth = waterDepth / (min(0.5, eyeVec.y) * 1.5 * min(0.5, eyeVec.y) * 2.0); #endif #if USE_REFRACTION @@ -243,10 +250,10 @@ float distoFactor = 0.5 + clamp(depth / 2.0, 0.0, 7.0); #if USE_REAL_DEPTH - vec2 depthCoord = clamp((gl_FragCoord.xy) / screenSize - normal.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); + // Distort the texture coords under where the water is to simulate refraction. + vec2 shiftedCoords = (0.5 * refractionCoords.xy - normal.xz * distoFactor) / refractionCoords.z + 0.5; + vec3 refrWorldPos2 = getWorldPositionFromRefractionDepth(shiftedCoords); + float newDepth = distance(refrWorldPos2, worldPos); // try to correct for fish. In general they'd look weirder without this fix. if (depth > newDepth + 3.0) @@ -269,7 +276,7 @@ // If we get a pure red fragment, use an undistorted/less distorted coord instead. // blur the refraction map, distoring using normal so that it looks more random than it really is // and thus looks much better. - float blur = (0.3 + clamp(normal.x, -0.1, 0.1)) / refractionCoords.z; + float blur = (0.1 + clamp(normal.x, -0.1, 0.1)) / refractionCoords.z; vec4 blurColor = vec4(refColor, 1.0); Index: source/ps/CStrInternStatic.h =================================================================== --- source/ps/CStrInternStatic.h +++ source/ps/CStrInternStatic.h @@ -123,6 +123,7 @@ X(particle_solid) X(playerColor) X(pointSize) +X(projInvTransform) X(qualityLevel) X(reflectionMap) X(reflectionMatrix) @@ -152,6 +153,7 @@ X(tint) X(transform) X(translation) +X(viewInvTransform) X(water_simple) X(waterEffectsTex) X(waterTex) Index: source/renderer/Renderer.cpp =================================================================== --- source/renderer/Renderer.cpp +++ source/renderer/Renderer.cpp @@ -1102,6 +1102,8 @@ // Save the model-view-projection matrix so the shaders can use it for projective texturing wm.m_RefractionMatrix = m_ViewCamera.GetViewProjection(); + wm.m_RefractionProjInvMatrix = m_ViewCamera.GetProjection().GetInverse(); + wm.m_RefractionViewInvMatrix = m_ViewCamera.GetOrientation(); float vpHeight = wm.m_RefTextureSize; float vpWidth = wm.m_RefTextureSize; Index: source/renderer/TerrainRenderer.cpp =================================================================== --- source/renderer/TerrainRenderer.cpp +++ source/renderer/TerrainRenderer.cpp @@ -685,28 +685,6 @@ CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture(); - // creating the real depth texture using the depth buffer. - if (WaterMgr->m_WaterRealDepth) - { - if (WaterMgr->m_depthTT == 0) - { - GLuint depthTex; - glGenTextures(1, (GLuint*)&depthTex); - WaterMgr->m_depthTT = depthTex; - glBindTexture(GL_TEXTURE_2D, WaterMgr->m_depthTT); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, g_Renderer.GetWidth(), g_Renderer.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - else - { - glBindTexture(GL_TEXTURE_2D, WaterMgr->m_depthTT); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight(), 0); - } - glBindTexture(GL_TEXTURE_2D, 0); - } // Calculating the advanced informations about Foam and all if the quality calls for it. /*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves)) { @@ -769,8 +747,12 @@ m->fancyWaterShader->BindTexture(str_waterEffectsTex, WaterMgr->m_FancyTexture); } - if (WaterMgr->m_WaterRealDepth) - m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_depthTT); + if (WaterMgr->m_WaterRefraction && WaterMgr->m_WaterRealDepth) + { + m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_RefrFboDepthTexture); + m->fancyWaterShader->Uniform(str_projInvTransform, WaterMgr->m_RefractionProjInvMatrix); + m->fancyWaterShader->Uniform(str_viewInvTransform, WaterMgr->m_RefractionViewInvMatrix); + } if (WaterMgr->m_WaterRefraction) m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture); @@ -809,11 +791,6 @@ m->fancyWaterShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix()); m->fancyWaterShader->Uniform(str_cameraPos, camera.GetOrientation().GetTranslation()); - if (WaterMgr->m_WaterRealDepth) - { - m->fancyWaterShader->Uniform(str_zNear, camera.GetNearPlane()); - m->fancyWaterShader->Uniform(str_zFar, camera.GetFarPlane()); - } m->fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor); m->fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f); Index: source/renderer/WaterManager.h =================================================================== --- source/renderer/WaterManager.h +++ source/renderer/WaterManager.h @@ -61,7 +61,6 @@ CTexturePtr m_WaveTex; CTexturePtr m_FoamTex; - GLuint m_depthTT; GLuint m_FancyTexture; GLuint m_FancyTextureDepth; GLuint m_ReflFboDepthTexture; @@ -113,6 +112,8 @@ // (used to let the vertex shader do projective texturing) CMatrix3D m_ReflectionMatrix; CMatrix3D m_RefractionMatrix; + CMatrix3D m_RefractionProjInvMatrix; + CMatrix3D m_RefractionViewInvMatrix; // Water parameters std::wstring m_WaterType; // Which texture to use. Index: source/renderer/WaterManager.cpp =================================================================== --- source/renderer/WaterManager.cpp +++ source/renderer/WaterManager.cpp @@ -124,7 +124,6 @@ m_NeedsReloading = false; m_NeedInfoUpdate = true; - m_depthTT = 0; m_FancyTexture = 0; m_FancyTextureDepth = 0; m_ReflFboDepthTexture = 0; @@ -160,7 +159,6 @@ if (!g_Renderer.GetCapabilities().m_PrettyWater) return; - glDeleteTextures(1, &m_depthTT); glDeleteTextures(1, &m_FancyTexture); glDeleteTextures(1, &m_FancyTextureDepth); glDeleteTextures(1, &m_ReflFboDepthTexture); @@ -725,7 +723,7 @@ WaveObject* shoreWave = new WaveObject; std::vector vertices; vertices.reserve(9*width); - + shoreWave->m_Width = width; shoreWave->m_TimeDiff = diff; diff += (rand() % 100) / 25.0f + 4.0f;