diff --git a/source/renderer/RenderingOptions.cpp b/source/renderer/RenderingOptions.cpp index 4b9e8268a9..68cba0e537 100644 --- a/source/renderer/RenderingOptions.cpp +++ b/source/renderer/RenderingOptions.cpp @@ -29,6 +29,7 @@ #include "renderer/PostprocManager.h" #include "renderer/SceneRenderer.h" #include "renderer/ShadowMap.h" +#include "renderer/WaterManager.h" CRenderingOptions g_RenderingOptions; @@ -197,11 +198,35 @@ void CRenderingOptions::ReadConfigAndSetupHooks() m_ConfigHooks->Setup("smoothlos", m_SmoothLOS); - m_ConfigHooks->Setup("watereffects", m_WaterEffects); - m_ConfigHooks->Setup("waterfancyeffects", m_WaterFancyEffects); + m_ConfigHooks->Setup("watereffects", [this]() { + bool enabled; + CFG_GET_VAL("watereffects", enabled); + SetWaterEffects(enabled); + if (CRenderer::IsInitialised()) + g_Renderer.GetSceneRenderer().GetWaterManager().RecreateOrLoadTexturesIfNeeded(); + }); + m_ConfigHooks->Setup("waterfancyeffects", [this]() { + bool enabled; + CFG_GET_VAL("waterfancyeffects", enabled); + SetWaterFancyEffects(enabled); + if (CRenderer::IsInitialised()) + g_Renderer.GetSceneRenderer().GetWaterManager().RecreateOrLoadTexturesIfNeeded(); + }); m_ConfigHooks->Setup("waterrealdepth", m_WaterRealDepth); - m_ConfigHooks->Setup("waterrefraction", m_WaterRefraction); - m_ConfigHooks->Setup("waterreflection", m_WaterReflection); + m_ConfigHooks->Setup("waterrefraction", [this]() { + bool enabled; + CFG_GET_VAL("waterrefraction", enabled); + SetWaterRefraction(enabled); + if (CRenderer::IsInitialised()) + g_Renderer.GetSceneRenderer().GetWaterManager().RecreateOrLoadTexturesIfNeeded(); + }); + m_ConfigHooks->Setup("waterreflection", [this]() { + bool enabled; + CFG_GET_VAL("waterreflection", enabled); + SetWaterReflection(enabled); + if (CRenderer::IsInitialised()) + g_Renderer.GetSceneRenderer().GetWaterManager().RecreateOrLoadTexturesIfNeeded(); + }); m_ConfigHooks->Setup("particles", m_Particles); m_ConfigHooks->Setup("fog", [this]() { diff --git a/source/renderer/SceneRenderer.cpp b/source/renderer/SceneRenderer.cpp index 3784775d8a..f9bffbdbfe 100644 --- a/source/renderer/SceneRenderer.cpp +++ b/source/renderer/SceneRenderer.cpp @@ -273,7 +273,7 @@ void CSceneRenderer::Resize(int UNUSED(width), int UNUSED(height)) // need to recreate the shadow map object to resize the shadow texture m->shadow.RecreateTexture(); - m->waterManager.Resize(); + m->waterManager.RecreateOrLoadTexturesIfNeeded(); } void CSceneRenderer::BeginFrame() diff --git a/source/renderer/WaterManager.cpp b/source/renderer/WaterManager.cpp index ee3d29e91c..c14deaeed9 100644 --- a/source/renderer/WaterManager.cpp +++ b/source/renderer/WaterManager.cpp @@ -155,12 +155,6 @@ int WaterManager::LoadWaterTextures() m_RenderWater = true; - if (!WillRenderFancyWater()) - return 0; - -#if CONFIG2_GLES -#warning Fix WaterManager::LoadWaterTextures on GLES -#else // Load normalmaps (for fancy water) ReloadWaterNormalTextures(); @@ -184,88 +178,120 @@ int WaterManager::LoadWaterTextures() m_FoamTex = texture; } - // Use screen-sized textures for minimum artifacts. - m_RefTextureSize = round_up_to_pow2(g_Renderer.GetHeight()); + RecreateOrLoadTexturesIfNeeded(); - Renderer::Backend::GL::CDevice* backendDevice = g_VideoMode.GetBackendDevice(); - - // Create reflection texture - m_ReflectionTexture = backendDevice->CreateTexture2D("WaterReflectionTexture", - Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, - Renderer::Backend::Sampler::MakeDefaultSampler( - Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); - - // Create refraction texture - m_RefractionTexture = backendDevice->CreateTexture2D("WaterRefractionTexture", - Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, - Renderer::Backend::Sampler::MakeDefaultSampler( - Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); - - // Create depth textures - m_ReflFboDepthTexture = backendDevice->CreateTexture2D("WaterReflectionDepthTexture", - Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize, - Renderer::Backend::Sampler::MakeDefaultSampler( - Renderer::Backend::Sampler::Filter::NEAREST, - Renderer::Backend::Sampler::AddressMode::REPEAT)); - - m_RefrFboDepthTexture = backendDevice->CreateTexture2D("WaterRefractionDepthTexture", - Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize, - Renderer::Backend::Sampler::MakeDefaultSampler( - Renderer::Backend::Sampler::Filter::NEAREST, - Renderer::Backend::Sampler::AddressMode::REPEAT)); - - Resize(); - - // Create the water framebuffers - - m_ReflectionFramebuffer = backendDevice->CreateFramebuffer("ReflectionFramebuffer", - m_ReflectionTexture.get(), m_ReflFboDepthTexture.get(), CColor(0.5f, 0.5f, 1.0f, 0.0f)); - if (!m_ReflectionFramebuffer) - { - g_RenderingOptions.SetWaterReflection(false); - UpdateQuality(); - } - - m_RefractionFramebuffer = backendDevice->CreateFramebuffer("RefractionFramebuffer", - m_RefractionTexture.get(), m_RefrFboDepthTexture.get(), CColor(1.0f, 0.0f, 0.0f, 0.0f)); - if (!m_RefractionFramebuffer) - { - g_RenderingOptions.SetWaterRefraction(false); - UpdateQuality(); - } - - m_FancyEffectsFramebuffer = backendDevice->CreateFramebuffer("FancyEffectsFramebuffer", - m_FancyTexture.get(), m_FancyTextureDepth.get()); - if (!m_FancyEffectsFramebuffer) - { - g_RenderingOptions.SetWaterRefraction(false); - UpdateQuality(); - } -#endif return 0; } - -/////////////////////////////////////////////////////////////////// -// Resize: Updates the fancy water textures. -void WaterManager::Resize() +void WaterManager::RecreateOrLoadTexturesIfNeeded() { Renderer::Backend::GL::CDevice* backendDevice = g_VideoMode.GetBackendDevice(); - // Create the Fancy Effects texture - m_FancyTexture = backendDevice->CreateTexture2D("WaterFancyTexture", - Renderer::Backend::Format::R8G8B8A8_UNORM, g_Renderer.GetWidth(), g_Renderer.GetHeight(), - Renderer::Backend::Sampler::MakeDefaultSampler( - Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::REPEAT)); + // Use screen-sized textures for minimum artifacts. + const size_t newRefTextureSize = round_up_to_pow2(g_Renderer.GetHeight()); - m_FancyTextureDepth = backendDevice->CreateTexture2D("WaterFancyDepthTexture", - Renderer::Backend::Format::D32, g_Renderer.GetWidth(), g_Renderer.GetHeight(), - Renderer::Backend::Sampler::MakeDefaultSampler( - Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::REPEAT)); + if (m_RefTextureSize != newRefTextureSize) + { + m_ReflectionFramebuffer.reset(); + m_ReflectionTexture.reset(); + m_ReflFboDepthTexture.reset(); + + m_RefractionFramebuffer.reset(); + m_RefractionTexture.reset(); + m_RefrFboDepthTexture.reset(); + + m_RefTextureSize = newRefTextureSize; + } + + // Create reflection textures. + const bool needsReflectionTextures = + g_RenderingOptions.GetWaterEffects() && + g_RenderingOptions.GetWaterReflection(); + if (needsReflectionTextures && !m_ReflectionTexture) + { + m_ReflectionTexture = backendDevice->CreateTexture2D("WaterReflectionTexture", + Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); + + m_ReflFboDepthTexture = backendDevice->CreateTexture2D("WaterReflectionDepthTexture", + Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize, + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::NEAREST, + Renderer::Backend::Sampler::AddressMode::REPEAT)); + + m_ReflectionFramebuffer = backendDevice->CreateFramebuffer("ReflectionFramebuffer", + m_ReflectionTexture.get(), m_ReflFboDepthTexture.get(), CColor(0.5f, 0.5f, 1.0f, 0.0f)); + if (!m_ReflectionFramebuffer) + { + g_RenderingOptions.SetWaterReflection(false); + UpdateQuality(); + } + } + + // Create refraction textures. + const bool needsRefractionTextures = + g_RenderingOptions.GetWaterEffects() && + g_RenderingOptions.GetWaterRefraction(); + if (needsRefractionTextures && !m_RefractionTexture) + { + m_RefractionTexture = backendDevice->CreateTexture2D("WaterRefractionTexture", + Renderer::Backend::Format::R8G8B8A8_UNORM, m_RefTextureSize, m_RefTextureSize, + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); + + m_RefrFboDepthTexture = backendDevice->CreateTexture2D("WaterRefractionDepthTexture", + Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize, + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::NEAREST, + Renderer::Backend::Sampler::AddressMode::REPEAT)); + + m_RefractionFramebuffer = backendDevice->CreateFramebuffer("RefractionFramebuffer", + m_RefractionTexture.get(), m_RefrFboDepthTexture.get(), CColor(1.0f, 0.0f, 0.0f, 0.0f)); + if (!m_RefractionFramebuffer) + { + g_RenderingOptions.SetWaterRefraction(false); + UpdateQuality(); + } + } + + const uint32_t newWidth = static_cast(g_Renderer.GetWidth()); + const uint32_t newHeight = static_cast(g_Renderer.GetHeight()); + if (m_FancyTexture && (m_FancyTexture->GetWidth() != newWidth || m_FancyTexture->GetHeight() != newHeight)) + { + m_FancyEffectsFramebuffer.reset(); + m_FancyTexture.reset(); + m_FancyTextureDepth.reset(); + } + + // Create the Fancy Effects textures. + const bool needsFancyTextures = + g_RenderingOptions.GetWaterEffects() && + g_RenderingOptions.GetWaterFancyEffects(); + if (needsFancyTextures && !m_FancyTexture) + { + m_FancyTexture = backendDevice->CreateTexture2D("WaterFancyTexture", + Renderer::Backend::Format::R8G8B8A8_UNORM, g_Renderer.GetWidth(), g_Renderer.GetHeight(), + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::REPEAT)); + + m_FancyTextureDepth = backendDevice->CreateTexture2D("WaterFancyDepthTexture", + Renderer::Backend::Format::D32, g_Renderer.GetWidth(), g_Renderer.GetHeight(), + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::REPEAT)); + + m_FancyEffectsFramebuffer = backendDevice->CreateFramebuffer("FancyEffectsFramebuffer", + m_FancyTexture.get(), m_FancyTextureDepth.get()); + if (!m_FancyEffectsFramebuffer) + { + g_RenderingOptions.SetWaterRefraction(false); + UpdateQuality(); + } + } } void WaterManager::ReloadWaterNormalTextures() diff --git a/source/renderer/WaterManager.h b/source/renderer/WaterManager.h index 4dd6bbfec2..e4b01d8d2a 100644 --- a/source/renderer/WaterManager.h +++ b/source/renderer/WaterManager.h @@ -139,10 +139,9 @@ public: int LoadWaterTextures(); /** - * Resize: Updates the fancy water textures so that water will render correctly - * with fancy water. + * Recreates/loads needed water textures. */ - void Resize(); + void RecreateOrLoadTexturesIfNeeded(); /** * ReloadWaterNormalTextures: Reload the normal textures so that changing