Add instanced_indexed_mesh class

This commit is contained in:
Nikita Lisitsa 2020-10-03 15:36:26 +03:00
parent 6a94ca2a1d
commit 2771564b94
3 changed files with 254 additions and 16 deletions

View file

@ -389,6 +389,18 @@ namespace psemek::gfx
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)
{
switch (type)
{
case gl::UNSIGNED_BYTE: return 1;
case gl::UNSIGNED_SHORT: return 2;
case gl::UNSIGNED_INT: return 4;
}
assert(false);
return 0;
}
}
struct mesh
@ -617,7 +629,7 @@ namespace psemek::gfx
assert(first + count <= count_);
gl::BindVertexArray(array_);
gl::DrawElements(primitive_type_, count, index_type_, reinterpret_cast<char const *>(0) + first * index_size(index_type_));
gl::DrawElements(primitive_type_, count, index_type_, reinterpret_cast<char const *>(0) + first * detail::index_size(index_type_));
}
GLsizei index_count() const
@ -643,18 +655,6 @@ namespace psemek::gfx
GLenum primitive_type_;
indexed_mesh(int);
static std::size_t index_size(GLenum type)
{
switch (type)
{
case gl::UNSIGNED_BYTE: return 1;
case gl::UNSIGNED_SHORT: return 2;
case gl::UNSIGNED_INT: return 4;
}
assert(false);
return 0;
}
};
struct instanced_mesh
@ -786,7 +786,7 @@ namespace psemek::gfx
GLsizei instance_count() const
{
return count_;
return instance_count_;
}
GLenum primitive_type() const
@ -810,4 +810,164 @@ namespace psemek::gfx
instanced_mesh(int);
};
struct instanced_indexed_mesh
: drawable
{
static instanced_indexed_mesh null();
instanced_indexed_mesh();
instanced_indexed_mesh(instanced_indexed_mesh &&);
instanced_indexed_mesh(instanced_indexed_mesh const &) = delete;
instanced_indexed_mesh & operator = (instanced_indexed_mesh &&);
instanced_indexed_mesh & operator = (instanced_indexed_mesh const &) = delete;
~instanced_indexed_mesh();
template <typename ... Attribs>
void setup()
{
gl::BindVertexArray(array_);
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
stride_ = detail::instanced_mesh_vertex_setup<Attribs...>::setup();
gl::BindBuffer(gl::ARRAY_BUFFER, instance_buffer_);
instance_stride_ = detail::instanced_mesh_instance_setup<Attribs...>::setup();
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_);
}
template <typename Vertex, typename Index>
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_);
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<Index>;
primitive_type_ = primitive_type;
}
template <typename Vertex, typename Index>
void load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
{
load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage);
}
template <typename Vertex, typename Index, std::size_t N>
void load(Vertex const * vertices, std::size_t vertex_count, geom::simplex<Index, N> const * simplices, std::size_t simplex_count, GLenum usage = gl::STREAM_DRAW)
{
static_assert(sizeof(geom::simplex<Index, N>) == (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<Index const *>(simplices), simplex_count * (N + 1), primitive_type, usage);
}
template <typename Vertex, typename Index, std::size_t N>
void load(std::vector<Vertex> const & vertices, std::vector<geom::simplex<Index, N>> const & simplices, GLenum usage = gl::STREAM_DRAW)
{
load(vertices.data(), vertices.size(), simplices.data(), simplices.size(), usage);
}
template <typename Instance>
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 <typename Instance>
void load_instance(std::vector<Instance> 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<char const *>(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);
};
}

View file

@ -231,4 +231,83 @@ namespace psemek::gfx
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;
}
}

View file

@ -1,4 +1,3 @@
* Design affine transforms in geom & use them instead of matrices when appropriate
* Add more pixmap fonts
* Design ui system
* Add color utilities
@ -7,4 +6,4 @@
* gfx: design & implement simple rendering pipelines
* pcg: add clean Generator, Sampler & Pixmap processor concepts, uniformize interfaces, be type & dimension agnostic when possible
* pcg: add more vector & point distributions
* pcg: make template fractal generator, replace fractal_perlin with it
* gfx: unify 4 mesh classes somehow