diff --git a/src/graphics/core/Shader.cpp b/src/graphics/core/Shader.cpp index 8cc6f2025..1c752ef5a 100644 --- a/src/graphics/core/Shader.cpp +++ b/src/graphics/core/Shader.cpp @@ -186,7 +186,8 @@ void Shader::recompile(const std::vector& defines) { glDeleteProgram(id); id = newProgram; uniformLocations.clear(); - logger.info() << "shader " << id << " has been recompiled"; + logger.debug() << "shader program (" << vertexSource.file << ", " + << fragmentSource.file << ") has been recompiled"; } std::unique_ptr Shader::create( diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 57cc90f24..e59d4392f 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -52,6 +52,7 @@ #include "world/Level.hpp" #include "world/LevelEvents.hpp" #include "world/World.hpp" +#include "debug/Logger.hpp" #include #include @@ -62,9 +63,20 @@ inline constexpr size_t BATCH3D_CAPACITY = 4096; inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000; +static debug::Logger logger("world-renderer"); + bool WorldRenderer::showChunkBorders = false; bool WorldRenderer::showEntitiesDebug = false; +template +static ObserverHandler observe_setting( + ObservableSetting& setting, bool& dirtyShaders +) { + return setting.observe([&dirtyShaders](auto const&) { + dirtyShaders = true; + }); +} + WorldRenderer::WorldRenderer( Engine& engine, LevelFrontend& frontend, Player& player ) @@ -120,10 +132,41 @@ WorldRenderer::WorldRenderer( shadowMapping = std::make_unique(level); debugLines = std::make_unique(level); cloudsRenderer = std::make_unique(); + + keepAlive(observe_setting(settings.graphics.advancedRender, dirtyShaders)); + keepAlive(observe_setting(settings.graphics.shadowsQuality, dirtyShaders)); + keepAlive(observe_setting(settings.graphics.ssao, dirtyShaders)); } WorldRenderer::~WorldRenderer() = default; +void WorldRenderer::refreshSettings() { + Shader* affectedShaders[] { + &assets.require("main"), + &assets.require("entity"), + &assets.require("clouds"), + &assets.require("translucent"), + &assets.require("deferred_lighting").getShader(), + nullptr + }; + + const auto& graphics = engine.getSettings().graphics; + gbufferPipeline = graphics.advancedRender.get(); + + int shadowsQuality = graphics.shadowsQuality.get() * gbufferPipeline; + shadowMapping->setQuality(shadowsQuality); + + std::vector defines; + if (shadowsQuality != 0) defines.emplace_back("ENABLE_SHADOWS"); + if (graphics.ssao.get()) defines.emplace_back("ENABLE_SSAO"); + if (gbufferPipeline) defines.emplace_back("ADVANCED_RENDER"); + + logger.info() << "recompiling shaders due to settings change"; + for (size_t i = 0; affectedShaders[i]; i++) { + affectedShaders[i]->recompile(defines); + } +} + static void setup_weather(Shader& shader, const Weather& weather) { shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity()); shader.uniform1f("u_weatherFogDencity", weather.fogDencity()); @@ -282,33 +325,6 @@ void WorldRenderer::renderLines( } } -void WorldRenderer::refreshSettings(Shader** shaders) { - const auto& graphics = engine.getSettings().graphics; - gbufferPipeline = graphics.advancedRender.get(); - - int shadowsQuality = graphics.shadowsQuality.get() * gbufferPipeline; - shadowMapping->setQuality(shadowsQuality); - - CompileTimeShaderSettings currentSettings { - gbufferPipeline, - shadowsQuality != 0, - graphics.ssao.get() && gbufferPipeline}; - if (prevCTShaderSettings.advancedRender != currentSettings.advancedRender || - prevCTShaderSettings.shadows != currentSettings.shadows || - prevCTShaderSettings.ssao != currentSettings.ssao) { - std::vector defines; - if (currentSettings.shadows) defines.emplace_back("ENABLE_SHADOWS"); - if (currentSettings.ssao) defines.emplace_back("ENABLE_SSAO"); - if (currentSettings.advancedRender) - defines.emplace_back("ADVANCED_RENDER"); - - for (size_t i = 0; shaders[i]; i++) { - shaders[i]->recompile(defines); - } - prevCTShaderSettings = currentSettings; - } -} - void WorldRenderer::update(const Camera& camera, float delta) { timer += delta; weather.update(delta); @@ -327,28 +343,12 @@ void WorldRenderer::renderFrame( const auto& vp = pctx.getViewport(); camera.setAspectRatio(vp.x / static_cast(vp.y)); - - auto& mainShader = assets.require("main"); - auto& entityShader = assets.require("entity"); - auto& cloudsShader = assets.require("clouds"); - auto& translucentShader = assets.require("translucent"); - auto& deferredShader = - assets.require("deferred_lighting").getShader(); - - const auto& settings = engine.getSettings(); - - Shader* affectedShaders[] { - &mainShader, - &entityShader, - &cloudsShader, - &translucentShader, - &deferredShader, - nullptr}; - - refreshSettings(affectedShaders); + if (dirtyShaders) { + refreshSettings(); + dirtyShaders = false; + } const auto& worldInfo = world->getInfo(); - float clouds = weather.clouds(); clouds = glm::max(worldInfo.fog, clouds); float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f; @@ -371,6 +371,7 @@ void WorldRenderer::renderFrame( setupWorldShader(shader, shadowCamera, engine.getSettings(), 0.0f); chunksRenderer->drawShadowsPass(shadowCamera, shader, camera); }); + const auto& settings = engine.getSettings(); { DrawContext wctx = pctx.sub(); postProcessing.use(wctx, gbufferPipeline); @@ -388,10 +389,13 @@ void WorldRenderer::renderFrame( } float fogFactor = calcFogFactor(); if (gbufferPipeline) { + auto& deferredShader = + assets.require("deferred_lighting").getShader(); deferredShader.use(); setupWorldShader(deferredShader, camera, settings, fogFactor); postProcessing.renderDeferredShading(pctx, assets, timer, camera); } + auto& entityShader = assets.require("entity"); { DrawContext ctx = pctx.sub(); ctx.setDepthTest(true); @@ -423,6 +427,7 @@ void WorldRenderer::renderFrame( wctx.useTexture(advanced_pipeline::TARGET_COLOR, nullptr); // Translucent blocks { + auto& translucentShader = assets.require("translucent"); auto sctx = wctx.sub(); sctx.setCullFace(true); translucentShader.use(); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index d472b7b75..e813edb0b 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -6,6 +6,7 @@ #include "presets/WeatherPreset.hpp" #include "world/Weather.hpp" #include "window/Camera.hpp" +#include "util/ObjectsKeeper.hpp" #include #include @@ -37,13 +38,7 @@ class TextsRenderer; class CloudsRenderer; struct EngineSettings; -struct CompileTimeShaderSettings { - bool advancedRender = false; - bool shadows = false; - bool ssao = false; -}; - -class WorldRenderer { +class WorldRenderer final : public util::ObjectsKeeper { public: static bool showChunkBorders; static bool showEntitiesDebug; @@ -90,7 +85,7 @@ private: bool lightsDebug = false; bool gbufferPipeline = false; - CompileTimeShaderSettings prevCTShaderSettings {}; + bool dirtyShaders = false; /// @brief Render block selection lines void renderBlockSelection(); @@ -122,7 +117,7 @@ private: bool hudVisible ); - void refreshSettings(Shader** shaders); + void refreshSettings(); float calcFogFactor() const; public: