From 5571f7a7f9d10f6e2f8adad941143fac895381b6 Mon Sep 17 00:00:00 2001 From: wraitii Date: Sat, 5 Jul 2014 10:20:30 +0000 Subject: [PATCH] Fix "Wind Angle" parameter not working properly. Add a precomputed "wind strength" variable so that waves look smaller behind islands. Some tweaks. Refs #48 as usual. This was SVN commit r15492. --- .../mods/public/shaders/glsl/water_effects.fs | 12 +++-- .../mods/public/shaders/glsl/water_effects.vs | 13 +++++- .../mods/public/shaders/glsl/water_high.fs | 27 +++++++---- .../mods/public/shaders/glsl/water_high.vs | 7 ++- source/renderer/TerrainRenderer.cpp | 12 ++--- source/renderer/WaterManager.cpp | 46 +++++++++++++------ 6 files changed, 79 insertions(+), 38 deletions(-) diff --git a/binaries/data/mods/public/shaders/glsl/water_effects.fs b/binaries/data/mods/public/shaders/glsl/water_effects.fs index a846c3e9c0..4b7c92de1b 100644 --- a/binaries/data/mods/public/shaders/glsl/water_effects.fs +++ b/binaries/data/mods/public/shaders/glsl/water_effects.fs @@ -6,7 +6,9 @@ uniform float waviness; uniform vec2 screenSize; uniform float time; + varying vec3 worldPos; +varying vec4 waterInfo; uniform float mapSize; @@ -23,7 +25,8 @@ uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmoveme void main() { - float wavyFactor = waviness * 0.125; + // Fix the waviness for local wind strength + float fwaviness = waviness * ((0.15+waterInfo.r/1.15)); float wavyEffect = waveParams1.r; float baseScale = waveParams1.g; @@ -46,9 +49,12 @@ void main() ww1 = mix(ww1, ww2, mod(time * 60.0, 8.0) / 8.0); smallWW = mix(smallWW, smallWW2, mod(time * 60.0, 8.0) / 8.0) - vec3(0.5); - ww1 += vec3(smallWW.x,0.0,smallWW.z)*(waviness/10.0*smallIntensity + smallBase); + ww1 += vec3(smallWW.x,0.0,smallWW.z)*(fwaviness/10.0*smallIntensity + smallBase); - vec3 n = normalize(mix(vec3(0.0,1.0,0.0),ww1 - vec3(0.5,0.0,0.5), clamp(baseBump + waviness/flattenism,0.0,1.0))); + ww1 = mix(smallWW + vec3(0.5,0.0,0.5), ww1, waterInfo.r); + + // Flatten them based on waviness. + vec3 n = normalize(mix(vec3(0.0,1.0,0.0),ww1 - vec3(0.5,0.0,0.5), clamp(baseBump + fwaviness/flattenism,0.0,1.0))); float foamFact1 = texture2D(normalMap, (gl_TexCoord[0].st) * 0.3).a; float foamFact2 = texture2D(normalMap2, (gl_TexCoord[0].st) * 0.3).a; diff --git a/binaries/data/mods/public/shaders/glsl/water_effects.vs b/binaries/data/mods/public/shaders/glsl/water_effects.vs index 39a442a113..9a2d99e565 100644 --- a/binaries/data/mods/public/shaders/glsl/water_effects.vs +++ b/binaries/data/mods/public/shaders/glsl/water_effects.vs @@ -2,20 +2,29 @@ // This is a lightened version of water_high.vs uniform float repeatScale; -uniform vec2 translation; +uniform float windAngle; uniform float time; uniform float mapSize; varying vec3 worldPos; +varying vec4 waterInfo; attribute vec3 a_vertex; +attribute vec4 a_waterInfo; + void main() { worldPos = a_vertex; + waterInfo = a_waterInfo; + + float newX = a_vertex.x * cos(-windAngle) - a_vertex.z * sin(-windAngle); + float newY = a_vertex.x * sin(-windAngle) + a_vertex.z * cos(-windAngle); + + gl_TexCoord[0] = vec4(newX,newY,time,0.0); + gl_TexCoord[0].xy *= repeatScale; - gl_TexCoord[0] = vec4(a_vertex.xz*repeatScale,translation); gl_TexCoord[3].zw = vec2(a_vertex.xz)/mapSize; gl_Position = gl_ModelViewProjectionMatrix * vec4(a_vertex, 1.0); diff --git a/binaries/data/mods/public/shaders/glsl/water_high.fs b/binaries/data/mods/public/shaders/glsl/water_high.fs index 603aacb324..13e3fc5e39 100644 --- a/binaries/data/mods/public/shaders/glsl/water_high.fs +++ b/binaries/data/mods/public/shaders/glsl/water_high.fs @@ -33,11 +33,11 @@ uniform sampler2D normalMap2; #if USE_FANCY_EFFECTS uniform sampler2D waterEffectsTex; -#else - uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump - uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement #endif +uniform vec4 waveParams1; // wavyEffect, BaseScale, Flattenism, Basebump +uniform vec4 waveParams2; // Smallintensity, Smallbase, Bigmovement, Smallmovement + #if USE_REFLECTION uniform sampler2D reflectionMap; #endif @@ -128,6 +128,9 @@ vec3 get_fog(vec3 color) void main() { + //gl_FragColor = vec4(waterInfo.rrr,1.0); + //return; + float fresnel; float t; // Temporary variable vec2 reflCoords, refrCoords; @@ -139,7 +142,7 @@ void main() vec3 h = normalize(l + v); // Fix the waviness for local wind strength - float fwaviness = 6.0;waviness;// * ((0.15+waterInfo.r/1.15)); + float fwaviness = waviness * ((0.15+waterInfo.r/1.15)); // Calculate water normals. #if USE_FANCY_EFFECTS @@ -155,7 +158,7 @@ void main() float smallBase = waveParams2.g; float BigMovement = waveParams2.b; float SmallMovement = waveParams2.a; - + // This method uses 60 animated water frames. We're blending between each two frames // TODO: could probably have fewer frames thanks to this blending. // Scale the normal textures by waviness so that big waviness means bigger waves. @@ -167,17 +170,22 @@ void main() ww1 = mix(ww1, ww2, mod(time * 60.0, 8.0) / 8.0); smallWW = mix(smallWW, smallWW2, mod(time * 60.0, 8.0) / 8.0) - vec3(0.5); - ww1 += vec3(smallWW.x,0.0,smallWW.z)*(waviness/10.0*smallIntensity + smallBase); + ww1 += vec3(smallWW.x,0.0,smallWW.z)*(fwaviness/10.0*smallIntensity + smallBase); + ww1 = mix(smallWW + vec3(0.5,0.0,0.5), ww1, waterInfo.r); + // Flatten them based on waviness. - vec3 n = normalize(mix(vec3(0.0,1.0,0.0),ww1 - vec3(0.5,0.0,0.5), clamp(baseBump + waviness/flattenism,0.0,1.0))); + vec3 n = normalize(mix(vec3(0.0,1.0,0.0),ww1 - vec3(0.5,0.0,0.5), clamp(baseBump + fwaviness/flattenism,0.0,1.0))); // Fix our normals. //n = normalize(n - vec3(0.5, 0.5, 0.5)); #endif - + + n = mix(vec3(0.0,1.0,0.0), n,0.5 + waterInfo.r/2.0); + // simulates how parallel the "point->sun", "view->point" vectors are. float ndoth = dot(n , h); + // how perpendicular to the normal our view is. Used for fresnel. float ndotv = clamp(dot(n, v),0.0,1.0); @@ -311,7 +319,8 @@ void main() // Specular. specular = pow(ndoth, mix(5.0,2000.0, clamp(v.y*v.y*2.0,0.0,1.0)))*sunColor * 1.5;// * sunColor * 1.5 * ww.r; - + gl_FragColor = vec4(specular,1.0); + return; losMod = texture2D(losMap, gl_TexCoord[3].st).a; losMod = losMod < 0.03 ? 0.0 : losMod; diff --git a/binaries/data/mods/public/shaders/glsl/water_high.vs b/binaries/data/mods/public/shaders/glsl/water_high.vs index 3afee711ce..423f454562 100644 --- a/binaries/data/mods/public/shaders/glsl/water_high.vs +++ b/binaries/data/mods/public/shaders/glsl/water_high.vs @@ -6,7 +6,6 @@ uniform mat4 losMatrix; uniform mat4 shadowTransform; uniform float repeatScale; uniform float windAngle; -uniform vec2 translation; uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture #if USE_SHADOW_SAMPLER && USE_SHADOW_PCF @@ -31,7 +30,11 @@ void main() waterInfo = a_waterInfo; waterDepth = a_waterInfo.a; - gl_TexCoord[0] = vec4(a_vertex.xz*repeatScale,translation); + float newX = a_vertex.x * cos(-windAngle) - a_vertex.z * sin(-windAngle); + float newY = a_vertex.x * sin(-windAngle) + a_vertex.z * cos(-windAngle); + + gl_TexCoord[0] = vec4(newX,newY,time,0.0); + gl_TexCoord[0].xy *= repeatScale; gl_TexCoord[1] = reflectionMatrix * vec4(a_vertex, 1.0); // projective texturing gl_TexCoord[2] = refractionMatrix * vec4(a_vertex, 1.0); gl_TexCoord[3] = losMatrix * vec4(a_vertex, 1.0); diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index 09cbf25d26..ffab9e2aa4 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -703,13 +703,8 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr double period = 8; int curTex = (int)(time*60/period) % 60; int nexTex = (curTex + 1) % 60; - - // Shift the texture coordinates by these amounts to make the water "flow" - float tx = time*cos(WaterMgr->m_WindAngle); - float ty = time*sin(WaterMgr->m_WindAngle); float repeatPeriod = WaterMgr->m_RepeatPeriod; - GLuint FramebufferName = 0; @@ -746,9 +741,9 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr m->fancyEffectsShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]); m->fancyEffectsShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]); m->fancyEffectsShader->Uniform(str_waviness, WaterMgr->m_Waviness); - m->fancyEffectsShader->Uniform(str_translation, tx, ty); m->fancyEffectsShader->Uniform(str_repeatScale, 1.0f / repeatPeriod); m->fancyEffectsShader->Uniform(str_time, (float)time); + m->fancyEffectsShader->Uniform(str_windAngle, (float)WaterMgr->m_WindAngle); m->fancyEffectsShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f); m->fancyEffectsShader->Uniform(str_mapSize, (float)(WaterMgr->m_MapSize)); @@ -765,7 +760,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr else { m->fancyEffectsShader->Uniform(str_waveParams1, 15.0f,0.8f,10.0f,0.1f); - m->fancyEffectsShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.35f); + m->fancyEffectsShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.3f); } std::vector& visiblePatches = m->visiblePatches[cullGroup]; @@ -818,7 +813,6 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr m->fancyWaterShader->Uniform(str_waviness, WaterMgr->m_Waviness); m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness); m->fancyWaterShader->Uniform(str_windAngle, WaterMgr->m_WindAngle); - m->fancyWaterShader->Uniform(str_translation, tx, ty); m->fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod); m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix); m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix); @@ -844,7 +838,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr else { m->fancyWaterShader->Uniform(str_waveParams1, 15.0f,0.8f,10.0f,0.1f); - m->fancyWaterShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.35f); + m->fancyWaterShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.3f); } } diff --git a/source/renderer/WaterManager.cpp b/source/renderer/WaterManager.cpp index 7c188c401f..b38d288d51 100644 --- a/source/renderer/WaterManager.cpp +++ b/source/renderer/WaterManager.cpp @@ -379,6 +379,8 @@ void WaterManager::RecomputeBlurredNormalMap() m_BlurredNormalMap[j*m_MapSize + i] = blurValue * 0.2f; } } + + delete[] normals; } /////////////////////////////////////////////////////////////////// @@ -388,24 +390,26 @@ void WaterManager::RecomputeWindStrength() { if (m_WindStrength == NULL) m_WindStrength = new float[m_MapSize*m_MapSize]; - - std::fill(m_WindStrength, m_WindStrength + m_MapSize*m_MapSize, 1.0f); - + CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); float waterLevel = m_WaterHeight; CVector2D windDir = CVector2D(cos(m_WindAngle),sin(m_WindAngle)); + CVector2D perp = CVector2D(-windDir.Y, windDir.X); + // Our kernel will sample 5 points going towards the wind (generally). int kernel[5][2] = { {(int)windDir.X*2,(int)windDir.Y*2}, {(int)windDir.X*5,(int)windDir.Y*5}, {(int)windDir.X*9,(int)windDir.Y*9}, {(int)windDir.X*16,(int)windDir.Y*16}, {(int)windDir.X*25,(int)windDir.Y*25} }; - //CVector2D perp = CVector2D(-windDir.Y, windDir.X); + float* Temp = new float[m_MapSize*m_MapSize]; + std::fill(Temp, Temp + m_MapSize*m_MapSize, 1.0f); + for (size_t j = 0; j < m_MapSize; ++j) for (size_t i = 0; i < m_MapSize; ++i) { float curHeight = terrain->GetVertexGroundLevel(i,j); if (curHeight >= waterLevel) { - m_WindStrength[j*m_MapSize + i] = 0.0f; + Temp[j*m_MapSize + i] = 0.3f; // blurs too strong otherwise continue; } if (terrain->GetVertexGroundLevel(i + ceil(windDir.X),j + ceil(windDir.Y)) < waterLevel) @@ -415,34 +419,50 @@ void WaterManager::RecomputeWindStrength() float tendency = 0.0f; float oldHeight = std::max(waterLevel,terrain->GetVertexGroundLevel(i+kernel[4][0],j+kernel[4][1])); float currentHeight = std::max(waterLevel,terrain->GetVertexGroundLevel(i+kernel[3][0],j+kernel[3][1])); + float avgheight = oldHeight + currentHeight; tendency = currentHeight - oldHeight; oldHeight = currentHeight; currentHeight = std::max(waterLevel,terrain->GetVertexGroundLevel(i+kernel[2][0],j+kernel[2][1])); + avgheight += currentHeight; tendency += currentHeight - oldHeight; oldHeight = currentHeight; currentHeight = std::max(waterLevel,terrain->GetVertexGroundLevel(i+kernel[1][0],j+kernel[1][1])); + avgheight += currentHeight; tendency += currentHeight - oldHeight; oldHeight = currentHeight; currentHeight = std::max(waterLevel,terrain->GetVertexGroundLevel(i+kernel[0][0],j+kernel[0][1])); + avgheight += currentHeight; tendency += currentHeight - oldHeight; - float baseLevel = std::max(0.0f,1.0f - (currentHeight-waterLevel)/20.0f); + float baseLevel = std::max(0.0f,1.0f - (avgheight/5.0f-waterLevel)/20.0f); baseLevel *= baseLevel; - tendency /= 10.0f; + tendency /= 15.0f; baseLevel -= tendency; // if the terrain was sloping downwards, increase baselevel. Otherwise reduce. baseLevel = clamp(baseLevel,0.0f,1.0f); // Draw on map. This is pretty slow. - //float width = 3.0f; - float length = 1.2f;//21.0f * (1.0f-baseLevel); - + float length = 35.0f * (1.0f-baseLevel/1.8f); for (float y = 0; y < length; y += 0.6f) - //for (float x = -width*(y+1)/(length+1); x < width*(y+1)/(length+1); x += 0.5f) { - int index = clamp(j - y * windDir.Y,0.0f,(float)(m_MapSize-1))*m_MapSize + clamp(i - y * windDir.X,0.0f,(float)(m_MapSize-1)); - m_WindStrength[index] = (0.5f+baseLevel*0.5f) * (1.0f-y/length) + y/length * 1.0f; + int xx = clamp(i - y * windDir.X,0.0f,(float)(m_MapSize-1)); + int yy = clamp(j - y * windDir.Y,0.0f,(float)(m_MapSize-1)); + Temp[yy*m_MapSize + xx] = Temp[yy*m_MapSize + xx] < (0.0f+baseLevel/1.5f) * (1.0f-y/length) + y/length * 1.0f ? + Temp[yy*m_MapSize + xx] : (0.0f+baseLevel/1.5f) * (1.0f-y/length) + y/length * 1.0f; } } + + int blurKernel[4][2] = { {(int)ceil(windDir.X),(int)ceil(windDir.Y)}, {(int)windDir.X*3,(int)windDir.Y*3}, {(int)ceil(perp.X),(int)ceil(perp.Y)}, {(int)-ceil(perp.X),(int)-ceil(perp.Y)} }; + float blurValue; + for (size_t j = 2; j < m_MapSize-2; ++j) + for (size_t i = 2; i < m_MapSize-2; ++i) + { + blurValue = Temp[(j+blurKernel[0][1])*m_MapSize + i+blurKernel[0][0]]; + blurValue += Temp[(j+blurKernel[0][1])*m_MapSize + i+blurKernel[0][0]]; + blurValue += Temp[(j+blurKernel[0][1])*m_MapSize + i+blurKernel[0][0]]; + blurValue += Temp[(j+blurKernel[0][1])*m_MapSize + i+blurKernel[0][0]]; + m_WindStrength[j*m_MapSize + i] = blurValue * 0.25f; + } + delete[] Temp; } ////////////////////////////////////////////////////////////////////////