diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-07 17:50:50 +0100 |
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-08 08:29:12 +0100 |
| commit | 9a6a923c68afc4e9b6f47164c7ae9b2ed67bcf77 (patch) | |
| tree | 9123a47535b14f38fa8a171797fafdf492987920 | |
| parent | ea90834553ca195049c41892c1356e157ec6d203 (diff) | |
src, draw: don't overallocate ground & wall vbo's
| -rw-r--r-- | draw/floor.cpp | 16 | ||||
| -rw-r--r-- | draw/wall.cpp | 14 | ||||
| -rw-r--r-- | editor/scenery-editor.hpp | 2 | ||||
| -rw-r--r-- | src/chunk-render.cpp | 111 | ||||
| -rw-r--r-- | src/chunk.hpp | 6 |
5 files changed, 80 insertions, 69 deletions
diff --git a/draw/floor.cpp b/draw/floor.cpp index 5e645b0f..5b5a515f 100644 --- a/draw/floor.cpp +++ b/draw/floor.cpp @@ -13,30 +13,32 @@ floor_mesh::floor_mesh() = default; void floor_mesh::draw(tile_shader& shader, chunk& c) { - constexpr auto quad_index_count = 6; - auto [mesh_, ids] = c.ensure_ground_mesh(); + constexpr int quad_index_count = 6; + const auto [mesh_, ids, size] = c.ensure_ground_mesh(); struct { tile_atlas* atlas = nullptr; std::size_t pos = 0; } last; GL::MeshView mesh{mesh_}; [[maybe_unused]] std::size_t draw_count = 0; - const auto do_draw = [&](std::size_t i, tile_atlas* atlas) { + const auto do_draw = [&](std::size_t i, tile_atlas* atlas, std::uint32_t max_index) { if (atlas == last.atlas) return; if (auto len = i - last.pos; last.atlas && len > 0) { last.atlas->texture().bind(0); mesh.setCount((int)(quad_index_count * len)); - mesh.setIndexRange((int)(last.pos*quad_index_count), 0, quad_index_count*TILE_COUNT - 1); + mesh.setIndexRange((int)(last.pos*quad_index_count), 0, max_index); shader.draw(mesh); draw_count++; } last = { atlas, i }; }; - for (std::size_t k = 0; k < TILE_COUNT; k++) - do_draw(k, c.ground_atlas_at(ids[k])); - do_draw(TILE_COUNT, nullptr); + const auto max_index = std::uint32_t(size*quad_index_count - 1); + std::size_t k; + for (k = 0; k < size; k++) + do_draw(k, c.ground_atlas_at(ids[k]), max_index); + do_draw(size, nullptr, max_index); #ifdef FM_DEBUG_DRAW_COUNT if (draw_count) diff --git a/draw/wall.cpp b/draw/wall.cpp index dbc9c2ad..85365844 100644 --- a/draw/wall.cpp +++ b/draw/wall.cpp @@ -17,28 +17,30 @@ wall_mesh::wall_mesh() = default; void wall_mesh::draw(tile_shader& shader, chunk& c) { - auto [mesh_, ids] = c.ensure_wall_mesh(); + const auto [mesh_, ids, size] = c.ensure_wall_mesh(); struct { tile_atlas* atlas = nullptr; std::size_t pos = 0; } last; GL::MeshView mesh{mesh_}; [[maybe_unused]] std::size_t draw_count = 0; - const auto do_draw = [&](std::size_t i, tile_atlas* atlas) { + const auto do_draw = [&](std::size_t i, tile_atlas* atlas, std::uint32_t max_index) { if (atlas == last.atlas) return; if (auto len = i - last.pos; last.atlas && len > 0) { last.atlas->texture().bind(0); mesh.setCount((int)(quad_index_count * len)); - mesh.setIndexRange((int)(last.pos*quad_index_count), 0, quad_index_count*TILE_COUNT*2 - 1); + mesh.setIndexRange((int)(last.pos*quad_index_count), 0, max_index); shader.draw(mesh); draw_count++; } last = { atlas, i }; }; - for (std::size_t k = 0; k < TILE_COUNT*2; k++) - do_draw(k, c.wall_atlas_at(ids[k])); - do_draw(TILE_COUNT*2, nullptr); + const auto max_index = std::uint32_t(size*quad_index_count - 1); + std::size_t k; + for (k = 0; k < size; k++) + do_draw(k, c.wall_atlas_at(ids[k]), max_index); + do_draw(size, nullptr, max_index); #ifdef FM_DEBUG_DRAW_COUNT if (draw_count) diff --git a/editor/scenery-editor.hpp b/editor/scenery-editor.hpp index 8e47a6b8..647d6b47 100644 --- a/editor/scenery-editor.hpp +++ b/editor/scenery-editor.hpp @@ -31,7 +31,7 @@ struct scenery_editor final bool is_atlas_selected(const std::shared_ptr<anim_atlas>& atlas) const; bool is_item_selected(const scenery_& s) const; bool is_anything_selected() const; - void place_tile(world& w, global_coords pos, const scenery_& s); + static void place_tile(world& w, global_coords pos, const scenery_& s); auto cbegin() const noexcept { return _atlases.cbegin(); } auto cend() const noexcept { return _atlases.cend(); } diff --git a/src/chunk-render.cpp b/src/chunk-render.cpp index 37440af9..cfd10307 100644 --- a/src/chunk-render.cpp +++ b/src/chunk-render.cpp @@ -1,16 +1,18 @@ #include "chunk.hpp" #include "tile-atlas.hpp" +#include "anim-atlas.hpp" #include "shaders/tile.hpp" #include <algorithm> -#include <Magnum/GL/Buffer.h> #include <Corrade/Containers/ArrayViewStl.h> +#include <Magnum/GL/Buffer.h> namespace floormat { -static auto make_index_array(std::size_t offset) +template<std::size_t N = 1> +static auto make_index_array(std::size_t offset, std::size_t max) { - std::array<std::array<UnsignedShort, 6>, TILE_COUNT> array; // NOLINT(cppcoreguidelines-pro-type-member-init) - for (std::size_t i = 0; i < TILE_COUNT; i++) + std::array<std::array<UnsignedShort, 6>, N*TILE_COUNT> array; // NOLINT(cppcoreguidelines-pro-type-member-init) + for (std::size_t i = 0; i < max; i++) array[i] = tile_atlas::indices(i + offset); return array; } @@ -24,84 +26,87 @@ struct vertex { auto chunk::ensure_ground_mesh() noexcept -> ground_mesh_tuple { if (!_ground_modified) - return { ground_mesh, ground_indexes }; + return { ground_mesh, ground_indexes, std::size_t(ground_mesh.count()/6) }; _ground_modified = false; + std::size_t count = 0; for (std::size_t i = 0; i < TILE_COUNT; i++) - ground_indexes[i] = std::uint8_t(i); - std::sort(ground_indexes.begin(), ground_indexes.end(), [this](std::uint8_t a, std::uint8_t b) { - return _ground_atlases[a].get() < _ground_atlases[b].get(); - }); + if (_ground_atlases[i]) + ground_indexes[count++] = std::uint8_t(i); + + std::sort(ground_indexes.begin(), ground_indexes.begin() + count, + [this](std::uint8_t a, std::uint8_t b) { + return _ground_atlases[a] < _ground_atlases[b]; + }); std::array<std::array<vertex, 4>, TILE_COUNT> vertexes; - for (std::size_t k = 0; k < TILE_COUNT; k++) + for (std::size_t k = 0; k < count; k++) { const std::uint8_t i = ground_indexes[k]; - if (auto atlas = _ground_atlases[i]; !atlas) - vertexes[k] = {}; - else - { - const local_coords pos{i}; - const auto quad = atlas->floor_quad(Vector3(pos.x, pos.y, 0) * TILE_SIZE, TILE_SIZE2); - const auto texcoords = atlas->texcoords_for_id(_ground_variants[i]); - const float depth = tile_shader::depth_value(pos); - auto& v = vertexes[k]; - for (std::size_t j = 0; j < 4; j++) - v[j] = { quad[j], texcoords[j], depth }; - } + const auto& atlas = _ground_atlases[i]; + const local_coords pos{i}; + const auto quad = atlas->floor_quad(Vector3(pos.x, pos.y, 0) * TILE_SIZE, TILE_SIZE2); + const auto texcoords = atlas->texcoords_for_id(_ground_variants[i]); + const float depth = tile_shader::depth_value(pos); + auto& v = vertexes[k]; + for (std::size_t j = 0; j < 4; j++) + v[j] = { quad[j], texcoords[j], depth }; } - const auto indexes = make_index_array(0); + + const auto indexes = make_index_array(0, count); + const auto vertex_view = ArrayView{vertexes.data(), count}; + const auto vert_index_view = ArrayView{indexes.data(), count}; GL::Mesh mesh{GL::MeshPrimitive::Triangles}; - mesh.addVertexBuffer(GL::Buffer{vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) - .setIndexBuffer(GL::Buffer{indexes}, 0, GL::MeshIndexType::UnsignedShort) - .setCount(6 * TILE_COUNT); + mesh.addVertexBuffer(GL::Buffer{vertex_view}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) + .setIndexBuffer(GL::Buffer{vert_index_view}, 0, GL::MeshIndexType::UnsignedShort) + .setCount(std::int32_t(6 * count)); ground_mesh = Utility::move(mesh); - return { ground_mesh, ground_indexes }; + return { ground_mesh, ground_indexes, count }; } auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple { if (!_walls_modified) - return { wall_mesh, wall_indexes }; + return { wall_mesh, wall_indexes, std::size_t(wall_mesh.count()/6) }; _walls_modified = false; + std::size_t count = 0; for (std::size_t i = 0; i < TILE_COUNT*2; i++) - wall_indexes[i] = std::uint16_t(i); + if (_wall_atlases[i]) + wall_indexes[count++] = std::uint16_t(i); - std::sort(wall_indexes.begin(), wall_indexes.end(), [this](std::uint16_t a, std::uint16_t b) { - return _wall_atlases[a] < _wall_atlases[b]; - }); + std::sort(wall_indexes.begin(), wall_indexes.begin() + count, + [this](std::uint16_t a, std::uint16_t b) { + return _wall_atlases[a] < _wall_atlases[b]; + }); std::array<std::array<vertex, 4>, TILE_COUNT*2> vertexes; - for (std::size_t k = 0; k < TILE_COUNT*2; k++) + for (std::size_t k = 0; k < count; k++) { const std::uint16_t i = wall_indexes[k]; - if (const auto& atlas = _wall_atlases[i]; !atlas) - vertexes[k] = {}; - else - { - const auto& variant = _wall_variants[i]; - const local_coords pos{i / 2u}; - const auto center = Vector3(pos.x, pos.y, 0) * TILE_SIZE; - const auto quad = i & 1 ? atlas->wall_quad_W(center, TILE_SIZE) : atlas->wall_quad_N(center, TILE_SIZE); - const float depth = tile_shader::depth_value(pos); - const auto texcoords = atlas->texcoords_for_id(variant); - auto& v = vertexes[k]; - for (std::size_t j = 0; j < 4; j++) - v[j] = { quad[j], texcoords[j], depth, }; - } + const auto& atlas = _wall_atlases[i]; + const auto& variant = _wall_variants[i]; + const local_coords pos{i / 2u}; + const auto center = Vector3(pos.x, pos.y, 0) * TILE_SIZE; + const auto quad = i & 1 ? atlas->wall_quad_W(center, TILE_SIZE) : atlas->wall_quad_N(center, TILE_SIZE); + const float depth = tile_shader::depth_value(pos); + const auto texcoords = atlas->texcoords_for_id(variant); + auto& v = vertexes[k]; + for (std::size_t j = 0; j < 4; j++) + v[j] = { quad[j], texcoords[j], depth, }; } - using index_t = std::array<std::array<UnsignedShort, 6>, TILE_COUNT>; - const index_t indexes[2] = { make_index_array(0), make_index_array(TILE_COUNT) }; + auto indexes = make_index_array<2>(0, count); + const auto vertex_view = ArrayView{vertexes.data(), count}; + const auto vert_index_view = ArrayView{indexes.data(), count}; GL::Mesh mesh{GL::MeshPrimitive::Triangles}; - mesh.addVertexBuffer(GL::Buffer{vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) - .setIndexBuffer(GL::Buffer{indexes}, 0, GL::MeshIndexType::UnsignedShort) - .setCount(6 * TILE_COUNT); + mesh.addVertexBuffer(GL::Buffer{vertex_view}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) + .setIndexBuffer(GL::Buffer{vert_index_view}, 0, GL::MeshIndexType::UnsignedShort) + .setCount(std::int32_t(6 * count)); wall_mesh = Utility::move(mesh); - return { wall_mesh, wall_indexes }; + return { wall_mesh, wall_indexes, count }; } } // namespace floormat diff --git a/src/chunk.hpp b/src/chunk.hpp index 3a6ea3df..c061d070 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -63,11 +63,13 @@ struct chunk final struct ground_mesh_tuple final { GL::Mesh& mesh; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - const std::array<std::uint8_t, TILE_COUNT>& ids; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + const ArrayView<const std::uint8_t> ids; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::size_t size; }; struct wall_mesh_tuple final { GL::Mesh& mesh; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - const std::array<std::uint16_t, TILE_COUNT*2>& ids; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + const ArrayView<const std::uint16_t> ids; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + const std::size_t size; }; ground_mesh_tuple ensure_ground_mesh() noexcept; |
