Add instanced_indexed_mesh class
This commit is contained in:
parent
6a94ca2a1d
commit
2771564b94
3 changed files with 254 additions and 16 deletions
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
3
todo.md
3
todo.md
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue