diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index fed5c1fb..d27811a9 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -139,38 +139,32 @@ void WorldRenderer::drawChunks( // [warning] this whole method is not thread-safe for chunks + int chunksWidth = chunks->getWidth(); + int chunksOffsetX = chunks->getOffsetX(); + int chunksOffsetY = chunks->getOffsetY(); + if (indices.size() != chunks->getVolume()) { indices.clear(); - for (size_t i = 0; i < chunks->getVolume(); i++) { - indices.emplace_back(i); + for (int i = 0; i < chunks->getVolume(); i++) { + indices.push_back(ChunksSortEntry {i, 0}); } } float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; float pz = camera.position.z / static_cast(CHUNK_D) - 0.5f; - int chunksWidth = chunks->getWidth(); - int chunksOffsetX = chunks->getOffsetX(); - int chunksOffsetY = chunks->getOffsetY(); - util::insertion_sort(indices.begin(), indices.end(), - [chunks, px, pz, chunksWidth, chunksOffsetX, chunksOffsetY] - (auto i, auto j) - { - int ax = i % chunksWidth + chunksOffsetX; - int az = i / chunksWidth + chunksOffsetY; - int bx = j % chunksWidth + chunksOffsetX; - int bz = j / chunksWidth + chunksOffsetY; - auto adx = (ax - px); - auto adz = (az - pz); - auto bdx = (bx - px); - auto bdz = (bz - pz); - return (adx * adx + adz * adz > bdx * bdx + bdz * bdz); - }); + for (auto& index : indices) { + int x = index.index % chunksWidth + chunksOffsetX - px; + int z = index.index / chunksWidth + chunksOffsetY - pz; + index.d = x * x + z * z; + } + util::insertion_sort(indices.begin(), indices.end()); + bool culling = engine->getSettings().graphics.frustumCulling.get(); if (culling) { frustumCulling->update(camera.getProjView()); } chunks->visible = 0; for (size_t i = 0; i < indices.size(); i++) { - chunks->visible += drawChunk(indices[i], camera, shader, culling); + chunks->visible += drawChunk(indices[i].index, camera, shader, culling); } } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 65893c14..7799e457 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -34,6 +34,15 @@ namespace model { struct Model; } +struct ChunksSortEntry { + int index; + int d; + + inline bool operator<(const ChunksSortEntry& o) const noexcept { + return d > o.d; + } +}; + class WorldRenderer { Engine* engine; Level* level; @@ -45,7 +54,7 @@ class WorldRenderer { std::unique_ptr batch3d; std::unique_ptr modelBatch; - std::vector indices; + std::vector indices; float timer = 0.0f; diff --git a/src/util/listutil.hpp b/src/util/listutil.hpp index 4618921d..9f2afe0c 100644 --- a/src/util/listutil.hpp +++ b/src/util/listutil.hpp @@ -5,6 +5,15 @@ #include namespace util { + template + inline void insertion_sort(Iter first, Iter last) { + for (Iter it = first; it != last; ++it) { + std::rotate( + std::upper_bound(first, it, *it), it, std::next(it) + ); + } + } + template inline void insertion_sort(Iter first, Iter last, Compare compare) { for (Iter it = first; it != last; ++it) {