Remove gfx::vertex, setup meshes using attributes directly
This commit is contained in:
parent
f69fb7299e
commit
0424bae480
3 changed files with 73 additions and 114 deletions
|
|
@ -19,6 +19,9 @@ namespace psemek::gfx
|
||||||
struct normalized
|
struct normalized
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
struct skip
|
||||||
|
{};
|
||||||
|
|
||||||
template <typename Attrib>
|
template <typename Attrib>
|
||||||
struct attrib_traits;
|
struct attrib_traits;
|
||||||
|
|
||||||
|
|
@ -132,111 +135,62 @@ namespace psemek::gfx
|
||||||
static constexpr GLboolean normalized = gl::TRUE_;
|
static constexpr GLboolean normalized = gl::TRUE_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ... Attribs>
|
|
||||||
struct vertex
|
|
||||||
{
|
|
||||||
static constexpr std::size_t size = (0 + ... + sizeof(typename attrib_traits<Attribs>::attrib_type));
|
|
||||||
|
|
||||||
using attribs = std::tuple<Attribs...>;
|
|
||||||
using attrib_types = std::tuple<typename attrib_traits<Attribs>::attrib_type...>;
|
|
||||||
|
|
||||||
template <std::size_t I>
|
|
||||||
static constexpr std::size_t offset()
|
|
||||||
{
|
|
||||||
return offset_impl(std::make_index_sequence<I>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t I>
|
|
||||||
auto & get()
|
|
||||||
{
|
|
||||||
using T = std::tuple_element_t<I, attrib_types>;
|
|
||||||
return *reinterpret_cast<T *>(reinterpret_cast<char *>(&storage) + offset<I>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t I>
|
|
||||||
auto const & get() const
|
|
||||||
{
|
|
||||||
using T = std::tuple_element_t<I, attrib_types>;
|
|
||||||
return *reinterpret_cast<T const *>(reinterpret_cast<char const *>(&storage) + offset<I>());
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex() = default;
|
|
||||||
|
|
||||||
vertex(vertex const & other)
|
|
||||||
{
|
|
||||||
copy_impl(std::make_index_sequence<sizeof...(Attribs)>{}, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex (typename attrib_traits<Attribs>::attrib_type const & ... args)
|
|
||||||
{
|
|
||||||
construct_impl(std::make_index_sequence<sizeof...(Attribs)>{}, args...);
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex & operator = (vertex const & other)
|
|
||||||
{
|
|
||||||
if (this != &other) copy_impl(std::make_index_sequence<sizeof...(Attribs)>{}, other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::aligned_storage_t<size, std::max(std::initializer_list<std::size_t>{alignof(Attribs)...})> storage;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
template <std::size_t ... Is>
|
|
||||||
static constexpr std::size_t offset_impl(std::index_sequence<Is...>)
|
|
||||||
{
|
|
||||||
return (0 + ... + sizeof(std::tuple_element_t<Is, attrib_types>));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t ... Is>
|
|
||||||
void construct_impl(std::index_sequence<Is...>, typename attrib_traits<Attribs>::attrib_type const & ... args)
|
|
||||||
{
|
|
||||||
((get<Is>() = args), ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t ... Is>
|
|
||||||
void copy_impl(std::index_sequence<Is...>, vertex const & other)
|
|
||||||
{
|
|
||||||
((get<Is>() = other.get<Is>()), ...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template <std::size_t ... Is>
|
template <typename Attr>
|
||||||
void enable_attribs(std::index_sequence<Is...>)
|
std::size_t attr_size()
|
||||||
{
|
{
|
||||||
int x[] { ((void) gl::EnableVertexAttribArray(Is), 0) ... };
|
if constexpr (std::is_same_v<Attr, skip>)
|
||||||
(void) x;
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return sizeof(Attr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Vertex, std::size_t I>
|
|
||||||
void attrib_pointer()
|
|
||||||
{
|
|
||||||
using traits = attrib_traits<std::tuple_element_t<I, typename Vertex::attribs>>;
|
|
||||||
gl::VertexAttribPointer(I, traits::size, traits::type, traits::normalized, sizeof(Vertex), reinterpret_cast<char const *>(Vertex::template offset<I>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex, std::size_t ... Is>
|
|
||||||
void attrib_pointers(std::index_sequence<Is...>)
|
|
||||||
{
|
|
||||||
int x[] { ((void) attrib_pointer<Vertex, Is>(), 0) ... };
|
|
||||||
(void) x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex>
|
|
||||||
struct mesh_setup;
|
|
||||||
|
|
||||||
template <typename ... Attribs>
|
template <typename ... Attribs>
|
||||||
struct mesh_setup<vertex<Attribs...>>
|
struct mesh_setup;
|
||||||
{
|
|
||||||
static void setup()
|
|
||||||
{
|
|
||||||
using indices = std::make_index_sequence<sizeof...(Attribs)>;
|
|
||||||
|
|
||||||
enable_attribs(indices{});
|
template <>
|
||||||
attrib_pointers<vertex<Attribs...>>(indices{});
|
struct mesh_setup<>
|
||||||
|
{
|
||||||
|
static std::size_t setup()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_impl(int, std::size_t, std::size_t)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Attr1, typename ... Attribs>
|
||||||
|
struct mesh_setup<Attr1, Attribs...>
|
||||||
|
{
|
||||||
|
static std::size_t setup()
|
||||||
|
{
|
||||||
|
std::size_t const stride = (0 + ... + attr_size<Attribs>());
|
||||||
|
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<Attr1, skip>)
|
||||||
|
{
|
||||||
|
mesh_setup<Attribs...>::setup_impl(index + 1, offset, stride);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using traits = attrib_traits<Attr1>;
|
||||||
|
|
||||||
|
gl::EnableVertexAttribArray(index);
|
||||||
|
gl::VertexAttribPointer(index, traits::size, traits::type, traits::normalized, stride, reinterpret_cast<char const *>(offset));
|
||||||
|
|
||||||
|
mesh_setup<Attribs...>::setup_impl(index + 1, offset + attr_size<Attr1>(), stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -274,25 +228,26 @@ namespace psemek::gfx
|
||||||
mesh(mesh &&);
|
mesh(mesh &&);
|
||||||
mesh(mesh const &) = delete;
|
mesh(mesh const &) = delete;
|
||||||
|
|
||||||
mesh & operator =(mesh &&);
|
mesh & operator = (mesh &&);
|
||||||
mesh & operator =(mesh const &) = delete;
|
mesh & operator = (mesh const &) = delete;
|
||||||
|
|
||||||
~mesh();
|
~mesh();
|
||||||
|
|
||||||
template <typename Vertex>
|
template <typename ... Attribs>
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
static_assert(sizeof(Vertex) == Vertex::size);
|
|
||||||
|
|
||||||
gl::BindVertexArray(array_);
|
gl::BindVertexArray(array_);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||||
|
|
||||||
detail::mesh_setup<Vertex>::setup();
|
stride_ = detail::mesh_setup<Attribs...>::setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Vertex>
|
template <typename Vertex>
|
||||||
void load(std::vector<Vertex> const & vertices, GLenum usage = gl::STREAM_DRAW)
|
void load(std::vector<Vertex> 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::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage);
|
gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage);
|
||||||
|
|
||||||
|
|
@ -318,6 +273,8 @@ namespace psemek::gfx
|
||||||
|
|
||||||
GLsizei count_ = 0;
|
GLsizei count_ = 0;
|
||||||
|
|
||||||
|
std::size_t stride_ = 0;
|
||||||
|
|
||||||
mesh(int);
|
mesh(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -334,13 +291,13 @@ namespace psemek::gfx
|
||||||
|
|
||||||
~indexed_mesh();
|
~indexed_mesh();
|
||||||
|
|
||||||
template <typename Vertex>
|
template <typename ... Attribs>
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
gl::BindVertexArray(array_);
|
gl::BindVertexArray(array_);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||||
|
|
||||||
detail::mesh_setup<Vertex>::setup();
|
stride_ = detail::mesh_setup<Attribs...>::setup();
|
||||||
|
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_);
|
||||||
}
|
}
|
||||||
|
|
@ -348,6 +305,9 @@ namespace psemek::gfx
|
||||||
template <typename Vertex, typename Index>
|
template <typename Vertex, typename Index>
|
||||||
void load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum usage = gl::STREAM_DRAW)
|
void load(std::vector<Vertex> const & vertices, std::vector<Index> 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::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage);
|
gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_);
|
gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_);
|
||||||
|
|
@ -378,6 +338,8 @@ namespace psemek::gfx
|
||||||
GLsizei count_ = 0;
|
GLsizei count_ = 0;
|
||||||
GLenum index_type_ = 0;
|
GLenum index_type_ = 0;
|
||||||
|
|
||||||
|
std::size_t stride_ = 0;
|
||||||
|
|
||||||
indexed_mesh(int);
|
indexed_mesh(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,13 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
indexed_mesh m;
|
indexed_mesh m;
|
||||||
|
|
||||||
using vertex = gfx::vertex<geom::point<float, 2>>;
|
std::vector<geom::point<float, 2>> vertices(4);
|
||||||
|
|
||||||
std::vector<vertex> vertices(4);
|
|
||||||
std::vector<std::uint8_t> indices(6);
|
std::vector<std::uint8_t> indices(6);
|
||||||
|
|
||||||
vertices[0].get<0>() = {-1.f, -1.f};
|
vertices[0] = {-1.f, -1.f};
|
||||||
vertices[1].get<0>() = { 1.f, -1.f};
|
vertices[1] = { 1.f, -1.f};
|
||||||
vertices[2].get<0>() = {-1.f, 1.f};
|
vertices[2] = {-1.f, 1.f};
|
||||||
vertices[3].get<0>() = { 1.f, 1.f};
|
vertices[3] = { 1.f, 1.f};
|
||||||
|
|
||||||
indices[0] = 0;
|
indices[0] = 0;
|
||||||
indices[1] = 1;
|
indices[1] = 1;
|
||||||
|
|
@ -24,7 +22,7 @@ namespace psemek::gfx
|
||||||
indices[4] = 1;
|
indices[4] = 1;
|
||||||
indices[5] = 3;
|
indices[5] = 3;
|
||||||
|
|
||||||
m.setup<vertex>();
|
m.setup<geom::point<float, 2>>();
|
||||||
m.load(vertices, indices, gl::STATIC_DRAW);
|
m.load(vertices, indices, gl::STATIC_DRAW);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|
|
||||||
1
todo.md
1
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
|
* Design affine transforms in geom & use them instead of matrices when appropriate
|
||||||
* Implement pixmap font rendering
|
* Implement pixmap font rendering
|
||||||
* Create a simple generic primive painter
|
* Create a simple generic primive painter
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue