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_vertex_size(std::size_t vertex_size, std::size_t stride);
|
||||||
void check_instance_size(std::size_t instance_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
|
struct mesh
|
||||||
|
|
@ -617,7 +629,7 @@ namespace psemek::gfx
|
||||||
assert(first + count <= count_);
|
assert(first + count <= count_);
|
||||||
|
|
||||||
gl::BindVertexArray(array_);
|
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
|
GLsizei index_count() const
|
||||||
|
|
@ -643,18 +655,6 @@ namespace psemek::gfx
|
||||||
GLenum primitive_type_;
|
GLenum primitive_type_;
|
||||||
|
|
||||||
indexed_mesh(int);
|
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
|
struct instanced_mesh
|
||||||
|
|
@ -786,7 +786,7 @@ namespace psemek::gfx
|
||||||
|
|
||||||
GLsizei instance_count() const
|
GLsizei instance_count() const
|
||||||
{
|
{
|
||||||
return count_;
|
return instance_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum primitive_type() const
|
GLenum primitive_type() const
|
||||||
|
|
@ -810,4 +810,164 @@ namespace psemek::gfx
|
||||||
instanced_mesh(int);
|
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;
|
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
|
* Add more pixmap fonts
|
||||||
* Design ui system
|
* Design ui system
|
||||||
* Add color utilities
|
* Add color utilities
|
||||||
|
|
@ -7,4 +6,4 @@
|
||||||
* gfx: design & implement simple rendering pipelines
|
* gfx: design & implement simple rendering pipelines
|
||||||
* pcg: add clean Generator, Sampler & Pixmap processor concepts, uniformize interfaces, be type & dimension agnostic when possible
|
* pcg: add clean Generator, Sampler & Pixmap processor concepts, uniformize interfaces, be type & dimension agnostic when possible
|
||||||
* pcg: add more vector & point distributions
|
* 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