simplify settings-based shaders recompilation

This commit is contained in:
MihailRis 2026-06-18 22:12:22 +03:00
parent 3fc1097217
commit af71d5b674
3 changed files with 58 additions and 57 deletions

View file

@ -186,7 +186,8 @@ void Shader::recompile(const std::vector<std::string>& defines) {
glDeleteProgram(id); glDeleteProgram(id);
id = newProgram; id = newProgram;
uniformLocations.clear(); uniformLocations.clear();
logger.info() << "shader " << id << " has been recompiled"; logger.debug() << "shader program (" << vertexSource.file << ", "
<< fragmentSource.file << ") has been recompiled";
} }
std::unique_ptr<Shader> Shader::create( std::unique_ptr<Shader> Shader::create(

View file

@ -52,6 +52,7 @@
#include "world/Level.hpp" #include "world/Level.hpp"
#include "world/LevelEvents.hpp" #include "world/LevelEvents.hpp"
#include "world/World.hpp" #include "world/World.hpp"
#include "debug/Logger.hpp"
#include <assert.h> #include <assert.h>
#include <algorithm> #include <algorithm>
@ -62,9 +63,20 @@
inline constexpr size_t BATCH3D_CAPACITY = 4096; inline constexpr size_t BATCH3D_CAPACITY = 4096;
inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000; inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000;
static debug::Logger logger("world-renderer");
bool WorldRenderer::showChunkBorders = false; bool WorldRenderer::showChunkBorders = false;
bool WorldRenderer::showEntitiesDebug = false; bool WorldRenderer::showEntitiesDebug = false;
template <typename T>
static ObserverHandler observe_setting(
ObservableSetting<T>& setting, bool& dirtyShaders
) {
return setting.observe([&dirtyShaders](auto const&) {
dirtyShaders = true;
});
}
WorldRenderer::WorldRenderer( WorldRenderer::WorldRenderer(
Engine& engine, LevelFrontend& frontend, Player& player Engine& engine, LevelFrontend& frontend, Player& player
) )
@ -120,10 +132,41 @@ WorldRenderer::WorldRenderer(
shadowMapping = std::make_unique<Shadows>(level); shadowMapping = std::make_unique<Shadows>(level);
debugLines = std::make_unique<DebugLinesRenderer>(level); debugLines = std::make_unique<DebugLinesRenderer>(level);
cloudsRenderer = std::make_unique<CloudsRenderer>(); cloudsRenderer = std::make_unique<CloudsRenderer>();
keepAlive(observe_setting(settings.graphics.advancedRender, dirtyShaders));
keepAlive(observe_setting(settings.graphics.shadowsQuality, dirtyShaders));
keepAlive(observe_setting(settings.graphics.ssao, dirtyShaders));
} }
WorldRenderer::~WorldRenderer() = default; WorldRenderer::~WorldRenderer() = default;
void WorldRenderer::refreshSettings() {
Shader* affectedShaders[] {
&assets.require<Shader>("main"),
&assets.require<Shader>("entity"),
&assets.require<Shader>("clouds"),
&assets.require<Shader>("translucent"),
&assets.require<PostEffect>("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<std::string> 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) { static void setup_weather(Shader& shader, const Weather& weather) {
shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity()); shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity());
shader.uniform1f("u_weatherFogDencity", weather.fogDencity()); 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<std::string> 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) { void WorldRenderer::update(const Camera& camera, float delta) {
timer += delta; timer += delta;
weather.update(delta); weather.update(delta);
@ -327,28 +343,12 @@ void WorldRenderer::renderFrame(
const auto& vp = pctx.getViewport(); const auto& vp = pctx.getViewport();
camera.setAspectRatio(vp.x / static_cast<float>(vp.y)); camera.setAspectRatio(vp.x / static_cast<float>(vp.y));
if (dirtyShaders) {
auto& mainShader = assets.require<Shader>("main"); refreshSettings();
auto& entityShader = assets.require<Shader>("entity"); dirtyShaders = false;
auto& cloudsShader = assets.require<Shader>("clouds"); }
auto& translucentShader = assets.require<Shader>("translucent");
auto& deferredShader =
assets.require<PostEffect>("deferred_lighting").getShader();
const auto& settings = engine.getSettings();
Shader* affectedShaders[] {
&mainShader,
&entityShader,
&cloudsShader,
&translucentShader,
&deferredShader,
nullptr};
refreshSettings(affectedShaders);
const auto& worldInfo = world->getInfo(); const auto& worldInfo = world->getInfo();
float clouds = weather.clouds(); float clouds = weather.clouds();
clouds = glm::max(worldInfo.fog, clouds); clouds = glm::max(worldInfo.fog, clouds);
float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f; 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); setupWorldShader(shader, shadowCamera, engine.getSettings(), 0.0f);
chunksRenderer->drawShadowsPass(shadowCamera, shader, camera); chunksRenderer->drawShadowsPass(shadowCamera, shader, camera);
}); });
const auto& settings = engine.getSettings();
{ {
DrawContext wctx = pctx.sub(); DrawContext wctx = pctx.sub();
postProcessing.use(wctx, gbufferPipeline); postProcessing.use(wctx, gbufferPipeline);
@ -388,10 +389,13 @@ void WorldRenderer::renderFrame(
} }
float fogFactor = calcFogFactor(); float fogFactor = calcFogFactor();
if (gbufferPipeline) { if (gbufferPipeline) {
auto& deferredShader =
assets.require<PostEffect>("deferred_lighting").getShader();
deferredShader.use(); deferredShader.use();
setupWorldShader(deferredShader, camera, settings, fogFactor); setupWorldShader(deferredShader, camera, settings, fogFactor);
postProcessing.renderDeferredShading(pctx, assets, timer, camera); postProcessing.renderDeferredShading(pctx, assets, timer, camera);
} }
auto& entityShader = assets.require<Shader>("entity");
{ {
DrawContext ctx = pctx.sub(); DrawContext ctx = pctx.sub();
ctx.setDepthTest(true); ctx.setDepthTest(true);
@ -423,6 +427,7 @@ void WorldRenderer::renderFrame(
wctx.useTexture(advanced_pipeline::TARGET_COLOR, nullptr); wctx.useTexture(advanced_pipeline::TARGET_COLOR, nullptr);
// Translucent blocks // Translucent blocks
{ {
auto& translucentShader = assets.require<Shader>("translucent");
auto sctx = wctx.sub(); auto sctx = wctx.sub();
sctx.setCullFace(true); sctx.setCullFace(true);
translucentShader.use(); translucentShader.use();

View file

@ -6,6 +6,7 @@
#include "presets/WeatherPreset.hpp" #include "presets/WeatherPreset.hpp"
#include "world/Weather.hpp" #include "world/Weather.hpp"
#include "window/Camera.hpp" #include "window/Camera.hpp"
#include "util/ObjectsKeeper.hpp"
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -37,13 +38,7 @@ class TextsRenderer;
class CloudsRenderer; class CloudsRenderer;
struct EngineSettings; struct EngineSettings;
struct CompileTimeShaderSettings { class WorldRenderer final : public util::ObjectsKeeper {
bool advancedRender = false;
bool shadows = false;
bool ssao = false;
};
class WorldRenderer {
public: public:
static bool showChunkBorders; static bool showChunkBorders;
static bool showEntitiesDebug; static bool showEntitiesDebug;
@ -90,7 +85,7 @@ private:
bool lightsDebug = false; bool lightsDebug = false;
bool gbufferPipeline = false; bool gbufferPipeline = false;
CompileTimeShaderSettings prevCTShaderSettings {}; bool dirtyShaders = false;
/// @brief Render block selection lines /// @brief Render block selection lines
void renderBlockSelection(); void renderBlockSelection();
@ -122,7 +117,7 @@ private:
bool hudVisible bool hudVisible
); );
void refreshSettings(Shader** shaders); void refreshSettings();
float calcFogFactor() const; float calcFogFactor() const;
public: public: