diff --git a/libs/gfx/include/psemek/gfx/texture.hpp b/libs/gfx/include/psemek/gfx/texture.hpp index d76e1987..52caf8f3 100644 --- a/libs/gfx/include/psemek/gfx/texture.hpp +++ b/libs/gfx/include/psemek/gfx/texture.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,40 @@ namespace psemek::gfx {} }; + struct buffer_texture + { + buffer_texture(); + buffer_texture(buffer_texture &&); + buffer_texture & operator = (buffer_texture &&); + ~buffer_texture(); + + buffer_texture(buffer_texture const &) = delete; + buffer_texture & operator = (buffer_texture const &) = delete; + + static buffer_texture null(); + + static constexpr GLenum target = gl::TEXTURE_BUFFER; + + GLuint id() const { return id_; } + + explicit operator bool() const { return id() != 0; } + + void reset(); + + void bind() const; + void bind(int texture_unit) const; + + void buffer(GLenum internal_format, gfx::buffer const & buffer); + + template + void buffer(gfx::buffer const & buffer); + + protected: + GLuint id_; + + explicit buffer_texture(std::nullptr_t); + }; + namespace detail { std::optional max_anisotropy(); @@ -433,6 +468,72 @@ namespace psemek::gfx : id_{0} {} + inline buffer_texture::buffer_texture() + { + gl::GenTextures(1, &id_); + } + + inline buffer_texture::buffer_texture(buffer_texture && other) + : id_(other.id_) + { + other.id_ = 0; + } + + inline buffer_texture & buffer_texture::operator = (buffer_texture && other) + { + if (this != &other) + { + reset(); + id_ = other.id_; + other.id_ = 0; + } + + return *this; + } + + inline buffer_texture::~buffer_texture() + { + reset(); + } + + inline buffer_texture buffer_texture::null() + { + return buffer_texture(nullptr); + } + + inline void buffer_texture::reset() + { + if (id_ != 0) + gl::DeleteTextures(1, &id_); + } + + inline void buffer_texture::bind() const + { + gl::BindTexture(target, id_); + } + + inline void buffer_texture::bind(int texture_unit) const + { + gl::ActiveTexture(gl::TEXTURE0 + texture_unit); + bind(); + } + + inline void buffer_texture::buffer(GLenum internal_format, gfx::buffer const & buffer) + { + bind(); + gl::TexBuffer(target, internal_format, buffer.id()); + } + + template + void buffer_texture::buffer(gfx::buffer const & buffer) + { + this->buffer(pixel_traits::internal_format, buffer); + } + + inline buffer_texture::buffer_texture(std::nullptr_t) + : id_(0) + {} + template std::size_t mipmap_count(geom::vector const & size) {