diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 24a7955b8..0ed4157e4 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -8,18 +8,16 @@ #include "graphics/core/DrawContext.hpp" #include "graphics/render/MainBatch.hpp" #include "lighting/Lightmap.hpp" -#include "objects/Player.hpp" #include "voxels/Block.hpp" #include "voxels/Chunks.hpp" -#include "world/Level.hpp" #include BlockWrapsRenderer::BlockWrapsRenderer( - const Assets& assets, const Level& level, const Chunks& chunks + const Assets& assets, const Content& content, const Chunks& chunks ) : assets(assets), - level(level), + content(content), chunks(chunks), batch(std::make_unique(1024)) { } @@ -43,16 +41,14 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { } const voxel* vox = chunks.get(wrapper.position); - if (vox == nullptr || vox->id == BLOCK_VOID) { + if (vox == nullptr || vox->id == BLOCK_AIR) { return; } // one frame can be invalid due to texture change but ok - const auto& def = - level.content.getIndices()->blocks.require(vox->id); + const auto& def = content.getIndices()->blocks.require(vox->id); if (wrapper.modelType != def.getModel(vox->state.userbits).type) { wrapper.dirtySides = 0xFF; - refreshWrapper(wrapper); } glm::vec4 light(1, 1, 1, 0); if (wrapper.emission < 1.0f) { @@ -95,6 +91,8 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { } void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { + clearOrder(&wrapper); + for (int i = 0; i < 6; i++) { if ((wrapper.cullingBits & (1 << i)) == 0) { continue; @@ -104,15 +102,19 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { wrapper.texRegions[i] = texRegion; wrapper.uvRegions[i] = texRegion.region; - renderOrder.insert({texRegion.texture, &wrapper}); + auto& wrappers = renderOrder[texRegion.texture]; + if (std::find(wrappers.begin(), wrappers.end(), &wrapper) == + wrappers.end()) { + wrappers.emplace_back(&wrapper); + } } wrapper.dirtySides = 0x0; const voxel* vox = chunks.get(wrapper.position); - if (vox == nullptr || vox->id == BLOCK_VOID) { + if (vox == nullptr || vox->id == BLOCK_AIR) { return; } - const auto& def = level.content.getIndices()->blocks.require(vox->id); + const auto& def = content.getIndices()->blocks.require(vox->id); wrapper.modelType = def.getModel(vox->state.userbits).type; switch (wrapper.modelType) { case BlockModelType::AABB: { @@ -133,7 +135,7 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { } } -void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { +void BlockWrapsRenderer::draw(const DrawContext& pctx) { auto ctx = pctx.sub(); auto& shader = assets.require("entity"); @@ -146,9 +148,11 @@ void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { } } - for (const auto& [texture, wrapper] : renderOrder) { + for (const auto& [texture, wrappersArray] : renderOrder) { batch->setTexture(texture); - draw(*wrapper, texture); + for (auto wrapper : wrappersArray) { + draw(*wrapper, texture); + } } batch->flush(); } @@ -181,15 +185,21 @@ void BlockWrapsRenderer::remove(u64id_t id) { if (found == wrappers.end()) { return; } - auto wrapper = std::move(found->second); + clearOrder(found->second.get()); wrappers.erase(id); +} +void BlockWrapsRenderer::clearOrder(const BlockWrapper* const wrapper) { auto it = renderOrder.begin(); while (it != renderOrder.end()) { - if (it->second == wrapper.get()) { + it->second.erase( + std::remove(it->second.begin(), it->second.end(), wrapper), + it->second.end() + ); + if (it->second.empty()) { it = renderOrder.erase(it); } else { ++it; } } -} +} \ No newline at end of file diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index f19bf6b66..632fe90cb 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -9,13 +9,9 @@ #include #include #include -#include -#include class Assets; -class Player; -class Level; -struct voxel; +class Content; class Chunks; class Texture; class DrawContext; @@ -36,24 +32,25 @@ struct BlockWrapper { class BlockWrapsRenderer { const Assets& assets; - const Level& level; + const Content& content; const Chunks& chunks; std::unique_ptr batch; - std::multimap renderOrder; + std::unordered_map> renderOrder; std::unordered_map> wrappers; u64id_t nextWrapper = 1; void draw(BlockWrapper& wrapper, const Texture* texture); void refreshWrapper(BlockWrapper& wrapper); + void clearOrder(const BlockWrapper* const wrapper); public: BlockWrapsRenderer( - const Assets& assets, const Level& level, const Chunks& chunks + const Assets& assets, const Content& content, const Chunks& chunks ); ~BlockWrapsRenderer(); - void draw(const DrawContext& ctx, const Player& player); + void draw(const DrawContext& ctx); u64id_t add( const glm::ivec3& position, diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 4157eeb98..e1f683b96 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -94,9 +94,9 @@ WorldRenderer::WorldRenderer( assets, level, *player.chunks, engine.getSettings().graphics )), texts(std::make_unique(*batch3d, assets, *frustumCulling)), - blockWraps( - std::make_unique(assets, level, *player.chunks) - ) { + blockWraps(std::make_unique( + assets, level.content, *player.chunks + )) { auto& settings = engine.getSettings(); level.events->listen( LevelEventType::CHUNK_HIDDEN, @@ -214,7 +214,7 @@ void WorldRenderer::renderOpaque( setupWorldShader(shader, camera, settings, fogFactor); chunksRenderer->drawChunks(camera, shader); - blockWraps->draw(ctx, player); + blockWraps->draw(ctx); int cloudsQuality = settings.graphics.cloudsQuality.get(); if (cloudsQuality > 0) { diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index 5b28f7dbb..084dd6b8b 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -34,10 +34,14 @@ static int l_set_pos(lua::State* L) { static int l_set_texture(lua::State* L) { if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { + const char* newTexture = lua::require_string(L, 2); + for (int i = 0; i < wrapper->textureFaces.size(); i++) { - wrapper->textureFaces[i] = lua::require_string(L, 2); + if (wrapper->textureFaces[i] != newTexture) { + wrapper->textureFaces[i] = newTexture; + wrapper->dirtySides = 0xFF; + } } - wrapper->dirtySides = 0xFF; } return 0; } @@ -52,7 +56,7 @@ static int l_set_faces(lua::State* L) { wrapper->dirtySides |= (1 << i); } } else { - auto texture = lua::require_string(L, 2 + i);; + auto texture = lua::require_string(L, 2 + i); if ((wrapper->cullingBits & (1 << i)) == 0x0 || wrapper->textureFaces[i] != texture) { wrapper->cullingBits |= (1 << i); @@ -73,7 +77,6 @@ static int l_set_tints(lua::State* L) { wrapper->tints[i] = lua::tovec3(L, 2 + i); } } - wrapper->dirtySides = 0xFF; } return 0; }