From e9af93b747a39679aba6c53f421f2d40d7fcbee6 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 4 Oct 2020 17:22:38 +0300 Subject: [PATCH] Refactor meshes: single unified mesh class --- examples/cloud.cpp | 4 +- examples/fire.cpp | 3 +- examples/grass.cpp | 4 +- libs/gfx/include/psemek/gfx/fullscreen.hpp | 2 +- libs/gfx/include/psemek/gfx/mesh.hpp | 729 ++++++--------------- libs/gfx/source/fullscreen.cpp | 8 +- libs/gfx/source/mesh.cpp | 358 ++-------- libs/gfx/source/painter.cpp | 4 +- 8 files changed, 294 insertions(+), 818 deletions(-) diff --git a/examples/cloud.cpp b/examples/cloud.cpp index af5994ba..9260ae4f 100644 --- a/examples/cloud.cpp +++ b/examples/cloud.cpp @@ -173,9 +173,9 @@ struct cloud_app std::vector> bbox_vertices; std::vector> bbox_edges; - gfx::indexed_mesh bbox_mesh; + gfx::mesh bbox_mesh; - gfx::indexed_mesh slice_mesh; + gfx::mesh slice_mesh; gfx::mesh light_mesh; std::vector> dirs; diff --git a/examples/fire.cpp b/examples/fire.cpp index 04d0439c..1d18ed04 100644 --- a/examples/fire.cpp +++ b/examples/fire.cpp @@ -99,7 +99,7 @@ private: gfx::program program_{vertex_source, fragment_source}; - gfx::instanced_mesh mesh_; + gfx::mesh mesh_; gfx::texture_2d texture_; gfx::texture_2d noise_texture_; @@ -229,7 +229,6 @@ void candle_renderer::render(geom::camera const & camera, float time) texture_.bind(); gl::ActiveTexture(gl::TEXTURE1); noise_texture_.bind(); - (void)time; mesh_.draw(); } diff --git a/examples/grass.cpp b/examples/grass.cpp index 1d8d3820..f2bec255 100644 --- a/examples/grass.cpp +++ b/examples/grass.cpp @@ -173,10 +173,10 @@ struct grass_app pcg::perlin density; gfx::program ground_program{ground_vs, ground_fs}; - gfx::indexed_mesh ground_mesh; + gfx::mesh ground_mesh; gfx::program grass_program{grass_vs, grass_fs}; - gfx::indexed_mesh grass_mesh; + gfx::mesh grass_mesh; gfx::texture_1d grass_texture; gfx::program grass_slice_program{grass_slice_vs, grass_slice_fs}; diff --git a/libs/gfx/include/psemek/gfx/fullscreen.hpp b/libs/gfx/include/psemek/gfx/fullscreen.hpp index 07df9694..e0988bcf 100644 --- a/libs/gfx/include/psemek/gfx/fullscreen.hpp +++ b/libs/gfx/include/psemek/gfx/fullscreen.hpp @@ -5,6 +5,6 @@ namespace psemek::gfx { - indexed_mesh const & fullscreen_quad(); + mesh const & fullscreen_quad(); } diff --git a/libs/gfx/include/psemek/gfx/mesh.hpp b/libs/gfx/include/psemek/gfx/mesh.hpp index 9929520e..7268116a 100644 --- a/libs/gfx/include/psemek/gfx/mesh.hpp +++ b/libs/gfx/include/psemek/gfx/mesh.hpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include @@ -386,10 +388,7 @@ namespace psemek::gfx template static constexpr GLenum gl_type_v = gl_type::value; - void check_vertex_size(std::size_t vertex_size, std::size_t stride); - void check_instance_size(std::size_t instance_size, std::size_t stride); - - static std::size_t index_size(GLenum type) + inline std::size_t index_size(GLenum type) { switch (type) { @@ -401,573 +400,277 @@ namespace psemek::gfx return 0; } + template + GLenum get_primitive_type() + { + if constexpr (N == 0) + { + return gl::POINTS; + } + else if constexpr (N == 1) + { + return gl::LINES; + } + else if constexpr (N == 2) + { + return gl::TRIANGLES; + } + else + { + static_assert("unknown primitive type"); + } + } + + inline std::optional get_primitive_type_vertex_count(GLenum type) + { + switch (type) + { + case gl::LINES: + return 2; + case gl::TRIANGLES: + return 3; + default: + return std::nullopt; + } + } + + template + struct has_instanced_attribs_impl + : std::false_type + {}; + + template + struct has_instanced_attribs_impl + : has_instanced_attribs_impl + {}; + + template + struct has_instanced_attribs_impl, Args...> + : std::true_type + {}; + + template + constexpr bool has_instanced_attribs = has_instanced_attribs_impl::value; } + /* A generic mesh class + * Supports both indexed & non-indexed rendering + * Supports both instanced & non-instanced rendering + * Checks vertex & instance size, may throw on load + * Strong exception guarantees + */ + struct mesh : drawable { - static mesh null(); - - mesh(); + mesh() = default; mesh(mesh &&); - mesh(mesh const &) = delete; - mesh & operator = (mesh &&); + + mesh(mesh const &) = delete; mesh & operator = (mesh const &) = delete; - ~mesh(); - template - void setup() - { - gl::BindVertexArray(array_); - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); + void setup(); - stride_ = detail::mesh_setup::setup(); - } + // Non-indexed vertex data template - void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - detail::check_vertex_size(sizeof(Vertex), stride_); - - switch (primitive_type) - { - case gl::LINES: - if ((count % 2) != 0) throw std::runtime_error("Vertex count for GL_LINES should be a multiple of 2"); - break; - case gl::TRIANGLES: - if ((count % 3) != 0) throw std::runtime_error("Vertex count for GL_TRIANGLES should be a multiple of 3"); - break; - default: - break; - } - - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Vertex), vertices, usage); - - count_ = count; - primitive_type_ = primitive_type; - } + void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW); template - void load(std::vector const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - load(vertices.data(), vertices.size(), primitive_type, usage); - } + void load(std::vector const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW); template - void load(geom::simplex const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW) - { - static_assert(sizeof(geom::simplex) == (N + 1) * sizeof(Vertex)); - - GLenum primitive_type; - - if constexpr (N == 0) - { - primitive_type = gl::POINTS; - } - else if constexpr (N == 1) - { - primitive_type = gl::LINES; - } - else if constexpr (N == 2) - { - primitive_type = gl::TRIANGLES; - } - else - { - static_assert("unknown primitive type"); - } - - load(reinterpret_cast(simplices), count * (N + 1), primitive_type, usage); - } + void load(geom::simplex const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW); template - void load(std::vector> const & simplices, GLenum usage = gl::STREAM_DRAW) - { - load(simplices.data(), simplices.size(), usage); - } + void load(std::vector> const & simplices, GLenum usage = gl::STREAM_DRAW); - void draw() const override - { - draw(0, count_); - } + // Indexed vertex data - void draw(GLsizei first, GLsizei count) const - { - assert(first + count <= count_); + template + void load(Vertex const * vertices, std::size_t vertex_count, Index const * indices, std::size_t index_count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW); - if (count == 0) return; + template + void load(std::vector const & vertices, std::vector const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW); - gl::BindVertexArray(array_); - gl::DrawArrays(primitive_type_, first, count); - } + template + void load(Vertex const * vertices, std::size_t vertex_count, geom::simplex const * simplices, std::size_t simplex_count, GLenum usage = gl::STREAM_DRAW); - GLsizei count() const - { - return count_; - } + template + void load(std::vector const & vertices, std::vector> const & simplices, GLenum usage = gl::STREAM_DRAW); - GLenum primitive_type() const - { - return primitive_type_; - } + // Instance data + + template + void load_instance(Instance const * instances, std::size_t count, GLenum usage = gl::STREAM_DRAW); + + template + void load_instance(std::vector const & instances, GLenum usage = gl::STREAM_DRAW); + + // Info + + bool is_indexed() const { return info_.indexed_; } + bool is_instanced() const { return info_.instanced_; } + + std::size_t vertex_count() const { return info_.vertex_count_; } + std::size_t index_count() const { return info_.index_count_; } + std::size_t instance_count() const { return info_.instance_count_; } + + std::size_t count() const; // total vertex count = number of vertex shader executions + + GLenum primitive_type() const { return info_.primitive_type_; } + GLenum index_type() const { return info_.index_type_; } + + // Drawing commands + + void draw() const override; + + void draw(std::size_t first, std::size_t count, std::size_t instance_count = 0) const; private: - GLuint array_; - GLuint buffer_; + array array_; + buffer vertex_buffer_ = buffer::null(); + buffer index_buffer_ = buffer::null(); + buffer instance_buffer_ = buffer::null(); - GLsizei count_ = 0; + struct mesh_info + { + bool indexed_ = false; + bool instanced_ = false; - std::size_t stride_ = 0; + std::size_t vertex_count_ = 0; + std::size_t index_count_ = 0; + std::size_t instance_count_ = 0; - GLenum primitive_type_; + std::size_t stride_ = 0; + std::size_t instance_stride_ = 0; - mesh(int); + GLenum primitive_type_; + GLenum index_type_; + }; + + mesh_info info_; }; - struct indexed_mesh - : drawable + template + void mesh::setup() { - static indexed_mesh null(); + array_.bind(); - indexed_mesh(); - indexed_mesh(indexed_mesh &&); - indexed_mesh(indexed_mesh const &) = delete; + if (!vertex_buffer_) vertex_buffer_ = buffer{}; + vertex_buffer_.bind(); + info_.stride_ = detail::instanced_mesh_vertex_setup::setup(); - indexed_mesh & operator =(indexed_mesh &&); - indexed_mesh & operator =(indexed_mesh const &) = delete; - - ~indexed_mesh(); - - template - void setup() + if constexpr (detail::has_instanced_attribs) { - gl::BindVertexArray(array_); - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - - stride_ = detail::mesh_setup::setup(); - - gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_); + if (!instance_buffer_) instance_buffer_ = buffer{}; + instance_buffer_.bind(); + info_.instance_stride_ = detail::instanced_mesh_instance_setup::setup(); + info_.instanced_ = true; } - - template - void load(Vertex const * vertices, std::size_t vertex_count, Index const * indices, std::size_t index_count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) + else { - detail::check_vertex_size(sizeof(Vertex), stride_); - - switch (primitive_type) - { - case gl::LINES: - if ((index_count % 2) != 0) throw std::runtime_error("Index count for GL_LINES should be a multiple of 2"); - break; - case gl::TRIANGLES: - if ((index_count % 3) != 0) throw std::runtime_error("Index count for GL_TRIANGLES should be a multiple of 3"); - break; - default: - break; - } - - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - gl::BufferData(gl::ARRAY_BUFFER, vertex_count * sizeof(Vertex), vertices, usage); - gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_); - gl::BufferData(gl::ARRAY_BUFFER, index_count * sizeof(Index), indices, usage); - - count_ = index_count; - index_type_ = detail::gl_type_v; - primitive_type_ = primitive_type; + info_.instance_stride_ = 0; + info_.instanced_ = false; } + } - template - void load(std::vector const & vertices, std::vector const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage); - } - - template - void load(Vertex const * vertices, std::size_t vertex_count, geom::simplex const * simplices, std::size_t simplex_count, GLenum usage = gl::STREAM_DRAW) - { - static_assert(sizeof(geom::simplex) == (N + 1) * sizeof(Index)); - - GLenum primitive_type; - - if constexpr (N == 0) - { - primitive_type = gl::POINTS; - } - else if constexpr (N == 1) - { - primitive_type = gl::LINES; - } - else if constexpr (N == 2) - { - primitive_type = gl::TRIANGLES; - } - else - { - static_assert("unknown primitive type"); - } - - load(vertices, vertex_count, reinterpret_cast(simplices), simplex_count * (N + 1), primitive_type, usage); - } - - template - void load(std::vector const & vertices, std::vector> const & simplices, GLenum usage = gl::STREAM_DRAW) - { - load(vertices.data(), vertices.size(), simplices.data(), simplices.size(), usage); - } - - void draw() const override - { - draw(0, count_); - } - - void draw(GLsizei first, GLsizei count) const - { - if (count == 0) return; - assert(first + count <= count_); - - gl::BindVertexArray(array_); - gl::DrawElements(primitive_type_, count, index_type_, reinterpret_cast(0) + first * detail::index_size(index_type_)); - } - - GLsizei index_count() const - { - return count_; - } - - GLenum primitive_type() const - { - return primitive_type_; - } - - private: - GLuint array_; - GLuint buffer_; - GLuint index_buffer_; - - GLsizei count_ = 0; - GLenum index_type_ = 0; - - std::size_t stride_ = 0; - - GLenum primitive_type_; - - indexed_mesh(int); - }; - - struct instanced_mesh - : drawable + template + void mesh::load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage) { - static instanced_mesh null(); + assert(info_.stride_ == sizeof(Vertex)); - instanced_mesh(); - instanced_mesh(instanced_mesh &&); - instanced_mesh(instanced_mesh const &) = delete; + if (auto n = detail::get_primitive_type_vertex_count(primitive_type); n) + assert((count % (*n)) == 0); - instanced_mesh & operator = (instanced_mesh &&); - instanced_mesh & operator = (instanced_mesh const &) = delete; + assert(vertex_buffer_); - ~instanced_mesh(); + vertex_buffer_.load(vertices, count, usage); + info_.vertex_count_ = count; + info_.index_count_ = 0; + info_.indexed_ = false; + info_.primitive_type_ = primitive_type; + } - template - void setup() - { - gl::BindVertexArray(array_); - - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - stride_ = detail::instanced_mesh_vertex_setup::setup(); - - gl::BindBuffer(gl::ARRAY_BUFFER, instance_buffer_); - instance_stride_ = detail::instanced_mesh_instance_setup::setup(); - } - - template - void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - detail::check_vertex_size(sizeof(Vertex), stride_); - - switch (primitive_type) - { - case gl::LINES: - if ((count % 2) != 0) throw std::runtime_error("Vertex count for GL_LINES should be a multiple of 2"); - break; - case gl::TRIANGLES: - if ((count % 3) != 0) throw std::runtime_error("Vertex count for GL_TRIANGLES should be a multiple of 3"); - break; - default: - break; - } - - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Vertex), vertices, usage); - - count_ = count; - primitive_type_ = primitive_type; - } - - template - void load(std::vector const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - load(vertices.data(), vertices.size(), primitive_type, usage); - } - - template - void load(geom::simplex const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW) - { - static_assert(sizeof(geom::simplex) == (N + 1) * sizeof(Vertex)); - - GLenum primitive_type; - - if constexpr (N == 0) - { - primitive_type = gl::POINTS; - } - else if constexpr (N == 1) - { - primitive_type = gl::LINES; - } - else if constexpr (N == 2) - { - primitive_type = gl::TRIANGLES; - } - else - { - static_assert("unknown primitive type"); - } - - load(reinterpret_cast(simplices), count * (N + 1), primitive_type, usage); - } - - template - void load(std::vector> const & simplices, GLenum usage = gl::STREAM_DRAW) - { - load(simplices.data(), simplices.size(), usage); - } - - template - void load_instance(Instance const * instances, std::size_t count, GLenum usage = gl::STREAM_DRAW) - { - detail::check_instance_size(sizeof(Instance), instance_stride_); - - gl::BindBuffer(gl::ARRAY_BUFFER, instance_buffer_); - gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Instance), instances, usage); - instance_count_ = count; - } - - template - void load_instance(std::vector const & instances, GLenum usage = gl::STREAM_DRAW) - { - load_instance(instances.data(), instances.size(), usage); - } - - void draw() const override - { - draw(0, count_, instance_count_); - } - - void draw(GLsizei first, GLsizei count, GLsizei instance_count) const - { - assert(first + count <= count_); - assert(instance_count <= instance_count_); - - if (count == 0) return; - if (instance_count == 0) return; - - gl::BindVertexArray(array_); - gl::DrawArraysInstanced(primitive_type_, first, count, instance_count); - } - - GLsizei count() const - { - return count_; - } - - GLsizei instance_count() const - { - return instance_count_; - } - - GLenum primitive_type() const - { - return primitive_type_; - } - - private: - GLuint array_; - GLuint buffer_; - GLuint instance_buffer_; - - GLsizei count_ = 0; - GLsizei instance_count_ = 0; - - std::size_t stride_ = 0; - std::size_t instance_stride_ = 0; - - GLenum primitive_type_; - - instanced_mesh(int); - }; - - struct instanced_indexed_mesh - : drawable + template + void mesh::load(std::vector const & vertices, GLenum primitive_type, GLenum usage) { - static instanced_indexed_mesh null(); + load(vertices.data(), vertices.size(), primitive_type, usage); + } - instanced_indexed_mesh(); - instanced_indexed_mesh(instanced_indexed_mesh &&); - instanced_indexed_mesh(instanced_indexed_mesh const &) = delete; + template + void mesh::load(geom::simplex const * simplices, std::size_t count, GLenum usage) + { + static_assert(sizeof(Vertex) * (N + 1) == sizeof(simplices[0])); + load(reinterpret_cast(simplices), count * (N + 1), detail::get_primitive_type(), usage); + } - instanced_indexed_mesh & operator = (instanced_indexed_mesh &&); - instanced_indexed_mesh & operator = (instanced_indexed_mesh const &) = delete; + template + void mesh::load(std::vector> const & simplices, GLenum usage) + { + load(simplices.data(), simplices.size(), usage); + } - ~instanced_indexed_mesh(); + template + void mesh::load(Vertex const * vertices, std::size_t vertex_count, Index const * indices, std::size_t index_count, GLenum primitive_type, GLenum usage) + { + assert(info_.stride_ == sizeof(Vertex)); - template - void setup() + if (auto n = detail::get_primitive_type_vertex_count(primitive_type); n) + assert((index_count % (*n)) == 0); + + assert(vertex_buffer_); + + if (!index_buffer_) { - gl::BindVertexArray(array_); - - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - stride_ = detail::instanced_mesh_vertex_setup::setup(); - - gl::BindBuffer(gl::ARRAY_BUFFER, instance_buffer_); - instance_stride_ = detail::instanced_mesh_instance_setup::setup(); - - gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_); + index_buffer_ = buffer{}; + array_.bind(); + gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_.id()); } + vertex_buffer_.load(vertices, vertex_count, usage); + index_buffer_.load(indices, index_count, usage); + info_.vertex_count_ = vertex_count; + info_.index_count_ = index_count; + info_.indexed_ = true; + info_.primitive_type_ = primitive_type; + info_.index_type_ = detail::gl_type_v; + } - template - void load(Vertex const * vertices, std::size_t vertex_count, Index const * indices, std::size_t index_count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - detail::check_vertex_size(sizeof(Vertex), stride_); + template + void mesh::load(std::vector const & vertices, std::vector const & indices, GLenum primitive_type, GLenum usage) + { + load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage); + } - switch (primitive_type) - { - case gl::LINES: - if ((index_count % 2) != 0) throw std::runtime_error("Index count for GL_LINES should be a multiple of 2"); - break; - case gl::TRIANGLES: - if ((index_count % 3) != 0) throw std::runtime_error("Index count for GL_TRIANGLES should be a multiple of 3"); - break; - default: - break; - } + template + void mesh::load(Vertex const * vertices, std::size_t vertex_count, geom::simplex const * simplices, std::size_t simplex_count, GLenum usage) + { + static_assert(sizeof(Index) * (N + 1) == sizeof(simplices[0])); + load(vertices, vertex_count, reinterpret_cast(simplices), (N + 1) * simplex_count, detail::get_primitive_type(), usage); + } - gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - gl::BufferData(gl::ARRAY_BUFFER, vertex_count * sizeof(Vertex), vertices, usage); - gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_); - gl::BufferData(gl::ARRAY_BUFFER, index_count * sizeof(Index), indices, usage); + template + void mesh::load(std::vector const & vertices, std::vector> const & simplices, GLenum usage) + { + load(vertices.data(), vertices.size(), simplices.data(), simplices.size(), usage); + } - count_ = index_count; - index_type_ = detail::gl_type_v; - primitive_type_ = primitive_type; - } + template + void mesh::load_instance(Instance const * instances, std::size_t count, GLenum usage) + { + assert(info_.instance_stride_ == sizeof(Instance)); - template - void load(std::vector const & vertices, std::vector const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW) - { - load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage); - } + assert(instance_buffer_); + instance_buffer_.load(instances, count, usage); + info_.instance_count_ = count; + } - template - void load(Vertex const * vertices, std::size_t vertex_count, geom::simplex const * simplices, std::size_t simplex_count, GLenum usage = gl::STREAM_DRAW) - { - static_assert(sizeof(geom::simplex) == (N + 1) * sizeof(Index)); - - GLenum primitive_type; - - if constexpr (N == 0) - { - primitive_type = gl::POINTS; - } - else if constexpr (N == 1) - { - primitive_type = gl::LINES; - } - else if constexpr (N == 2) - { - primitive_type = gl::TRIANGLES; - } - else - { - static_assert("unknown primitive type"); - } - - load(vertices, vertex_count, reinterpret_cast(simplices), simplex_count * (N + 1), primitive_type, usage); - } - - template - void load(std::vector const & vertices, std::vector> const & simplices, GLenum usage = gl::STREAM_DRAW) - { - load(vertices.data(), vertices.size(), simplices.data(), simplices.size(), usage); - } - - template - void load_instance(Instance const * instances, std::size_t count, GLenum usage = gl::STREAM_DRAW) - { - detail::check_instance_size(sizeof(Instance), instance_stride_); - - gl::BindBuffer(gl::ARRAY_BUFFER, instance_buffer_); - gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Instance), instances, usage); - instance_count_ = count; - } - - template - void load_instance(std::vector const & instances, GLenum usage = gl::STREAM_DRAW) - { - load_instance(instances.data(), instances.size(), usage); - } - - void draw() const override - { - draw(0, count_, instance_count_); - } - - void draw(GLsizei first, GLsizei count, GLsizei instance_count) const - { - assert(first + count <= count_); - assert(instance_count <= instance_count_); - - if (count == 0) return; - if (instance_count == 0) return; - - gl::BindVertexArray(array_); - gl::DrawElementsInstanced(primitive_type_, count, index_type_, reinterpret_cast(0) + detail::index_size(index_type_) * first, instance_count); - } - - GLsizei index_count() const - { - return count_; - } - - GLsizei instance_count() const - { - return instance_count_; - } - - GLenum primitive_type() const - { - return primitive_type_; - } - - private: - GLuint array_; - GLuint buffer_; - GLuint index_buffer_; - GLuint instance_buffer_; - - GLsizei count_ = 0; - GLsizei instance_count_ = 0; - GLenum index_type_ = 0; - - std::size_t stride_ = 0; - std::size_t instance_stride_ = 0; - - GLenum primitive_type_; - - instanced_indexed_mesh(int); - }; + template + void mesh::load_instance(std::vector const & instances, GLenum usage) + { + load_instance(instances.data(), instances.size(), usage); + } } diff --git a/libs/gfx/source/fullscreen.cpp b/libs/gfx/source/fullscreen.cpp index 0cb311d3..5b7edb17 100644 --- a/libs/gfx/source/fullscreen.cpp +++ b/libs/gfx/source/fullscreen.cpp @@ -3,9 +3,9 @@ namespace psemek::gfx { - static indexed_mesh create_fullscreen_quad() + static mesh create_fullscreen_quad() { - indexed_mesh m; + mesh m; std::vector> vertices(4); std::vector indices(6); @@ -28,9 +28,9 @@ namespace psemek::gfx return m; } - indexed_mesh const & fullscreen_quad() + mesh const & fullscreen_quad() { - static indexed_mesh m = create_fullscreen_quad(); + static mesh m = create_fullscreen_quad(); return m; } diff --git a/libs/gfx/source/mesh.cpp b/libs/gfx/source/mesh.cpp index e55ec563..5ca89df6 100644 --- a/libs/gfx/source/mesh.cpp +++ b/libs/gfx/source/mesh.cpp @@ -5,309 +5,83 @@ namespace psemek::gfx { - namespace detail - { - - void check_vertex_size(std::size_t vertex_size, std::size_t stride) - { - if (vertex_size != stride) - throw std::runtime_error(util::to_string("Vertex size (", vertex_size, ") not equal to sum of attribute sizes (", stride, ")")); - } - - void check_instance_size(std::size_t instance_size, std::size_t stride) - { - if (instance_size != stride) - throw std::runtime_error(util::to_string("Instance size (", instance_size, ") not equal to sum of instanced attribute sizes (", stride, ")")); - } - - } - - mesh mesh::null() - { - return mesh(0); - } - - mesh::mesh() - { - gl::GenVertexArrays(1, &array_); - gl::GenBuffers(1, &buffer_); - } - mesh::mesh(mesh && other) + : array_{std::move(other.array_)} + , vertex_buffer_{std::move(other.vertex_buffer_)} + , index_buffer_{std::move(other.index_buffer_)} + , instance_buffer_{std::move(other.instance_buffer_)} + , info_{other.info_} { - array_ = other.array_; - buffer_ = other.buffer_; - count_ = other.count_; - stride_ = other.stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.count_ = 0; - other.stride_ = 0; + other.info_ = mesh_info{}; } - mesh & mesh::operator =(mesh && other) + mesh & mesh::operator = (mesh && other) { if (this == &other) return *this; - if (array_) + array_ = std::move(other.array_); + vertex_buffer_ = std::move(other.vertex_buffer_); + index_buffer_ = std::move(other.index_buffer_); + instance_buffer_ = std::move(other.instance_buffer_); + info_ = other.info_; + other.info_ = mesh_info{}; + + return *this; + } + + void mesh::draw() const + { + draw(0, is_indexed() ? index_count() : vertex_count(), instance_count()); + } + + void mesh::draw(std::size_t first, std::size_t count, std::size_t instance_count) const + { + if (is_indexed()) { - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); + assert(first + count <= index_count()); + + if (is_instanced()) + { + assert(instance_count <= this->instance_count()); + + if (count != 0 && instance_count != 0) + { + array_.bind(); + gl::DrawElementsInstanced(primitive_type(), count, index_type(), reinterpret_cast(detail::index_size(index_type()) * first), instance_count); + } + } + else + { + if (count != 0) + { + array_.bind(); + gl::DrawElements(primitive_type(), count, index_type(), reinterpret_cast(detail::index_size(index_type()) * first)); + } + } } - - array_ = other.array_; - buffer_ = other.buffer_; - count_ = other.count_; - stride_ = other.stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.count_ = 0; - other.stride_ = 0; - - return *this; - } - - mesh::~mesh() - { - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - } - - mesh::mesh(int) - { - array_ = 0; - buffer_ = 0; - } - - indexed_mesh indexed_mesh::null() - { - return indexed_mesh(0); - } - - indexed_mesh::indexed_mesh() - { - gl::GenVertexArrays(1, &array_); - gl::GenBuffers(1, &buffer_); - gl::GenBuffers(1, &index_buffer_); - } - - indexed_mesh::indexed_mesh(indexed_mesh && other) - { - array_ = other.array_; - buffer_ = other.buffer_; - index_buffer_ = other.index_buffer_; - count_ = other.count_; - index_type_ = other.index_type_; - stride_ = other.stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.index_buffer_ = 0; - other.count_ = 0; - other.index_type_ = 0; - other.stride_ = 0; - } - - indexed_mesh & indexed_mesh::operator =(indexed_mesh && other) - { - if (this == &other) return *this; - - if (array_) + else { - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - gl::DeleteBuffers(1, &index_buffer_); + assert(first + count <= vertex_count()); + + if (is_instanced()) + { + assert(instance_count <= this->instance_count()); + + if (count != 0 && instance_count != 0) + { + array_.bind(); + gl::DrawArraysInstanced(primitive_type(), first, count, instance_count); + } + } + else + { + if (count != 0) + { + array_.bind(); + gl::DrawArrays(primitive_type(), first, count); + } + } } - - array_ = other.array_; - buffer_ = other.buffer_; - index_buffer_ = other.index_buffer_; - count_ = other.count_; - index_type_ = other.index_type_; - stride_ = other.stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.index_buffer_ = 0; - other.count_ = 0; - other.index_type_ = 0; - other.stride_ = 0; - - return *this; - } - - indexed_mesh::~indexed_mesh() - { - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - gl::DeleteBuffers(1, &index_buffer_); - } - - indexed_mesh::indexed_mesh(int) - { - array_ = 0; - buffer_ = 0; - index_buffer_ = 0; - } - - instanced_mesh instanced_mesh::null() - { - return instanced_mesh(0); - } - - instanced_mesh::instanced_mesh() - { - gl::GenVertexArrays(1, &array_); - gl::GenBuffers(1, &buffer_); - gl::GenBuffers(1, &instance_buffer_); - } - - instanced_mesh::instanced_mesh(instanced_mesh && other) - { - array_ = other.array_; - buffer_ = other.buffer_; - instance_buffer_ = other.instance_buffer_; - count_ = other.count_; - instance_count_ = other.instance_count_; - stride_ = other.stride_; - instance_stride_ = other.instance_stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.instance_buffer_ = 0; - other.count_ = 0; - other.instance_count_ = 0; - other.stride_ = 0; - other.instance_stride_ = 0; - } - - instanced_mesh & instanced_mesh::operator = (instanced_mesh && other) - { - if (this == &other) - return *this; - - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - gl::DeleteBuffers(1, &instance_buffer_); - - array_ = other.array_; - buffer_ = other.buffer_; - instance_buffer_ = other.instance_buffer_; - count_ = other.count_; - instance_count_ = other.instance_count_; - stride_ = other.stride_; - instance_stride_ = other.instance_stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.instance_buffer_ = 0; - other.count_ = 0; - other.instance_count_ = 0; - other.stride_ = 0; - other.instance_stride_ = 0; - - return *this; - } - - instanced_mesh::~instanced_mesh() - { - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - gl::DeleteBuffers(1, &instance_buffer_); - } - - instanced_mesh::instanced_mesh(int) - { - array_ = 0; - buffer_ = 0; - instance_buffer_ = 0; - } - - instanced_indexed_mesh instanced_indexed_mesh::null() - { - return instanced_indexed_mesh(0); - } - - instanced_indexed_mesh::instanced_indexed_mesh() - { - gl::GenVertexArrays(1, &array_); - gl::GenBuffers(1, &buffer_); - gl::GenBuffers(1, &index_buffer_); - gl::GenBuffers(1, &instance_buffer_); - } - - instanced_indexed_mesh::instanced_indexed_mesh(instanced_indexed_mesh && other) - { - array_ = other.array_; - buffer_ = other.buffer_; - instance_buffer_ = other.instance_buffer_; - count_ = other.count_; - instance_count_ = other.instance_count_; - stride_ = other.stride_; - instance_stride_ = other.instance_stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.instance_buffer_ = 0; - other.count_ = 0; - other.instance_count_ = 0; - other.stride_ = 0; - other.instance_stride_ = 0; - } - - instanced_indexed_mesh & instanced_indexed_mesh::operator = (instanced_indexed_mesh && other) - { - if (this == &other) - return *this; - - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - gl::DeleteBuffers(1, &index_buffer_); - gl::DeleteBuffers(1, &instance_buffer_); - - array_ = other.array_; - buffer_ = other.buffer_; - instance_buffer_ = other.instance_buffer_; - count_ = other.count_; - instance_count_ = other.instance_count_; - stride_ = other.stride_; - instance_stride_ = other.instance_stride_; - primitive_type_ = other.primitive_type_; - - other.array_ = 0; - other.buffer_ = 0; - other.instance_buffer_ = 0; - other.count_ = 0; - other.instance_count_ = 0; - other.stride_ = 0; - other.instance_stride_ = 0; - - return *this; - } - - instanced_indexed_mesh::~instanced_indexed_mesh() - { - gl::DeleteVertexArrays(1, &array_); - gl::DeleteBuffers(1, &buffer_); - gl::DeleteBuffers(1, &index_buffer_); - gl::DeleteBuffers(1, &instance_buffer_); - } - - instanced_indexed_mesh::instanced_indexed_mesh(int) - { - array_ = 0; - buffer_ = 0; - index_buffer_ = 0; - instance_buffer_ = 0; } } diff --git a/libs/gfx/source/painter.cpp b/libs/gfx/source/painter.cpp index d52110bc..00fa6f9a 100644 --- a/libs/gfx/source/painter.cpp +++ b/libs/gfx/source/painter.cpp @@ -94,8 +94,8 @@ namespace psemek::gfx gfx::program program{vertex_source, fragment_source}; gfx::program text_program{text_vertex_source, text_fragment_source}; - gfx::indexed_mesh mesh; - gfx::indexed_mesh text_mesh; + gfx::mesh mesh; + gfx::mesh text_mesh; std::vector vertices; std::vector indices;