From 30ab6c2f5e147869cc91741b9a12d7f3006d166d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 6 Jul 2026 01:05:44 +0300 Subject: [PATCH] remove unnecessary drawGroup-based loops --- src/graphics/render/BlocksRenderer.cpp | 336 ++++++++++++------------- src/graphics/render/BlocksRenderer.hpp | 12 +- src/graphics/render/ChunksRenderer.cpp | 7 +- src/voxels/VoxelsVolume.hpp | 20 +- 4 files changed, 180 insertions(+), 195 deletions(-) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 0aae42010..6ccc5dcf6 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -10,15 +10,14 @@ #include "frontend/ContentGfxCache.hpp" const glm::vec3 BlocksRenderer::SUN_VECTOR(0.528265, 0.833149, -0.163704); -const float DIRECTIONAL_LIGHT_FACTOR = 0.3f; +constexpr float DIRECTIONAL_LIGHT_FACTOR = 0.3f; BlocksRenderer::BlocksRenderer( size_t capacity, - const Content& content, + const Block* const* blockDefs, const ContentGfxCache& cache, const EngineSettings& settings -) : content(content), - vertexBuffer(std::make_unique(capacity)), +) : vertexBuffer(std::make_unique(capacity)), indexBuffer(std::make_unique(capacity)), denseIndexBuffer(std::make_unique(capacity)), vertexCount(0), @@ -28,7 +27,7 @@ BlocksRenderer::BlocksRenderer( cache(cache), settings(settings) { - blockDefsCache = content.getIndices()->blocks.getDefs(); + blockDefsCache = blockDefs; } BlocksRenderer::~BlocksRenderer() = default; @@ -482,84 +481,78 @@ glm::vec4 BlocksRenderer::pickSoftLight( } void BlocksRenderer::render( - const voxel* voxels, const int beginEnds[256][2] + const voxel* voxels, int totalBegin, int totalEnd ) { bool denseRender = this->denseRender; bool densePass = this->densePass; bool enableAO = settings.graphics.softLighting.get(); - for (const auto drawGroup : *content.drawGroups) { - int begin = beginEnds[drawGroup][0]; - if (begin == 0) { + + for (int i = totalBegin; i < totalEnd; i++) { + const voxel& vox = voxels[i]; + blockid_t id = vox.id; + blockstate state = vox.state; + const auto& def = *blockDefsCache[id]; + uint8_t variantId = def.getVariantIndex(state.userbits); + const auto& variant = def.getVariant(variantId); + if (id == 0 || state.segment) { continue; } - int end = beginEnds[drawGroup][1]; - for (int i = begin-1; i <= end; i++) { - const voxel& vox = voxels[i]; - blockid_t id = vox.id; - blockstate state = vox.state; - const auto& def = *blockDefsCache[id]; - uint8_t variantId = def.getVariantIndex(state.userbits); - const auto& variant = def.getVariant(variantId); - if (id == 0 || variant.drawGroup != drawGroup || state.segment) { - continue; + if (denseRender != (variant.culling == CullingMode::OPTIONAL)) { + continue; + } + if (def.translucent) { + continue; + } + const UVRegion texfaces[6] { + cache.getRegion(id, variantId, 0, densePass), + cache.getRegion(id, variantId, 1, densePass), + cache.getRegion(id, variantId, 2, densePass), + cache.getRegion(id, variantId, 3, densePass), + cache.getRegion(id, variantId, 4, densePass), + cache.getRegion(id, variantId, 5, densePass) + }; + int x = i % CHUNK_W; + int y = i / (CHUNK_D * CHUNK_W); + int z = (i / CHUNK_D) % CHUNK_W; + switch (def.getModel(state.userbits).type) { + case BlockModelType::BLOCK: + blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless, + def.ambientOcclusion && enableAO); + break; + case BlockModelType::XSPRITE: { + if (!denseRender) + blockXSprite(x, y, z, glm::vec3(1.0f), + texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f); + break; } - if (denseRender != (variant.culling == CullingMode::OPTIONAL)) { - continue; + case BlockModelType::AABB: { + if (!denseRender) + blockAABB({x, y, z}, texfaces, &def, vox.state.rotation, + !def.shadeless, def.ambientOcclusion && enableAO); + break; } - if (def.translucent) { - continue; - } - const UVRegion texfaces[6] { - cache.getRegion(id, variantId, 0, densePass), - cache.getRegion(id, variantId, 1, densePass), - cache.getRegion(id, variantId, 2, densePass), - cache.getRegion(id, variantId, 3, densePass), - cache.getRegion(id, variantId, 4, densePass), - cache.getRegion(id, variantId, 5, densePass) - }; - int x = i % CHUNK_W; - int y = i / (CHUNK_D * CHUNK_W); - int z = (i / CHUNK_D) % CHUNK_W; - switch (def.getModel(state.userbits).type) { - case BlockModelType::BLOCK: - blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless, - def.ambientOcclusion && enableAO); - break; - case BlockModelType::XSPRITE: { - if (!denseRender) - blockXSprite(x, y, z, glm::vec3(1.0f), - texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f); - break; - } - case BlockModelType::AABB: { - if (!denseRender) - blockAABB({x, y, z}, texfaces, &def, vox.state.rotation, - !def.shadeless, def.ambientOcclusion && enableAO); - break; - } - case BlockModelType::CUSTOM: { - if (!denseRender) - blockCustomModel( - {x, y, z}, - def, - vox.state, - !def.shadeless, - def.ambientOcclusion && enableAO - ); - break; - } - default: - break; - } - if (overflow) { - return; + case BlockModelType::CUSTOM: { + if (!denseRender) + blockCustomModel( + {x, y, z}, + def, + vox.state, + !def.shadeless, + def.ambientOcclusion && enableAO + ); + break; } + default: + break; + } + if (overflow) { + return; } } } SortingMeshData BlocksRenderer::renderTranslucent( - const voxel* voxels, int beginEnds[256][2] + const voxel* voxels, int totalBegin, int totalEnd ) { SortingMeshData sortingMesh {{}}; @@ -569,106 +562,98 @@ SortingMeshData BlocksRenderer::renderTranslucent( bool densePass = this->densePass; bool enableAO = settings.graphics.softLighting.get(); - for (const auto drawGroup : *content.drawGroups) { - int begin = beginEnds[drawGroup][0]; - if (begin == 0) { + for (int i = totalBegin; i < totalEnd; i++) { + const voxel& vox = voxels[i]; + blockid_t id = vox.id; + blockstate state = vox.state; + const auto& def = *blockDefsCache[id]; + uint8_t variantId = def.getVariantIndex(state.userbits); + if (id == 0 || state.segment) { continue; } - int end = beginEnds[drawGroup][1]; - for (int i = begin-1; i <= end; i++) { - const voxel& vox = voxels[i]; - blockid_t id = vox.id; - blockstate state = vox.state; - const auto& def = *blockDefsCache[id]; - uint8_t variantId = def.getVariantIndex(state.userbits); - const auto& variant = def.getVariant(variantId); - if (id == 0 || variant.drawGroup != drawGroup || state.segment) { - continue; - } - if (!def.translucent) { - continue; - } - const UVRegion texfaces[6] { - cache.getRegion(id, variantId, 0, densePass), - cache.getRegion(id, variantId, 1, densePass), - cache.getRegion(id, variantId, 2, densePass), - cache.getRegion(id, variantId, 3, densePass), - cache.getRegion(id, variantId, 4, densePass), - cache.getRegion(id, variantId, 5, densePass) - }; - int x = i % CHUNK_W; - int y = i / (CHUNK_D * CHUNK_W); - int z = (i / CHUNK_D) % CHUNK_W; - switch (def.getModel(state.userbits).type) { - case BlockModelType::BLOCK: - blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless, - def.ambientOcclusion && enableAO); - break; - case BlockModelType::XSPRITE: { - blockXSprite(x, y, z, glm::vec3(1.0f), - texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f); - break; - } - case BlockModelType::AABB: { - blockAABB( - {x, y, z}, - texfaces, - &def, - vox.state.rotation, - !def.shadeless, - def.ambientOcclusion && enableAO - ); - break; - } - case BlockModelType::CUSTOM: { - blockCustomModel( - {x, y, z}, - def, - vox.state, - !def.shadeless, - def.ambientOcclusion && enableAO - ); - break; - } - default: - break; - } - if (vertexCount == 0) { - continue; - } - SortingMeshEntry entry { - glm::vec3( - x + chunk->x * CHUNK_W + 0.5f, - y + 0.5f, - z + chunk->z * CHUNK_D + 0.5f - ), - util::Buffer(indexCount), 0}; - - totalSize += entry.vertexData.size(); - - for (int j = 0; j < indexCount; j++) { - std::memcpy( - entry.vertexData.data() + j, - vertexBuffer.get() + indexBuffer[j], - sizeof(ChunkVertex) - ); - ChunkVertex& vertex = entry.vertexData[j]; - - if (!aabbInit) { - aabbInit = true; - aabb.a = aabb.b = vertex.position; - } else { - aabb.addPoint(vertex.position); - } - - vertex.position.x += chunk->x * CHUNK_W + 0.5f; - vertex.position.y += 0.5f; - vertex.position.z += chunk->z * CHUNK_D + 0.5f; - } - sortingMesh.entries.push_back(std::move(entry)); - vertexCount = 0; - vertexOffset = indexCount = 0; + if (!def.translucent) { + continue; } + const UVRegion texfaces[6] { + cache.getRegion(id, variantId, 0, densePass), + cache.getRegion(id, variantId, 1, densePass), + cache.getRegion(id, variantId, 2, densePass), + cache.getRegion(id, variantId, 3, densePass), + cache.getRegion(id, variantId, 4, densePass), + cache.getRegion(id, variantId, 5, densePass) + }; + int x = i % CHUNK_W; + int y = i / (CHUNK_D * CHUNK_W); + int z = (i / CHUNK_D) % CHUNK_W; + switch (def.getModel(state.userbits).type) { + case BlockModelType::BLOCK: + blockCube({x, y, z}, texfaces, def, vox.state, !def.shadeless, + def.ambientOcclusion && enableAO); + break; + case BlockModelType::XSPRITE: { + blockXSprite(x, y, z, glm::vec3(1.0f), + texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f); + break; + } + case BlockModelType::AABB: { + blockAABB( + {x, y, z}, + texfaces, + &def, + vox.state.rotation, + !def.shadeless, + def.ambientOcclusion && enableAO + ); + break; + } + case BlockModelType::CUSTOM: { + blockCustomModel( + {x, y, z}, + def, + vox.state, + !def.shadeless, + def.ambientOcclusion && enableAO + ); + break; + } + default: + break; + } + if (vertexCount == 0) { + continue; + } + SortingMeshEntry entry { + glm::vec3( + x + chunk->x * CHUNK_W + 0.5f, + y + 0.5f, + z + chunk->z * CHUNK_D + 0.5f + ), + util::Buffer(indexCount), 0}; + + totalSize += entry.vertexData.size(); + + for (int j = 0; j < indexCount; j++) { + std::memcpy( + entry.vertexData.data() + j, + vertexBuffer.get() + indexBuffer[j], + sizeof(ChunkVertex) + ); + ChunkVertex& vertex = entry.vertexData[j]; + + if (!aabbInit) { + aabbInit = true; + aabb.a = aabb.b = vertex.position; + } else { + aabb.addPoint(vertex.position); + } + + vertex.position.x += chunk->x * CHUNK_W + 0.5f; + vertex.position.y += 0.5f; + vertex.position.z += chunk->z * CHUNK_D + 0.5f; + } + sortingMesh.entries.push_back(std::move(entry)); + vertexCount = 0; + vertexOffset = indexCount = 0; } // additional powerful optimization @@ -710,19 +695,16 @@ void BlocksRenderer::build( int totalBegin = chunk->bottom * (CHUNK_W * CHUNK_D); int totalEnd = chunk->top * (CHUNK_W * CHUNK_D); + bool hasTranslucent = false; - int beginEnds[256][2] {}; for (int i = totalBegin; i < totalEnd; i++) { const voxel& vox = voxels[i]; blockid_t id = vox.id; const auto& def = *blockDefsCache[id]; - const auto& variant = def.getVariantByBits(vox.state.userbits); - hasTranslucent = def.translucent || hasTranslucent; - - if (beginEnds[variant.drawGroup][0] == 0) { - beginEnds[variant.drawGroup][0] = i + 1; + if (def.translucent) { + hasTranslucent = true; + break; } - beginEnds[variant.drawGroup][1] = i; } cancelled = false; @@ -734,7 +716,7 @@ void BlocksRenderer::build( densePass = false; if (hasTranslucent) { - sortingMesh = renderTranslucent(voxels, beginEnds); + sortingMesh = renderTranslucent(voxels, totalBegin, totalEnd); } else { sortingMesh = {}; } @@ -747,13 +729,13 @@ void BlocksRenderer::build( denseRender = false; densePass = false; - render(voxels, beginEnds); + render(voxels, totalBegin, totalEnd); size_t endIndex = indexCount; denseRender = true; densePass = settings.graphics.denseRender.get(); - render(voxels, beginEnds); + render(voxels, totalBegin, totalEnd); denseIndexCount = indexCount; for (size_t i = 0; i < denseIndexCount; i++) { @@ -762,7 +744,7 @@ void BlocksRenderer::build( indexCount = endIndex; densePass = false; - render(voxels, beginEnds); + render(voxels, totalBegin, totalEnd); } ChunkMeshData BlocksRenderer::createMesh() { diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 94b708a54..0488f0080 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -25,7 +25,7 @@ class BlocksRenderer final { public: BlocksRenderer( size_t capacity, - const Content& content, + const Block* const* blockDefs, const ContentGfxCache& cache, const EngineSettings& settings ); @@ -44,7 +44,6 @@ public: } private: static const glm::vec3 SUN_VECTOR; - const Content& content; std::unique_ptr vertexBuffer; std::unique_ptr indexBuffer; std::unique_ptr denseIndexBuffer; @@ -145,13 +144,16 @@ private: ); // Does block allow to see other blocks sides (is it transparent) - inline bool isOpen(const glm::ivec3& pos, const Block& def, const Variant& variant) const { + bool isOpen(const glm::ivec3& pos, const Block& def, const Variant& variant) const { const auto& vox = voxelsBuffer->pickBlock( chunk->x * CHUNK_W + pos.x, pos.y, chunk->z * CHUNK_D + pos.z ); if (vox.id == BLOCK_VOID) { return false; } + if (def.rt.id == vox.id && def.rt.solid && variant.culling == CullingMode::DEFAULT) { + return false; + } const auto& block = *blockDefsCache[vox.id]; const auto& blockVariant = block.getVariantByBits(vox.state.userbits); uint8_t otherDrawGroup = blockVariant.drawGroup; @@ -178,6 +180,6 @@ private: float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up ) const; - void render(const voxel* voxels, const int beginEnds[256][2]); - SortingMeshData renderTranslucent(const voxel* voxels, int beginEnds[256][2]); + void render(const voxel* voxels, int totalBegin, int totalEnd); + SortingMeshData renderTranslucent(const voxel* voxels, int totalBegin, int totalEnd); }; diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index baf4cf356..7e81e0bd5 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -14,6 +14,7 @@ #include "util/listutil.hpp" #include "util/ObjectsPool.hpp" #include "settings.hpp" +#include "content/Content.hpp" static debug::Logger logger("chunks-render"); @@ -33,7 +34,7 @@ public: settings.graphics.denseRender.get() ? settings.graphics.chunkMaxVerticesDense.get() : settings.graphics.chunkMaxVertices.get(), - level.content, + level.content.getIndices()->blocks.getDefs(), cache, settings ) { @@ -92,7 +93,7 @@ ChunksRenderer::ChunksRenderer( threadPool.setStopOnFail(false); renderer = std::make_unique( settings.graphics.chunkMaxVertices.get(), - level.content, cache, settings + level.content.getIndices()->blocks.getDefs(), cache, settings ); logger.info() << "created " << threadPool.getWorkersCount() << " workers"; logger.info() << "memory consumption is " @@ -126,7 +127,7 @@ const ChunkMesh* ChunksRenderer::render( const std::shared_ptr& chunk, bool important, bool lowPriority ) { glm::ivec2 key(chunk->x, chunk->z); - if (important) { + if (important || true) { ChunkMesh mesh {}; auto voxelsBuffer = prepareVoxelsVolume(*chunk); mesh = renderer->render(chunk.get(), *voxelsBuffer); diff --git a/src/voxels/VoxelsVolume.hpp b/src/voxels/VoxelsVolume.hpp index 471b159c5..d90acfa5d 100644 --- a/src/voxels/VoxelsVolume.hpp +++ b/src/voxels/VoxelsVolume.hpp @@ -66,7 +66,7 @@ public: return lights.get(); } - inline blockid_t pickBlockId(int bx, int by, int bz) const { + blockid_t pickBlockId(int bx, int by, int bz) const { if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || bz >= z + d) { return BLOCK_VOID; @@ -75,7 +75,7 @@ public: } - inline voxel pickBlock(int bx, int by, int bz) const { + voxel pickBlock(int bx, int by, int bz) const { if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || bz >= z + d) { return {BLOCK_VOID, {}}; @@ -83,7 +83,7 @@ public: return voxels[vox_index(bx - x, by - y, bz - z, w, d)]; } - inline light_t pickLight(int bx, int by, int bz) const { + light_t pickLight(int bx, int by, int bz) const { if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h || bz >= z + d) { return 0; @@ -103,10 +103,10 @@ private: template class StaticVoxelsVolume { public: - static inline constexpr size_t size = w * h * d; - static inline constexpr int width = w; - static inline constexpr int height = h; - static inline constexpr int depth = d; + static constexpr size_t size = w * h * d; + static constexpr int width = w; + static constexpr int height = h; + static constexpr int depth = d; StaticVoxelsVolume() : StaticVoxelsVolume(0, 0, 0) {} @@ -142,7 +142,7 @@ public: return lights; } - inline blockid_t pickBlockId(uint bx, uint by, uint bz) const { + blockid_t pickBlockId(uint bx, uint by, uint bz) const { bx -= x; by -= y; bz -= z; @@ -153,7 +153,7 @@ public: } - inline const voxel& pickBlock(uint bx, uint by, uint bz) const { + const voxel& pickBlock(uint bx, uint by, uint bz) const { bx -= x; by -= y; bz -= z; @@ -164,7 +164,7 @@ public: return voxels[vox_index(bx, by, bz, w, d)]; } - inline light_t pickLight(uint bx, uint by, uint bz) const { + light_t pickLight(uint bx, uint by, uint bz) const { bx -= x; by -= y; bz -= z;