summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-04-09 21:54:56 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-04-09 21:55:29 +0200
commit3c6e95bd369270e90472bc25f91dff76d0811b71 (patch)
tree62e1ee33f244252ba854d5494fd2ce8c8de83fe0
parent3694207151dbee36ea89681fc0fd163bdac5695c (diff)
draw: do batching in an easier way for now
-rw-r--r--draw/anim.cpp116
-rw-r--r--draw/anim.hpp8
-rw-r--r--src/chunk-scenery.cpp50
-rw-r--r--src/chunk-scenery.hpp2
-rw-r--r--src/chunk.hpp2
5 files changed, 73 insertions, 105 deletions
diff --git a/draw/anim.cpp b/draw/anim.cpp
index c6c12a64..f8a2835f 100644
--- a/draw/anim.cpp
+++ b/draw/anim.cpp
@@ -6,6 +6,7 @@
#include "chunk-scenery.hpp"
#include <cstdio>
#include <Corrade/Containers/Optional.h>
+#include <Corrade/Containers/ArrayView.h>
#include <Magnum/GL/MeshView.h>
#include <Magnum/GL/Texture.h>
@@ -13,10 +14,29 @@ namespace floormat {
anim_mesh::anim_mesh()
{
- _mesh.setCount(6)
+ _mesh.setCount(quad_index_count)
.addVertexBuffer(_vertex_buffer, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{})
.setIndexBuffer(_index_buffer, 0, GL::MeshIndexType::UnsignedShort);
CORRADE_INTERNAL_ASSERT(_mesh.isIndexed());
+
+ _batch_mesh.setCount(batch_size * quad_index_count)
+ .addVertexBuffer(_batch_vertex_buffer, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{})
+ .setIndexBuffer(_index_buffer, 0, GL::MeshIndexType::UnsignedShort);
+ CORRADE_INTERNAL_ASSERT(_batch_mesh.isIndexed());
+}
+
+auto anim_mesh::make_batch_index_array() -> std::array<std::array<UnsignedShort, quad_index_count>, batch_size>
+{
+ std::array<std::array<UnsignedShort, quad_index_count>, batch_size> array; // NOLINT(cppcoreguidelines-pro-type-member-init)
+ for (std::size_t N = 0; N < batch_size; N++)
+ {
+ using u16 = uint16_t;
+ array[N] = { /* 3--1 1 */
+ (u16)(0+N*4), (u16)(1+N*4), (u16)(2+N*4), /* | / /| */
+ (u16)(2+N*4), (u16)(1+N*4), (u16)(3+N*4), /* |/ / | */
+ }; /* 2 2--0 */
+ }
+ return array;
}
std::array<UnsignedShort, 6> anim_mesh::make_index_array()
@@ -57,67 +77,59 @@ void anim_mesh::add_clickable(tile_shader& shader, const Vector2i& win_size,
void anim_mesh::draw(tile_shader& shader, const Vector2i& win_size, chunk& c, std::vector<clickable>& list)
{
- constexpr auto quad_index_count = 6;
-
- auto [mesh_, es, size] = c.ensure_scenery_mesh(_draw_array);
- for (const auto& x : es)
- add_clickable(shader, win_size, x.data.in, x.data, list);
-
- GL::MeshView mesh{mesh_};
- [[maybe_unused]] size_t draw_count = 0;
- const auto max_index = uint32_t(size*quad_index_count - 1);
-
- const auto do_draw = [&](size_t from, size_t to, anim_atlas* atlas) {
- atlas->texture().bind(0);
- mesh.setCount((int)(quad_index_count * (to-from)));
- mesh.setIndexRange((int)(from*quad_index_count), 0, max_index);
- shader.draw(mesh);
- draw_count++;
+ GL::MeshView mesh{_batch_mesh};
+ auto [es] = c.ensure_scenery_mesh(_draw_array);
+ std::array<quad_data, batch_size> array = {};
+ std::array<anim_atlas*, batch_size> atlases = {};
+ anim_atlas* last_atlas = nullptr;
+
+ constexpr auto do_draw = [](tile_shader& shader, GL::MeshView& mesh, anim_atlas*& last_atlas, anim_atlas* atlas, uint32_t i) {
+ constexpr auto max_index = uint32_t(batch_size*quad_index_count - 1);
+ if (atlas != last_atlas)
+ {
+ last_atlas = atlas;
+ atlas->texture().bind(0);
+ }
+ mesh.setCount((int)(quad_index_count));
+ mesh.setIndexRange((int)(i*quad_index_count), 0, max_index);
+ shader.draw(mesh);
};
- fm_debug_assert(size_t(mesh_.count()) <= size*quad_index_count);
+ uint32_t k = 0;
- struct last_ {
- anim_atlas* atlas = nullptr; size_t run_from = 0;
- operator bool() const { return atlas; }
- last_& operator=(std::nullptr_t) { atlas = nullptr; return *this; }
- } last;
- size_t i = 0;
-
- for (auto k = 0uz; k < size; k++)
+ for (const auto& x : es)
{
- fm_assert(es[k].e);
- auto& e = *es[k].e;
+ fm_assert(x.e);
+ add_clickable(shader, win_size, x.data.in, x.data, list);
+ const auto& e = *x.e;
+ const auto depth0 = e.depth_offset();
+ const auto depth1 = depth0[1]*TILE_MAX_DIM + depth0[0];
+ const auto depth = tile_shader::depth_value(e.coord.local(), depth1);
+ const auto pos0 = Vector3(e.coord.local()) * TILE_SIZE + Vector3(Vector2(e.offset), 0);
auto& atlas = *e.atlas;
- if (last.atlas && &atlas != last.atlas)
- {
- //Debug{} << "draw-static" << es[last.run_from].e->atlas->name() << es[last.run_from].e->ordinal() << Vector2i(es[last.run_from].e->coord.local()) << i - last.run_from;
- do_draw(last.run_from, i, last.atlas);
- last = {};
- }
- if (e.is_dynamic())
- {
- const auto depth0 = e.depth_offset();
- const auto depth1 = depth0[1]*TILE_MAX_DIM + depth0[0];
- const auto depth = tile_shader::depth_value(e.coord.local(), depth1);
- //Debug{} << "draw-dyn" << e.atlas->name() << e.ordinal() << Vector2i(e.coord.local());
- draw(shader, atlas, e.r, e.frame, e.coord.local(), e.offset, depth);
- last = {};
- }
- else
+ const auto pos = atlas.frame_quad(pos0, e.r, e.frame);
+ const auto& g = atlas.group(e.r);
+ const auto texcoords = atlas.texcoords_for_frame(e.r, e.frame, !g.mirror_from.isEmpty());
+
+ for (auto i = 0uz; i < 4; i++)
+ array[k][i] = { pos[i], texcoords[i], depth };
+ atlases[k] = &atlas;
+
+ if (++k >= 1)
{
- if (!last.atlas)
- last = { &atlas, i };
- i++;
+ _batch_vertex_buffer.setSubData(0, { array.data(), k });
+ for (uint32_t i = 0; i < k; i++)
+ do_draw(shader, mesh, last_atlas, atlases[i], i);
+ k = 0;
}
}
- if (last.atlas && i != last.run_from)
+
+ if (k > 0)
{
- //Debug{} << "draw-last" << last.atlas->name() << es[es.size()-1].e->ordinal() << Vector2i(es[es.size()-1].e->coord.local()) << i - last.run_from;
- do_draw(last.run_from, i, last.atlas);
+ _batch_vertex_buffer.setSubData(0, ArrayView<const quad_data>{array.data(), k});
+ for (uint32_t i = 0; i < k; i++)
+ do_draw(shader, mesh, last_atlas, atlases[i], i);
}
-
- //Debug{} << "--" << i << draw_count << "--"; std::fflush(stdout);
}
void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, size_t frame, const Vector3& center, float depth)
diff --git a/draw/anim.hpp b/draw/anim.hpp
index eaa191f5..93900caf 100644
--- a/draw/anim.hpp
+++ b/draw/anim.hpp
@@ -34,7 +34,9 @@ struct anim_mesh final
std::vector<clickable>& list);
private:
- static std::array<UnsignedShort, 6> make_index_array();
+ static constexpr size_t batch_size = 256, quad_index_count = 6;
+ static std::array<UnsignedShort, quad_index_count> make_index_array();
+ static std::array<std::array<UnsignedShort, quad_index_count>, batch_size> make_batch_index_array();
struct vertex_data final {
Vector3 position;
@@ -47,6 +49,10 @@ private:
GL::Mesh _mesh;
GL::Buffer _vertex_buffer{quad_data{}, Magnum::GL::BufferUsage::DynamicDraw},
_index_buffer{make_index_array()};
+
+ GL::Mesh _batch_mesh{NoCreate};
+ GL::Buffer _batch_vertex_buffer{std::array<quad_data, batch_size>{}, Magnum::GL::BufferUsage::DynamicDraw},
+ _batch_index_buffer{make_batch_index_array()};
};
} // namespace floormat
diff --git a/src/chunk-scenery.cpp b/src/chunk-scenery.cpp
index 66f6a733..40a99487 100644
--- a/src/chunk-scenery.cpp
+++ b/src/chunk-scenery.cpp
@@ -132,55 +132,7 @@ auto chunk::ensure_scenery_mesh(Array<entity_draw_order>& array) noexcept -> sce
std::sort(array.begin(), array.begin() + size, [](const auto& a, const auto& b) { return a.ord < b.ord; });
topological_sort(array, size);
- const auto es = ArrayView<entity_draw_order>{array, size};
-
- if (_scenery_modified)
- {
- _scenery_modified = false;
-
- const auto count = fm_begin(
- size_t ret = 0;
- for (const auto& [e, ord, _data] : es)
- ret += !e->is_dynamic();
- return ret;
- );
-
- scenery_indexes.clear();
- scenery_indexes.reserve(count);
- scenery_vertexes.clear();
- scenery_vertexes.reserve(count);
-
- for (const auto& [e, ord, _data] : es)
- {
- if (e->is_dynamic())
- continue;
-
- const auto i = scenery_indexes.size();
- scenery_indexes.emplace_back(tile_atlas::indices(i));
- const auto& atlas = e->atlas;
- const auto& fr = *e;
- const auto pos = e->coord.local();
- const auto coord = Vector3(pos) * TILE_SIZE + Vector3(Vector2(fr.offset), 0);
- const auto quad = atlas->frame_quad(coord, fr.r, fr.frame);
- const auto& group = atlas->group(fr.r);
- const auto texcoords = atlas->texcoords_for_frame(fr.r, fr.frame, !group.mirror_from.isEmpty());
- const float depth = tile_shader::depth_value(pos, tile_shader::scenery_depth_offset);
- scenery_vertexes.emplace_back();
- auto& v = scenery_vertexes.back();
- for (auto j = 0uz; j < 4; j++)
- v[j] = { quad[j], texcoords[j], depth };
- }
-
- GL::Mesh mesh{GL::MeshPrimitive::Triangles};
- mesh.addVertexBuffer(GL::Buffer{scenery_vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{})
- .setIndexBuffer(GL::Buffer{scenery_indexes}, 0, GL::MeshIndexType::UnsignedShort)
- .setCount(int32_t(6 * count));
- scenery_mesh = Utility::move(mesh);
- }
-
- fm_assert(!size || es);
-
- return { scenery_mesh, es, size };
+ return { ArrayView<entity_draw_order>{array, size} };
}
void chunk::ensure_scenery_draw_array(Array<entity_draw_order>& array)
diff --git a/src/chunk-scenery.hpp b/src/chunk-scenery.hpp
index cbe2ea83..067f176a 100644
--- a/src/chunk-scenery.hpp
+++ b/src/chunk-scenery.hpp
@@ -25,9 +25,7 @@ struct chunk::entity_draw_order
topo_sort_data data;
};
struct chunk::scenery_mesh_tuple {
- GL::Mesh& mesh;
ArrayView<entity_draw_order> array;
- size_t size;
};
} // namespace floormat
diff --git a/src/chunk.hpp b/src/chunk.hpp
index be90c89a..db6f96f7 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -125,7 +125,7 @@ private:
std::vector<std::array<vertex, 4>> scenery_vertexes;
struct world* _world;
- GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate}, scenery_mesh{NoCreate};
+ GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate};
RTree _rtree;