Refactor meshes: single unified mesh class
This commit is contained in:
parent
726b8486c7
commit
e9af93b747
8 changed files with 294 additions and 818 deletions
|
|
@ -173,9 +173,9 @@ struct cloud_app
|
||||||
std::vector<geom::point<float, 3>> bbox_vertices;
|
std::vector<geom::point<float, 3>> bbox_vertices;
|
||||||
std::vector<geom::segment<std::uint32_t>> bbox_edges;
|
std::vector<geom::segment<std::uint32_t>> bbox_edges;
|
||||||
|
|
||||||
gfx::indexed_mesh bbox_mesh;
|
gfx::mesh bbox_mesh;
|
||||||
|
|
||||||
gfx::indexed_mesh slice_mesh;
|
gfx::mesh slice_mesh;
|
||||||
|
|
||||||
gfx::mesh light_mesh;
|
gfx::mesh light_mesh;
|
||||||
std::vector<geom::vector<float, 3>> dirs;
|
std::vector<geom::vector<float, 3>> dirs;
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ private:
|
||||||
|
|
||||||
gfx::program program_{vertex_source, fragment_source};
|
gfx::program program_{vertex_source, fragment_source};
|
||||||
|
|
||||||
gfx::instanced_mesh mesh_;
|
gfx::mesh mesh_;
|
||||||
|
|
||||||
gfx::texture_2d texture_;
|
gfx::texture_2d texture_;
|
||||||
gfx::texture_2d noise_texture_;
|
gfx::texture_2d noise_texture_;
|
||||||
|
|
@ -229,7 +229,6 @@ void candle_renderer::render(geom::camera const & camera, float time)
|
||||||
texture_.bind();
|
texture_.bind();
|
||||||
gl::ActiveTexture(gl::TEXTURE1);
|
gl::ActiveTexture(gl::TEXTURE1);
|
||||||
noise_texture_.bind();
|
noise_texture_.bind();
|
||||||
(void)time;
|
|
||||||
mesh_.draw();
|
mesh_.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -173,10 +173,10 @@ struct grass_app
|
||||||
pcg::perlin<float, 2> density;
|
pcg::perlin<float, 2> density;
|
||||||
|
|
||||||
gfx::program ground_program{ground_vs, ground_fs};
|
gfx::program ground_program{ground_vs, ground_fs};
|
||||||
gfx::indexed_mesh ground_mesh;
|
gfx::mesh ground_mesh;
|
||||||
|
|
||||||
gfx::program grass_program{grass_vs, grass_fs};
|
gfx::program grass_program{grass_vs, grass_fs};
|
||||||
gfx::indexed_mesh grass_mesh;
|
gfx::mesh grass_mesh;
|
||||||
gfx::texture_1d grass_texture;
|
gfx::texture_1d grass_texture;
|
||||||
|
|
||||||
gfx::program grass_slice_program{grass_slice_vs, grass_slice_fs};
|
gfx::program grass_slice_program{grass_slice_vs, grass_slice_fs};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
indexed_mesh const & fullscreen_quad();
|
mesh const & fullscreen_quad();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <psemek/gfx/gl.hpp>
|
#include <psemek/gfx/gl.hpp>
|
||||||
#include <psemek/gfx/drawable.hpp>
|
#include <psemek/gfx/drawable.hpp>
|
||||||
|
#include <psemek/gfx/array.hpp>
|
||||||
|
#include <psemek/gfx/buffer.hpp>
|
||||||
|
|
||||||
#include <psemek/geom/vector.hpp>
|
#include <psemek/geom/vector.hpp>
|
||||||
#include <psemek/geom/point.hpp>
|
#include <psemek/geom/point.hpp>
|
||||||
|
|
@ -386,10 +388,7 @@ namespace psemek::gfx
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static constexpr GLenum gl_type_v = gl_type<T>::value;
|
static constexpr GLenum gl_type_v = gl_type<T>::value;
|
||||||
|
|
||||||
void check_vertex_size(std::size_t vertex_size, std::size_t stride);
|
inline std::size_t index_size(GLenum type)
|
||||||
void check_instance_size(std::size_t instance_size, std::size_t stride);
|
|
||||||
|
|
||||||
static std::size_t index_size(GLenum type)
|
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
@ -401,573 +400,277 @@ namespace psemek::gfx
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
GLenum get_primitive_type()
|
||||||
|
{
|
||||||
|
if constexpr (N == 0)
|
||||||
|
{
|
||||||
|
return gl::POINTS;
|
||||||
|
}
|
||||||
|
else if constexpr (N == 1)
|
||||||
|
{
|
||||||
|
return gl::LINES;
|
||||||
|
}
|
||||||
|
else if constexpr (N == 2)
|
||||||
|
{
|
||||||
|
return gl::TRIANGLES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert("unknown primitive type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::optional<std::size_t> get_primitive_type_vertex_count(GLenum type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case gl::LINES:
|
||||||
|
return 2;
|
||||||
|
case gl::TRIANGLES:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ... Args>
|
||||||
|
struct has_instanced_attribs_impl
|
||||||
|
: std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename T, typename ... Args>
|
||||||
|
struct has_instanced_attribs_impl<T, Args...>
|
||||||
|
: has_instanced_attribs_impl<Args...>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename T, typename ... Args>
|
||||||
|
struct has_instanced_attribs_impl<instanced<T>, Args...>
|
||||||
|
: std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename ... Args>
|
||||||
|
constexpr bool has_instanced_attribs = has_instanced_attribs_impl<Args...>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A generic mesh class
|
||||||
|
* Supports both indexed & non-indexed rendering
|
||||||
|
* Supports both instanced & non-instanced rendering
|
||||||
|
* Checks vertex & instance size, may throw on load
|
||||||
|
* Strong exception guarantees
|
||||||
|
*/
|
||||||
|
|
||||||
struct mesh
|
struct mesh
|
||||||
: drawable
|
: drawable
|
||||||
{
|
{
|
||||||
static mesh null();
|
mesh() = default;
|
||||||
|
|
||||||
mesh();
|
|
||||||
mesh(mesh &&);
|
mesh(mesh &&);
|
||||||
mesh(mesh const &) = delete;
|
|
||||||
|
|
||||||
mesh & operator = (mesh &&);
|
mesh & operator = (mesh &&);
|
||||||
|
|
||||||
|
mesh(mesh const &) = delete;
|
||||||
mesh & operator = (mesh const &) = delete;
|
mesh & operator = (mesh const &) = delete;
|
||||||
|
|
||||||
~mesh();
|
|
||||||
|
|
||||||
template <typename ... Attribs>
|
template <typename ... Attribs>
|
||||||
void setup()
|
void setup();
|
||||||
{
|
|
||||||
gl::BindVertexArray(array_);
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
|
||||||
|
|
||||||
stride_ = detail::mesh_setup<Attribs...>::setup();
|
// Non-indexed vertex data
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex>
|
template <typename Vertex>
|
||||||
void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW);
|
||||||
{
|
|
||||||
detail::check_vertex_size(sizeof(Vertex), stride_);
|
|
||||||
|
|
||||||
switch (primitive_type)
|
|
||||||
{
|
|
||||||
case gl::LINES:
|
|
||||||
if ((count % 2) != 0) throw std::runtime_error("Vertex count for GL_LINES should be a multiple of 2");
|
|
||||||
break;
|
|
||||||
case gl::TRIANGLES:
|
|
||||||
if ((count % 3) != 0) throw std::runtime_error("Vertex count for GL_TRIANGLES should be a multiple of 3");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Vertex), vertices, usage);
|
|
||||||
|
|
||||||
count_ = count;
|
|
||||||
primitive_type_ = primitive_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex>
|
template <typename Vertex>
|
||||||
void load(std::vector<Vertex> const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
void load(std::vector<Vertex> const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW);
|
||||||
{
|
|
||||||
load(vertices.data(), vertices.size(), primitive_type, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex, std::size_t N>
|
template <typename Vertex, std::size_t N>
|
||||||
void load(geom::simplex<Vertex, N> const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW)
|
void load(geom::simplex<Vertex, N> const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW);
|
||||||
{
|
|
||||||
static_assert(sizeof(geom::simplex<Vertex, N>) == (N + 1) * sizeof(Vertex));
|
|
||||||
|
|
||||||
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(reinterpret_cast<Vertex const *>(simplices), count * (N + 1), primitive_type, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex, std::size_t N>
|
template <typename Vertex, std::size_t N>
|
||||||
void load(std::vector<geom::simplex<Vertex, N>> const & simplices, GLenum usage = gl::STREAM_DRAW)
|
void load(std::vector<geom::simplex<Vertex, N>> const & simplices, GLenum usage = gl::STREAM_DRAW);
|
||||||
{
|
|
||||||
load(simplices.data(), simplices.size(), usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw() const override
|
// Indexed vertex data
|
||||||
{
|
|
||||||
draw(0, count_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(GLsizei first, GLsizei count) const
|
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);
|
||||||
assert(first + count <= count_);
|
|
||||||
|
|
||||||
if (count == 0) return;
|
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);
|
||||||
|
|
||||||
gl::BindVertexArray(array_);
|
template <typename Vertex, typename Index, std::size_t N>
|
||||||
gl::DrawArrays(primitive_type_, first, count);
|
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);
|
||||||
}
|
|
||||||
|
|
||||||
GLsizei count() const
|
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);
|
||||||
return count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum primitive_type() const
|
// Instance data
|
||||||
{
|
|
||||||
return primitive_type_;
|
template <typename Instance>
|
||||||
}
|
void load_instance(Instance const * instances, std::size_t count, GLenum usage = gl::STREAM_DRAW);
|
||||||
|
|
||||||
|
template <typename Instance>
|
||||||
|
void load_instance(std::vector<Instance> const & instances, GLenum usage = gl::STREAM_DRAW);
|
||||||
|
|
||||||
|
// Info
|
||||||
|
|
||||||
|
bool is_indexed() const { return info_.indexed_; }
|
||||||
|
bool is_instanced() const { return info_.instanced_; }
|
||||||
|
|
||||||
|
std::size_t vertex_count() const { return info_.vertex_count_; }
|
||||||
|
std::size_t index_count() const { return info_.index_count_; }
|
||||||
|
std::size_t instance_count() const { return info_.instance_count_; }
|
||||||
|
|
||||||
|
std::size_t count() const; // total vertex count = number of vertex shader executions
|
||||||
|
|
||||||
|
GLenum primitive_type() const { return info_.primitive_type_; }
|
||||||
|
GLenum index_type() const { return info_.index_type_; }
|
||||||
|
|
||||||
|
// Drawing commands
|
||||||
|
|
||||||
|
void draw() const override;
|
||||||
|
|
||||||
|
void draw(std::size_t first, std::size_t count, std::size_t instance_count = 0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint array_;
|
array array_;
|
||||||
GLuint buffer_;
|
buffer vertex_buffer_ = buffer::null();
|
||||||
|
buffer index_buffer_ = buffer::null();
|
||||||
|
buffer instance_buffer_ = buffer::null();
|
||||||
|
|
||||||
GLsizei count_ = 0;
|
struct mesh_info
|
||||||
|
{
|
||||||
|
bool indexed_ = false;
|
||||||
|
bool instanced_ = false;
|
||||||
|
|
||||||
std::size_t stride_ = 0;
|
std::size_t vertex_count_ = 0;
|
||||||
|
std::size_t index_count_ = 0;
|
||||||
|
std::size_t instance_count_ = 0;
|
||||||
|
|
||||||
GLenum primitive_type_;
|
std::size_t stride_ = 0;
|
||||||
|
std::size_t instance_stride_ = 0;
|
||||||
|
|
||||||
mesh(int);
|
GLenum primitive_type_;
|
||||||
|
GLenum index_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
mesh_info info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct indexed_mesh
|
template <typename ... Attribs>
|
||||||
: drawable
|
void mesh::setup()
|
||||||
{
|
{
|
||||||
static indexed_mesh null();
|
array_.bind();
|
||||||
|
|
||||||
indexed_mesh();
|
if (!vertex_buffer_) vertex_buffer_ = buffer{};
|
||||||
indexed_mesh(indexed_mesh &&);
|
vertex_buffer_.bind();
|
||||||
indexed_mesh(indexed_mesh const &) = delete;
|
info_.stride_ = detail::instanced_mesh_vertex_setup<Attribs...>::setup();
|
||||||
|
|
||||||
indexed_mesh & operator =(indexed_mesh &&);
|
if constexpr (detail::has_instanced_attribs<Attribs...>)
|
||||||
indexed_mesh & operator =(indexed_mesh const &) = delete;
|
|
||||||
|
|
||||||
~indexed_mesh();
|
|
||||||
|
|
||||||
template <typename ... Attribs>
|
|
||||||
void setup()
|
|
||||||
{
|
{
|
||||||
gl::BindVertexArray(array_);
|
if (!instance_buffer_) instance_buffer_ = buffer{};
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
instance_buffer_.bind();
|
||||||
|
info_.instance_stride_ = detail::instanced_mesh_instance_setup<Attribs...>::setup();
|
||||||
stride_ = detail::mesh_setup<Attribs...>::setup();
|
info_.instanced_ = true;
|
||||||
|
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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_);
|
info_.instance_stride_ = 0;
|
||||||
|
info_.instanced_ = false;
|
||||||
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>
|
template <typename Vertex>
|
||||||
void load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
void mesh::load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage)
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw() const override
|
|
||||||
{
|
|
||||||
draw(0, count_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(GLsizei first, GLsizei count) const
|
|
||||||
{
|
|
||||||
if (count == 0) return;
|
|
||||||
assert(first + count <= count_);
|
|
||||||
|
|
||||||
gl::BindVertexArray(array_);
|
|
||||||
gl::DrawElements(primitive_type_, count, index_type_, reinterpret_cast<char const *>(0) + first * detail::index_size(index_type_));
|
|
||||||
}
|
|
||||||
|
|
||||||
GLsizei index_count() const
|
|
||||||
{
|
|
||||||
return count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum primitive_type() const
|
|
||||||
{
|
|
||||||
return primitive_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLuint array_;
|
|
||||||
GLuint buffer_;
|
|
||||||
GLuint index_buffer_;
|
|
||||||
|
|
||||||
GLsizei count_ = 0;
|
|
||||||
GLenum index_type_ = 0;
|
|
||||||
|
|
||||||
std::size_t stride_ = 0;
|
|
||||||
|
|
||||||
GLenum primitive_type_;
|
|
||||||
|
|
||||||
indexed_mesh(int);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct instanced_mesh
|
|
||||||
: drawable
|
|
||||||
{
|
{
|
||||||
static instanced_mesh null();
|
assert(info_.stride_ == sizeof(Vertex));
|
||||||
|
|
||||||
instanced_mesh();
|
if (auto n = detail::get_primitive_type_vertex_count(primitive_type); n)
|
||||||
instanced_mesh(instanced_mesh &&);
|
assert((count % (*n)) == 0);
|
||||||
instanced_mesh(instanced_mesh const &) = delete;
|
|
||||||
|
|
||||||
instanced_mesh & operator = (instanced_mesh &&);
|
assert(vertex_buffer_);
|
||||||
instanced_mesh & operator = (instanced_mesh const &) = delete;
|
|
||||||
|
|
||||||
~instanced_mesh();
|
vertex_buffer_.load(vertices, count, usage);
|
||||||
|
info_.vertex_count_ = count;
|
||||||
|
info_.index_count_ = 0;
|
||||||
|
info_.indexed_ = false;
|
||||||
|
info_.primitive_type_ = primitive_type;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ... Attribs>
|
template <typename Vertex>
|
||||||
void setup()
|
void mesh::load(std::vector<Vertex> const & vertices, GLenum primitive_type, GLenum usage)
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex>
|
|
||||||
void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
|
||||||
{
|
|
||||||
detail::check_vertex_size(sizeof(Vertex), stride_);
|
|
||||||
|
|
||||||
switch (primitive_type)
|
|
||||||
{
|
|
||||||
case gl::LINES:
|
|
||||||
if ((count % 2) != 0) throw std::runtime_error("Vertex count for GL_LINES should be a multiple of 2");
|
|
||||||
break;
|
|
||||||
case gl::TRIANGLES:
|
|
||||||
if ((count % 3) != 0) throw std::runtime_error("Vertex count for GL_TRIANGLES should be a multiple of 3");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Vertex), vertices, usage);
|
|
||||||
|
|
||||||
count_ = count;
|
|
||||||
primitive_type_ = primitive_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex>
|
|
||||||
void load(std::vector<Vertex> const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
|
||||||
{
|
|
||||||
load(vertices.data(), vertices.size(), primitive_type, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex, std::size_t N>
|
|
||||||
void load(geom::simplex<Vertex, N> const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(geom::simplex<Vertex, N>) == (N + 1) * sizeof(Vertex));
|
|
||||||
|
|
||||||
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(reinterpret_cast<Vertex const *>(simplices), count * (N + 1), primitive_type, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex, std::size_t N>
|
|
||||||
void load(std::vector<geom::simplex<Vertex, N>> const & simplices, GLenum usage = gl::STREAM_DRAW)
|
|
||||||
{
|
|
||||||
load(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::DrawArraysInstanced(primitive_type_, first, count, instance_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLsizei count() const
|
|
||||||
{
|
|
||||||
return count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLsizei instance_count() const
|
|
||||||
{
|
|
||||||
return instance_count_;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum primitive_type() const
|
|
||||||
{
|
|
||||||
return primitive_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLuint array_;
|
|
||||||
GLuint buffer_;
|
|
||||||
GLuint instance_buffer_;
|
|
||||||
|
|
||||||
GLsizei count_ = 0;
|
|
||||||
GLsizei instance_count_ = 0;
|
|
||||||
|
|
||||||
std::size_t stride_ = 0;
|
|
||||||
std::size_t instance_stride_ = 0;
|
|
||||||
|
|
||||||
GLenum primitive_type_;
|
|
||||||
|
|
||||||
instanced_mesh(int);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct instanced_indexed_mesh
|
|
||||||
: drawable
|
|
||||||
{
|
{
|
||||||
static instanced_indexed_mesh null();
|
load(vertices.data(), vertices.size(), primitive_type, usage);
|
||||||
|
}
|
||||||
|
|
||||||
instanced_indexed_mesh();
|
template <typename Vertex, std::size_t N>
|
||||||
instanced_indexed_mesh(instanced_indexed_mesh &&);
|
void mesh::load(geom::simplex<Vertex, N> const * simplices, std::size_t count, GLenum usage)
|
||||||
instanced_indexed_mesh(instanced_indexed_mesh const &) = delete;
|
{
|
||||||
|
static_assert(sizeof(Vertex) * (N + 1) == sizeof(simplices[0]));
|
||||||
|
load(reinterpret_cast<Vertex const *>(simplices), count * (N + 1), detail::get_primitive_type<N>(), usage);
|
||||||
|
}
|
||||||
|
|
||||||
instanced_indexed_mesh & operator = (instanced_indexed_mesh &&);
|
template <typename Vertex, std::size_t N>
|
||||||
instanced_indexed_mesh & operator = (instanced_indexed_mesh const &) = delete;
|
void mesh::load(std::vector<geom::simplex<Vertex, N>> const & simplices, GLenum usage)
|
||||||
|
{
|
||||||
|
load(simplices.data(), simplices.size(), usage);
|
||||||
|
}
|
||||||
|
|
||||||
~instanced_indexed_mesh();
|
template <typename Vertex, typename Index>
|
||||||
|
void mesh::load(Vertex const * vertices, std::size_t vertex_count, Index const * indices, std::size_t index_count, GLenum primitive_type, GLenum usage)
|
||||||
|
{
|
||||||
|
assert(info_.stride_ == sizeof(Vertex));
|
||||||
|
|
||||||
template <typename ... Attribs>
|
if (auto n = detail::get_primitive_type_vertex_count(primitive_type); n)
|
||||||
void setup()
|
assert((index_count % (*n)) == 0);
|
||||||
|
|
||||||
|
assert(vertex_buffer_);
|
||||||
|
|
||||||
|
if (!index_buffer_)
|
||||||
{
|
{
|
||||||
gl::BindVertexArray(array_);
|
index_buffer_ = buffer{};
|
||||||
|
array_.bind();
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_.id());
|
||||||
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_);
|
|
||||||
}
|
}
|
||||||
|
vertex_buffer_.load(vertices, vertex_count, usage);
|
||||||
|
index_buffer_.load(indices, index_count, usage);
|
||||||
|
info_.vertex_count_ = vertex_count;
|
||||||
|
info_.index_count_ = index_count;
|
||||||
|
info_.indexed_ = true;
|
||||||
|
info_.primitive_type_ = primitive_type;
|
||||||
|
info_.index_type_ = detail::gl_type_v<Index>;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Vertex, typename Index>
|
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)
|
void mesh::load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum primitive_type, GLenum usage)
|
||||||
{
|
{
|
||||||
detail::check_vertex_size(sizeof(Vertex), stride_);
|
load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage);
|
||||||
|
}
|
||||||
|
|
||||||
switch (primitive_type)
|
template <typename Vertex, typename Index, std::size_t N>
|
||||||
{
|
void mesh::load(Vertex const * vertices, std::size_t vertex_count, geom::simplex<Index, N> const * simplices, std::size_t simplex_count, GLenum usage)
|
||||||
case gl::LINES:
|
{
|
||||||
if ((index_count % 2) != 0) throw std::runtime_error("Index count for GL_LINES should be a multiple of 2");
|
static_assert(sizeof(Index) * (N + 1) == sizeof(simplices[0]));
|
||||||
break;
|
load(vertices, vertex_count, reinterpret_cast<Index const *>(simplices), (N + 1) * simplex_count, detail::get_primitive_type<N>(), usage);
|
||||||
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_);
|
template <typename Vertex, typename Index, std::size_t N>
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, vertex_count * sizeof(Vertex), vertices, usage);
|
void mesh::load(std::vector<Vertex> const & vertices, std::vector<geom::simplex<Index, N>> const & simplices, GLenum usage)
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_);
|
{
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, index_count * sizeof(Index), indices, usage);
|
load(vertices.data(), vertices.size(), simplices.data(), simplices.size(), usage);
|
||||||
|
}
|
||||||
|
|
||||||
count_ = index_count;
|
template <typename Instance>
|
||||||
index_type_ = detail::gl_type_v<Index>;
|
void mesh::load_instance(Instance const * instances, std::size_t count, GLenum usage)
|
||||||
primitive_type_ = primitive_type;
|
{
|
||||||
}
|
assert(info_.instance_stride_ == sizeof(Instance));
|
||||||
|
|
||||||
template <typename Vertex, typename Index>
|
assert(instance_buffer_);
|
||||||
void load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
instance_buffer_.load(instances, count, usage);
|
||||||
{
|
info_.instance_count_ = count;
|
||||||
load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Vertex, typename Index, std::size_t N>
|
template <typename Instance>
|
||||||
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)
|
void mesh::load_instance(std::vector<Instance> const & instances, GLenum usage)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(geom::simplex<Index, N>) == (N + 1) * sizeof(Index));
|
load_instance(instances.data(), instances.size(), usage);
|
||||||
|
}
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
static indexed_mesh create_fullscreen_quad()
|
static mesh create_fullscreen_quad()
|
||||||
{
|
{
|
||||||
indexed_mesh m;
|
mesh m;
|
||||||
|
|
||||||
std::vector<geom::point<float, 2>> vertices(4);
|
std::vector<geom::point<float, 2>> vertices(4);
|
||||||
std::vector<std::uint8_t> indices(6);
|
std::vector<std::uint8_t> indices(6);
|
||||||
|
|
@ -28,9 +28,9 @@ namespace psemek::gfx
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
indexed_mesh const & fullscreen_quad()
|
mesh const & fullscreen_quad()
|
||||||
{
|
{
|
||||||
static indexed_mesh m = create_fullscreen_quad();
|
static mesh m = create_fullscreen_quad();
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,309 +5,83 @@
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
void check_vertex_size(std::size_t vertex_size, std::size_t stride)
|
|
||||||
{
|
|
||||||
if (vertex_size != stride)
|
|
||||||
throw std::runtime_error(util::to_string("Vertex size (", vertex_size, ") not equal to sum of attribute sizes (", stride, ")"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_instance_size(std::size_t instance_size, std::size_t stride)
|
|
||||||
{
|
|
||||||
if (instance_size != stride)
|
|
||||||
throw std::runtime_error(util::to_string("Instance size (", instance_size, ") not equal to sum of instanced attribute sizes (", stride, ")"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh mesh::null()
|
|
||||||
{
|
|
||||||
return mesh(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh::mesh()
|
|
||||||
{
|
|
||||||
gl::GenVertexArrays(1, &array_);
|
|
||||||
gl::GenBuffers(1, &buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh::mesh(mesh && other)
|
mesh::mesh(mesh && other)
|
||||||
|
: array_{std::move(other.array_)}
|
||||||
|
, vertex_buffer_{std::move(other.vertex_buffer_)}
|
||||||
|
, index_buffer_{std::move(other.index_buffer_)}
|
||||||
|
, instance_buffer_{std::move(other.instance_buffer_)}
|
||||||
|
, info_{other.info_}
|
||||||
{
|
{
|
||||||
array_ = other.array_;
|
other.info_ = mesh_info{};
|
||||||
buffer_ = other.buffer_;
|
|
||||||
count_ = other.count_;
|
|
||||||
stride_ = other.stride_;
|
|
||||||
primitive_type_ = other.primitive_type_;
|
|
||||||
|
|
||||||
other.array_ = 0;
|
|
||||||
other.buffer_ = 0;
|
|
||||||
other.count_ = 0;
|
|
||||||
other.stride_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh & mesh::operator =(mesh && other)
|
mesh & mesh::operator = (mesh && other)
|
||||||
{
|
{
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
|
|
||||||
if (array_)
|
array_ = std::move(other.array_);
|
||||||
|
vertex_buffer_ = std::move(other.vertex_buffer_);
|
||||||
|
index_buffer_ = std::move(other.index_buffer_);
|
||||||
|
instance_buffer_ = std::move(other.instance_buffer_);
|
||||||
|
info_ = other.info_;
|
||||||
|
other.info_ = mesh_info{};
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh::draw() const
|
||||||
|
{
|
||||||
|
draw(0, is_indexed() ? index_count() : vertex_count(), instance_count());
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh::draw(std::size_t first, std::size_t count, std::size_t instance_count) const
|
||||||
|
{
|
||||||
|
if (is_indexed())
|
||||||
{
|
{
|
||||||
gl::DeleteVertexArrays(1, &array_);
|
assert(first + count <= index_count());
|
||||||
gl::DeleteBuffers(1, &buffer_);
|
|
||||||
|
if (is_instanced())
|
||||||
|
{
|
||||||
|
assert(instance_count <= this->instance_count());
|
||||||
|
|
||||||
|
if (count != 0 && instance_count != 0)
|
||||||
|
{
|
||||||
|
array_.bind();
|
||||||
|
gl::DrawElementsInstanced(primitive_type(), count, index_type(), reinterpret_cast<char const *>(detail::index_size(index_type()) * first), instance_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
array_.bind();
|
||||||
|
gl::DrawElements(primitive_type(), count, index_type(), reinterpret_cast<char const *>(detail::index_size(index_type()) * first));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
array_ = other.array_;
|
|
||||||
buffer_ = other.buffer_;
|
|
||||||
count_ = other.count_;
|
|
||||||
stride_ = other.stride_;
|
|
||||||
primitive_type_ = other.primitive_type_;
|
|
||||||
|
|
||||||
other.array_ = 0;
|
|
||||||
other.buffer_ = 0;
|
|
||||||
other.count_ = 0;
|
|
||||||
other.stride_ = 0;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh::~mesh()
|
|
||||||
{
|
|
||||||
gl::DeleteVertexArrays(1, &array_);
|
|
||||||
gl::DeleteBuffers(1, &buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh::mesh(int)
|
|
||||||
{
|
|
||||||
array_ = 0;
|
|
||||||
buffer_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexed_mesh indexed_mesh::null()
|
|
||||||
{
|
|
||||||
return indexed_mesh(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
indexed_mesh::indexed_mesh()
|
|
||||||
{
|
|
||||||
gl::GenVertexArrays(1, &array_);
|
|
||||||
gl::GenBuffers(1, &buffer_);
|
|
||||||
gl::GenBuffers(1, &index_buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
indexed_mesh::indexed_mesh(indexed_mesh && other)
|
|
||||||
{
|
|
||||||
array_ = other.array_;
|
|
||||||
buffer_ = other.buffer_;
|
|
||||||
index_buffer_ = other.index_buffer_;
|
|
||||||
count_ = other.count_;
|
|
||||||
index_type_ = other.index_type_;
|
|
||||||
stride_ = other.stride_;
|
|
||||||
primitive_type_ = other.primitive_type_;
|
|
||||||
|
|
||||||
other.array_ = 0;
|
|
||||||
other.buffer_ = 0;
|
|
||||||
other.index_buffer_ = 0;
|
|
||||||
other.count_ = 0;
|
|
||||||
other.index_type_ = 0;
|
|
||||||
other.stride_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexed_mesh & indexed_mesh::operator =(indexed_mesh && other)
|
|
||||||
{
|
|
||||||
if (this == &other) return *this;
|
|
||||||
|
|
||||||
if (array_)
|
|
||||||
{
|
{
|
||||||
gl::DeleteVertexArrays(1, &array_);
|
assert(first + count <= vertex_count());
|
||||||
gl::DeleteBuffers(1, &buffer_);
|
|
||||||
gl::DeleteBuffers(1, &index_buffer_);
|
if (is_instanced())
|
||||||
|
{
|
||||||
|
assert(instance_count <= this->instance_count());
|
||||||
|
|
||||||
|
if (count != 0 && instance_count != 0)
|
||||||
|
{
|
||||||
|
array_.bind();
|
||||||
|
gl::DrawArraysInstanced(primitive_type(), first, count, instance_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
array_.bind();
|
||||||
|
gl::DrawArrays(primitive_type(), first, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
array_ = other.array_;
|
|
||||||
buffer_ = other.buffer_;
|
|
||||||
index_buffer_ = other.index_buffer_;
|
|
||||||
count_ = other.count_;
|
|
||||||
index_type_ = other.index_type_;
|
|
||||||
stride_ = other.stride_;
|
|
||||||
primitive_type_ = other.primitive_type_;
|
|
||||||
|
|
||||||
other.array_ = 0;
|
|
||||||
other.buffer_ = 0;
|
|
||||||
other.index_buffer_ = 0;
|
|
||||||
other.count_ = 0;
|
|
||||||
other.index_type_ = 0;
|
|
||||||
other.stride_ = 0;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
indexed_mesh::~indexed_mesh()
|
|
||||||
{
|
|
||||||
gl::DeleteVertexArrays(1, &array_);
|
|
||||||
gl::DeleteBuffers(1, &buffer_);
|
|
||||||
gl::DeleteBuffers(1, &index_buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
indexed_mesh::indexed_mesh(int)
|
|
||||||
{
|
|
||||||
array_ = 0;
|
|
||||||
buffer_ = 0;
|
|
||||||
index_buffer_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
instanced_mesh instanced_mesh::null()
|
|
||||||
{
|
|
||||||
return instanced_mesh(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
instanced_mesh::instanced_mesh()
|
|
||||||
{
|
|
||||||
gl::GenVertexArrays(1, &array_);
|
|
||||||
gl::GenBuffers(1, &buffer_);
|
|
||||||
gl::GenBuffers(1, &instance_buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
instanced_mesh::instanced_mesh(instanced_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_mesh & instanced_mesh::operator = (instanced_mesh && other)
|
|
||||||
{
|
|
||||||
if (this == &other)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
gl::DeleteVertexArrays(1, &array_);
|
|
||||||
gl::DeleteBuffers(1, &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_mesh::~instanced_mesh()
|
|
||||||
{
|
|
||||||
gl::DeleteVertexArrays(1, &array_);
|
|
||||||
gl::DeleteBuffers(1, &buffer_);
|
|
||||||
gl::DeleteBuffers(1, &instance_buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
instanced_mesh::instanced_mesh(int)
|
|
||||||
{
|
|
||||||
array_ = 0;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ namespace psemek::gfx
|
||||||
|
|
||||||
gfx::program program{vertex_source, fragment_source};
|
gfx::program program{vertex_source, fragment_source};
|
||||||
gfx::program text_program{text_vertex_source, text_fragment_source};
|
gfx::program text_program{text_vertex_source, text_fragment_source};
|
||||||
gfx::indexed_mesh mesh;
|
gfx::mesh mesh;
|
||||||
gfx::indexed_mesh text_mesh;
|
gfx::mesh text_mesh;
|
||||||
|
|
||||||
std::vector<vertex> vertices;
|
std::vector<vertex> vertices;
|
||||||
std::vector<std::uint32_t> indices;
|
std::vector<std::uint32_t> indices;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue