diff --git a/res/layouts/pages/settings_graphics.xml.lua b/res/layouts/pages/settings_graphics.xml.lua index 8a479a1c6..c4503e52c 100644 --- a/res/layouts/pages/settings_graphics.xml.lua +++ b/res/layouts/pages/settings_graphics.xml.lua @@ -41,4 +41,5 @@ function on_open() create_setting("graphics.fog-curve", "Fog Curve", 0.1) create_setting("graphics.gamma", "Gamma", 0.05, "", "graphics.gamma.tooltip") create_checkbox("graphics.backlight", "Backlight", "graphics.backlight.tooltip") + create_checkbox("graphics.dense-render", "Dense blocks render", "graphics.dense-render.tooltip") end diff --git a/res/texts/en_US.txt b/res/texts/en_US.txt index c19fe00a8..e9b238970 100644 --- a/res/texts/en_US.txt +++ b/res/texts/en_US.txt @@ -16,6 +16,7 @@ devtools.traceback=Traceback (most recent call first) # Tooltips graphics.gamma.tooltip=Lighting brightness curve graphics.backlight.tooltip=Backlight to prevent total darkness +graphics.dense-render.tooltip=Enables transparency in blocks like leaves # settings settings.Controls Search Mode=Search by attached button name diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index ae591042a..e78b5f729 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -28,6 +28,7 @@ pack.remove-confirm=Удалить весь поставляемый паком/ # Подсказки graphics.gamma.tooltip=Кривая яркости освещения graphics.backlight.tooltip=Подсветка, предотвращающая полную темноту +graphics.dense-render.tooltip=Включает прозрачность блоков, таких как листья. # Меню menu.Apply=Применить @@ -67,6 +68,7 @@ world.delete-confirm=Удалить мир безвозвратно? # Настройки settings.Ambient=Фон settings.Backlight=Подсветка +settings.Dense blocks render=Плотный рендер блоков settings.Camera Shaking=Тряска Камеры settings.Camera Inertia=Инерция Камеры settings.Camera FOV Effects=Эффекты поля зрения diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index d2a85f6a1..fe251a11e 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -68,6 +68,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { builder.section("graphics"); builder.add("fog-curve", &settings.graphics.fogCurve); builder.add("backlight", &settings.graphics.backlight); + builder.add("dense-render", &settings.graphics.denseRender); builder.add("gamma", &settings.graphics.gamma); builder.add("frustum-culling", &settings.graphics.frustumCulling); builder.add("skybox-resolution", &settings.graphics.skyboxResolution); diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp index c6ba4e1c3..844fd4e6d 100644 --- a/src/frontend/ContentGfxCache.cpp +++ b/src/frontend/ContentGfxCache.cpp @@ -6,53 +6,71 @@ #include "assets/Assets.hpp" #include "content/Content.hpp" #include "content/ContentPack.hpp" -#include "core_defs.hpp" #include "graphics/core/Atlas.hpp" #include "maths/UVRegion.hpp" #include "voxels/Block.hpp" +#include "core_defs.hpp" +#include "settings.hpp" -ContentGfxCache::ContentGfxCache(const Content* content, const Assets& assets) - : content(content) { - auto indices = content->getIndices(); - sideregions = std::make_unique(indices->blocks.count() * 6); - const auto& atlas = assets.require("blocks"); - const auto& blocks = indices->blocks.getIterable(); - for (blockid_t i = 0; i < blocks.size(); i++) { - auto def = blocks[i]; - for (uint side = 0; side < 6; side++) { - const std::string& tex = def->textureFaces[side]; - if (atlas.has(tex)) { - sideregions[i * 6 + side] = atlas.get(tex); - } else if (atlas.has(TEXTURE_NOTFOUND)) { - sideregions[i * 6 + side] = atlas.get(TEXTURE_NOTFOUND); - } +ContentGfxCache::ContentGfxCache( + const Content& content, + const Assets& assets, + const GraphicsSettings& settings +) + : content(content), assets(assets), settings(settings) { + refresh(); +} + +void ContentGfxCache::refresh(const Block& def, const Atlas& atlas) { + for (uint side = 0; side < 6; side++) { + std::string tex = def.textureFaces[side]; + if (def.culling == CullingMode::OPTIONAL && + !settings.denseRender.get() && atlas.has(tex + "_opaque")) { + tex = tex + "_opaque"; } - if (def->model == BlockModel::custom) { - auto model = assets.require(def->modelName); - // temporary dirty fix tbh - if (def->modelName.find(':') == std::string::npos) { - for (auto& mesh : model.meshes) { - size_t pos = mesh.texture.find(':'); - if (pos == std::string::npos) { - continue; - } - if (auto region = atlas.getIf(mesh.texture.substr(pos+1))) { - for (auto& vertex : mesh.vertices) { - vertex.uv = region->apply(vertex.uv); - } + if (atlas.has(tex)) { + sideregions[def.rt.id * 6 + side] = atlas.get(tex); + } else if (atlas.has(TEXTURE_NOTFOUND)) { + sideregions[def.rt.id * 6 + side] = atlas.get(TEXTURE_NOTFOUND); + } + } + if (def.model == BlockModel::custom) { + auto model = assets.require(def.modelName); + // temporary dirty fix tbh + if (def.modelName.find(':') == std::string::npos) { + for (auto& mesh : model.meshes) { + size_t pos = mesh.texture.find(':'); + if (pos == std::string::npos) { + continue; + } + if (auto region = atlas.getIf(mesh.texture.substr(pos+1))) { + for (auto& vertex : mesh.vertices) { + vertex.uv = region->apply(vertex.uv); } } } - models[def->rt.id] = std::move(model); } + models[def.rt.id] = std::move(model); + } +} + +void ContentGfxCache::refresh() { + auto indices = content.getIndices(); + sideregions = std::make_unique(indices->blocks.count() * 6); + const auto& atlas = assets.require("blocks"); + + const auto& blocks = indices->blocks.getIterable(); + for (blockid_t i = 0; i < blocks.size(); i++) { + auto def = blocks[i]; + refresh(*def, atlas); } } ContentGfxCache::~ContentGfxCache() = default; const Content* ContentGfxCache::getContent() const { - return content; + return &content; } const model::Model& ContentGfxCache::getModel(blockid_t id) const { diff --git a/src/frontend/ContentGfxCache.hpp b/src/frontend/ContentGfxCache.hpp index 96d46ea59..739d6c1d4 100644 --- a/src/frontend/ContentGfxCache.hpp +++ b/src/frontend/ContentGfxCache.hpp @@ -10,19 +10,29 @@ class Content; class Assets; +class Atlas; +struct Block; struct UVRegion; +struct GraphicsSettings; namespace model { struct Model; } class ContentGfxCache { - const Content* content; + const Content& content; + const Assets& assets; + const GraphicsSettings& settings; + // array of block sides uv regions (6 per block) std::unique_ptr sideregions; std::unordered_map models; public: - ContentGfxCache(const Content* content, const Assets& assets); + ContentGfxCache( + const Content& content, + const Assets& assets, + const GraphicsSettings& settings + ); ~ContentGfxCache(); inline const UVRegion& getRegion(blockid_t id, int side) const { @@ -32,4 +42,8 @@ class ContentGfxCache { const model::Model& getModel(blockid_t id) const; const Content* getContent() const; + + void refresh(const Block& block, const Atlas& atlas); + + void refresh(); }; diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index 79784375d..d3cbb9e8d 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -14,12 +14,17 @@ #include "world/Level.hpp" LevelFrontend::LevelFrontend( - Player* currentPlayer, LevelController* controller, Assets& assets -) : level(*controller->getLevel()), - controller(controller), - assets(assets), - contentCache(std::make_unique(level.content, assets)) -{ + Player* currentPlayer, + LevelController* controller, + Assets& assets, + const EngineSettings& settings +) + : level(*controller->getLevel()), + controller(controller), + assets(assets), + contentCache(std::make_unique( + *level.content, assets, settings.graphics + )) { assets.store( BlocksPreview::build( *contentCache, assets, *level.content->getIndices() @@ -98,6 +103,10 @@ const Assets& LevelFrontend::getAssets() const { return assets; } +ContentGfxCache& LevelFrontend::getContentGfxCache() { + return *contentCache; +} + const ContentGfxCache& LevelFrontend::getContentGfxCache() const { return *contentCache; } diff --git a/src/frontend/LevelFrontend.hpp b/src/frontend/LevelFrontend.hpp index 163fc678f..b53d267a3 100644 --- a/src/frontend/LevelFrontend.hpp +++ b/src/frontend/LevelFrontend.hpp @@ -7,6 +7,7 @@ class Assets; class Player; class ContentGfxCache; class LevelController; +struct EngineSettings; class LevelFrontend { Level& level; @@ -14,12 +15,18 @@ class LevelFrontend { const Assets& assets; std::unique_ptr contentCache; public: - LevelFrontend(Player* currentPlayer, LevelController* controller, Assets& assets); + LevelFrontend( + Player* currentPlayer, + LevelController* controller, + Assets& assets, + const EngineSettings& settings + ); ~LevelFrontend(); Level& getLevel(); const Level& getLevel() const; const Assets& getAssets() const; const ContentGfxCache& getContentGfxCache() const; + ContentGfxCache& getContentGfxCache(); LevelController* getController() const; }; diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 34d1db678..e38b3beca 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -17,6 +17,7 @@ #include "graphics/render/Decorator.hpp" #include "graphics/ui/elements/Menu.hpp" #include "graphics/ui/GUI.hpp" +#include "frontend/ContentGfxCache.hpp" #include "logic/LevelController.hpp" #include "logic/scripting/scripting_hud.hpp" #include "util/stringutil.hpp" @@ -42,7 +43,7 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr levelPtr) controller = std::make_unique(engine, std::move(levelPtr)); frontend = std::make_unique( - controller->getPlayer(), controller.get(), assets + controller->getPlayer(), controller.get(), assets, settings ); worldRenderer = std::make_unique( engine, *frontend, controller->getPlayer() @@ -57,6 +58,11 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr levelPtr) controller->getLevel()->chunks->saveAndClear(); worldRenderer->clear(); })); + keepAlive(settings.graphics.denseRender.observe([=](bool) { + controller->getLevel()->chunks->saveAndClear(); + worldRenderer->clear(); + frontend->getContentGfxCache().refresh(); + })); keepAlive(settings.camera.fov.observe([=](double value) { controller->getPlayer()->fpCamera->setFov(glm::radians(value)); })); diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index f1e8001f1..56f1c4e2f 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -8,9 +8,6 @@ #include "voxels/Chunks.hpp" #include "lighting/Lightmap.hpp" #include "frontend/ContentGfxCache.hpp" -#include "settings.hpp" - -#include const glm::vec3 BlocksRenderer::SUN_VECTOR (0.411934f, 0.863868f, -0.279161f); diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index d27f681bb..c652b6a08 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -13,6 +13,7 @@ #include "graphics/core/MeshData.hpp" #include "maths/util.hpp" #include "commons.hpp" +#include "settings.hpp" class Content; class Mesh; @@ -22,7 +23,6 @@ class Chunks; class VoxelsVolume; class Chunks; class ContentGfxCache; -struct EngineSettings; struct UVRegion; class BlocksRenderer { @@ -129,8 +129,10 @@ class BlocksRenderer { if (((block.drawGroup != def.drawGroup) && block.drawGroup) || !block.rt.solid) { return true; } - if (def.culling == CullingMode::DISABLED || - (def.culling == CullingMode::OPTIONAL && id == def.rt.id)) { + if ((def.culling == CullingMode::DISABLED || + (def.culling == CullingMode::OPTIONAL && + settings.graphics.denseRender.get())) && + id == def.rt.id) { return true; } return !id; diff --git a/src/settings.hpp b/src/settings.hpp index b0eee035e..48d72b272 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -63,16 +63,22 @@ struct GraphicsSettings { NumberSetting gamma {1.0f, 0.4f, 1.0f}; /// @brief Enable blocks backlight to prevent complete darkness FlagSetting backlight {true}; + /// @brief Disable culling with 'optional' mode + FlagSetting denseRender {true}; /// @brief Enable chunks frustum culling FlagSetting frustumCulling {true}; + /// @brief Skybox texture face resolution IntegerSetting skyboxResolution {64 + 32, 64, 128}; + /// @brief Chunk renderer vertices buffer capacity IntegerSetting chunkMaxVertices {200'000, 0, 4'000'000}; + /// @brief Limit of chunk renderers count IntegerSetting chunkMaxRenderers {6, -4, 32}; }; struct DebugSettings { /// @brief Turns off chunks saving/loading FlagSetting generatorTestMode {false}; + /// @brief Write lights cache FlagSetting doWriteLights {true}; };