From 0424bae48085f7c0e6b5a17a5ac71cce4446539b Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 28 Aug 2020 11:15:49 +0300 Subject: [PATCH] Remove gfx::vertex, setup meshes using attributes directly --- libs/gfx/include/psemek/gfx/mesh.hpp | 172 +++++++++++---------------- libs/gfx/source/gfx/fullscreen.cpp | 14 +-- todo.md | 1 - 3 files changed, 73 insertions(+), 114 deletions(-) diff --git a/libs/gfx/include/psemek/gfx/mesh.hpp b/libs/gfx/include/psemek/gfx/mesh.hpp index 3ed232d5..5f5d0497 100644 --- a/libs/gfx/include/psemek/gfx/mesh.hpp +++ b/libs/gfx/include/psemek/gfx/mesh.hpp @@ -19,6 +19,9 @@ namespace psemek::gfx struct normalized {}; + struct skip + {}; + template struct attrib_traits; @@ -132,111 +135,62 @@ namespace psemek::gfx static constexpr GLboolean normalized = gl::TRUE_; }; - template - struct vertex - { - static constexpr std::size_t size = (0 + ... + sizeof(typename attrib_traits::attrib_type)); - - using attribs = std::tuple; - using attrib_types = std::tuple::attrib_type...>; - - template - static constexpr std::size_t offset() - { - return offset_impl(std::make_index_sequence{}); - } - - template - auto & get() - { - using T = std::tuple_element_t; - return *reinterpret_cast(reinterpret_cast(&storage) + offset()); - } - - template - auto const & get() const - { - using T = std::tuple_element_t; - return *reinterpret_cast(reinterpret_cast(&storage) + offset()); - } - - vertex() = default; - - vertex(vertex const & other) - { - copy_impl(std::make_index_sequence{}, other); - } - - vertex (typename attrib_traits::attrib_type const & ... args) - { - construct_impl(std::make_index_sequence{}, args...); - } - - vertex & operator = (vertex const & other) - { - if (this != &other) copy_impl(std::make_index_sequence{}, other); - return *this; - } - - std::aligned_storage_t{alignof(Attribs)...})> storage; - - private: - - template - static constexpr std::size_t offset_impl(std::index_sequence) - { - return (0 + ... + sizeof(std::tuple_element_t)); - } - - template - void construct_impl(std::index_sequence, typename attrib_traits::attrib_type const & ... args) - { - ((get() = args), ...); - } - - template - void copy_impl(std::index_sequence, vertex const & other) - { - ((get() = other.get()), ...); - } - }; - namespace detail { - template - void enable_attribs(std::index_sequence) + template + std::size_t attr_size() { - int x[] { ((void) gl::EnableVertexAttribArray(Is), 0) ... }; - (void) x; + if constexpr (std::is_same_v) + { + return 0; + } + else + { + return sizeof(Attr); + } } - template - void attrib_pointer() - { - using traits = attrib_traits>; - gl::VertexAttribPointer(I, traits::size, traits::type, traits::normalized, sizeof(Vertex), reinterpret_cast(Vertex::template offset())); - } - - template - void attrib_pointers(std::index_sequence) - { - int x[] { ((void) attrib_pointer(), 0) ... }; - (void) x; - } - - template - struct mesh_setup; - template - struct mesh_setup> - { - static void setup() - { - using indices = std::make_index_sequence; + struct mesh_setup; - enable_attribs(indices{}); - attrib_pointers>(indices{}); + template <> + struct mesh_setup<> + { + static std::size_t setup() + { + return 0; + } + + static void setup_impl(int, std::size_t, std::size_t) + {} + }; + + template + struct mesh_setup + { + static std::size_t setup() + { + std::size_t const stride = (0 + ... + attr_size()); + setup_impl(0, 0, stride); + return stride; + } + + static void setup_impl(int index, std::size_t offset, std::size_t stride) + { + if constexpr (std::is_same_v) + { + mesh_setup::setup_impl(index + 1, offset, stride); + } + else + { + using traits = attrib_traits; + + gl::EnableVertexAttribArray(index); + gl::VertexAttribPointer(index, traits::size, traits::type, traits::normalized, stride, reinterpret_cast(offset)); + + mesh_setup::setup_impl(index + 1, offset + attr_size(), stride); + } } }; @@ -274,25 +228,26 @@ namespace psemek::gfx mesh(mesh &&); mesh(mesh const &) = delete; - mesh & operator =(mesh &&); - mesh & operator =(mesh const &) = delete; + mesh & operator = (mesh &&); + mesh & operator = (mesh const &) = delete; ~mesh(); - template + template void setup() { - static_assert(sizeof(Vertex) == Vertex::size); - gl::BindVertexArray(array_); gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - detail::mesh_setup::setup(); + stride_ = detail::mesh_setup::setup(); } template void load(std::vector const & vertices, GLenum usage = gl::STREAM_DRAW) { + if (sizeof(Vertex) != stride_) + throw std::runtime_error("Vertex size not equal to sum of attribute sizes"); + gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage); @@ -318,6 +273,8 @@ namespace psemek::gfx GLsizei count_ = 0; + std::size_t stride_ = 0; + mesh(int); }; @@ -334,13 +291,13 @@ namespace psemek::gfx ~indexed_mesh(); - template + template void setup() { gl::BindVertexArray(array_); gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); - detail::mesh_setup::setup(); + stride_ = detail::mesh_setup::setup(); gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_); } @@ -348,6 +305,9 @@ namespace psemek::gfx template void load(std::vector const & vertices, std::vector const & indices, GLenum usage = gl::STREAM_DRAW) { + if (sizeof(Vertex) != stride_) + throw std::runtime_error("Vertex size not equal to sum of attribute sizes"); + gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage); gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_); @@ -378,6 +338,8 @@ namespace psemek::gfx GLsizei count_ = 0; GLenum index_type_ = 0; + std::size_t stride_ = 0; + indexed_mesh(int); }; diff --git a/libs/gfx/source/gfx/fullscreen.cpp b/libs/gfx/source/gfx/fullscreen.cpp index 12f0f295..0cb311d3 100644 --- a/libs/gfx/source/gfx/fullscreen.cpp +++ b/libs/gfx/source/gfx/fullscreen.cpp @@ -7,15 +7,13 @@ namespace psemek::gfx { indexed_mesh m; - using vertex = gfx::vertex>; - - std::vector vertices(4); + std::vector> vertices(4); std::vector indices(6); - vertices[0].get<0>() = {-1.f, -1.f}; - vertices[1].get<0>() = { 1.f, -1.f}; - vertices[2].get<0>() = {-1.f, 1.f}; - vertices[3].get<0>() = { 1.f, 1.f}; + vertices[0] = {-1.f, -1.f}; + vertices[1] = { 1.f, -1.f}; + vertices[2] = {-1.f, 1.f}; + vertices[3] = { 1.f, 1.f}; indices[0] = 0; indices[1] = 1; @@ -24,7 +22,7 @@ namespace psemek::gfx indices[4] = 1; indices[5] = 3; - m.setup(); + m.setup>(); m.load(vertices, indices, gl::STATIC_DRAW); return m; diff --git a/todo.md b/todo.md index e0cd4ff1..7c86ce72 100644 --- a/todo.md +++ b/todo.md @@ -1,4 +1,3 @@ -* Remove gfx::vertex, setup mesh using attributes directly * Design affine transforms in geom & use them instead of matrices when appropriate * Implement pixmap font rendering * Create a simple generic primive painter