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 skip
|
||||
{};
|
||||
|
||||
template <typename Attrib>
|
||||
struct attrib_traits;
|
||||
|
||||
|
|
@ -132,111 +135,62 @@ namespace psemek::gfx
|
|||
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
|
||||
{
|
||||
|
||||
template <std::size_t ... Is>
|
||||
void enable_attribs(std::index_sequence<Is...>)
|
||||
template <typename Attr>
|
||||
std::size_t attr_size()
|
||||
{
|
||||
int x[] { ((void) gl::EnableVertexAttribArray(Is), 0) ... };
|
||||
(void) x;
|
||||
}
|
||||
|
||||
template <typename Vertex, std::size_t I>
|
||||
void attrib_pointer()
|
||||
if constexpr (std::is_same_v<Attr, skip>)
|
||||
{
|
||||
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>()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Vertex, std::size_t ... Is>
|
||||
void attrib_pointers(std::index_sequence<Is...>)
|
||||
else
|
||||
{
|
||||
int x[] { ((void) attrib_pointer<Vertex, Is>(), 0) ... };
|
||||
(void) x;
|
||||
return sizeof(Attr);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
struct mesh_setup;
|
||||
|
||||
template <typename ... Attribs>
|
||||
struct mesh_setup<vertex<Attribs...>>
|
||||
{
|
||||
static void setup()
|
||||
{
|
||||
using indices = std::make_index_sequence<sizeof...(Attribs)>;
|
||||
struct mesh_setup;
|
||||
|
||||
enable_attribs(indices{});
|
||||
attrib_pointers<vertex<Attribs...>>(indices{});
|
||||
template <>
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -279,20 +233,21 @@ namespace psemek::gfx
|
|||
|
||||
~mesh();
|
||||
|
||||
template <typename Vertex>
|
||||
template <typename ... Attribs>
|
||||
void setup()
|
||||
{
|
||||
static_assert(sizeof(Vertex) == Vertex::size);
|
||||
|
||||
gl::BindVertexArray(array_);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||
|
||||
detail::mesh_setup<Vertex>::setup();
|
||||
stride_ = detail::mesh_setup<Attribs...>::setup();
|
||||
}
|
||||
|
||||
template <typename Vertex>
|
||||
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::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 <typename Vertex>
|
||||
template <typename ... Attribs>
|
||||
void setup()
|
||||
{
|
||||
gl::BindVertexArray(array_);
|
||||
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_);
|
||||
}
|
||||
|
|
@ -348,6 +305,9 @@ namespace psemek::gfx
|
|||
template <typename Vertex, typename Index>
|
||||
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::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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,13 @@ namespace psemek::gfx
|
|||
{
|
||||
indexed_mesh m;
|
||||
|
||||
using vertex = gfx::vertex<geom::point<float, 2>>;
|
||||
|
||||
std::vector<vertex> vertices(4);
|
||||
std::vector<geom::point<float, 2>> vertices(4);
|
||||
std::vector<std::uint8_t> 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<vertex>();
|
||||
m.setup<geom::point<float, 2>>();
|
||||
m.load(vertices, indices, gl::STATIC_DRAW);
|
||||
|
||||
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
|
||||
* Implement pixmap font rendering
|
||||
* Create a simple generic primive painter
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue