From db0f7915cfa475a3e5e16c74ac106b681af72ad7 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 4 Oct 2020 11:20:42 +0300 Subject: [PATCH] Refactor textures: add generic template, remove copypaste --- examples/grass.cpp | 2 +- libs/gfx/include/psemek/gfx/texture.hpp | 475 +++++++++++------------ libs/gfx/source/texture.cpp | 481 +----------------------- 3 files changed, 241 insertions(+), 717 deletions(-) diff --git a/examples/grass.cpp b/examples/grass.cpp index 97673658..1d8d3820 100644 --- a/examples/grass.cpp +++ b/examples/grass.cpp @@ -422,7 +422,7 @@ struct grass_app std::size_t slice_resolution = 256; - grass_slice_z_texture.load(slice_resolution, slice_resolution, density_level_count); + grass_slice_z_texture.load({slice_resolution, slice_resolution, density_level_count}); grass_slice_renderbuffer.storage(gl::DEPTH24_STENCIL8, slice_resolution, slice_resolution); for (int d = 0; d < density_level_count; ++d) { diff --git a/libs/gfx/include/psemek/gfx/texture.hpp b/libs/gfx/include/psemek/gfx/texture.hpp index 29f5452e..2d8ca677 100644 --- a/libs/gfx/include/psemek/gfx/texture.hpp +++ b/libs/gfx/include/psemek/gfx/texture.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace psemek::gfx { @@ -82,64 +84,52 @@ namespace psemek::gfx static constexpr GLenum type = gl::FLOAT; }; - struct texture_1d + template + struct basic_texture { - texture_1d(); - texture_1d(texture_1d const &) = delete; - texture_1d(texture_1d &&); + static_assert(D >= 1 && D <= 3); - texture_1d & operator = (texture_1d const &) = delete; - texture_1d & operator = (texture_1d &&); + basic_texture(); + basic_texture(basic_texture &&); + basic_texture & operator = (basic_texture &&); + ~basic_texture(); - ~texture_1d(); + basic_texture(basic_texture const &) = delete; + basic_texture & operator = (basic_texture const &) = delete; - static texture_1d null(); + static basic_texture null(); GLuint id() const { return id_; } + void reset(); + void bind() const; - explicit operator bool () const { return id_ != 0; } + explicit operator bool() const { return id() != 0; } - int width() const { return width_; } + geom::vector size() const { return size_; } - geom::vector size() const { return {width_}; } + std::size_t width() const; + std::size_t height() const; + std::size_t depth() const; - void load(GLint internal_format, std::size_t width, GLenum format, GLenum type, const void * data); + void load(GLint internal_format, geom::vector const & size, GLenum format, GLenum type, const void * data); template - void load(std::size_t width, Pixel const * data = nullptr) - { - using traits = pixel_traits; - load(traits::internal_format, width, traits::format, traits::type, data); - } + void load(geom::vector const & size, Pixel const * data = nullptr); template - void load(util::array const & p) - { - load(p.width(), p.data()); - } + void load(util::array const & p); void pixels(GLenum format, GLenum type, void * data) const; template - Pixmap pixels() const - { - using traits = pixel_traits; - Pixmap p({width_}); - pixels(traits::format, traits::type, p.data()); - return p; - } + Pixmap pixels() const; - static texture_1d from_data(GLint internal_format, std::size_t width, GLenum format, GLenum type, const void * data); + static basic_texture from_data(GLint internal_format, geom::vector const & size, GLenum format, GLenum type, const void * data); template - static texture_1d from_pixmap(Pixmap const & p) - { - texture_1d t; - t.load(p); - return t; - } + static basic_texture from_pixmap(Pixmap const & p); void generate_mipmap(); void nearest_filter(); @@ -151,241 +141,236 @@ namespace psemek::gfx private: GLuint id_; - int width_ = 0; + geom::vector size_; - texture_1d(GLuint id); + explicit basic_texture(std::nullptr_t); }; - struct texture_2d + using texture_1d = basic_texture<1, gl::TEXTURE_1D>; + using texture_1d_array = basic_texture<2, gl::TEXTURE_1D_ARRAY>; + using texture_2d = basic_texture<2, gl::TEXTURE_2D>; + using texture_2d_array = basic_texture<3, gl::TEXTURE_2D_ARRAY>; + using texture_3d = basic_texture<3, gl::TEXTURE_3D>; + + namespace detail { - texture_2d(); - texture_2d(texture_2d const &) = delete; - texture_2d(texture_2d &&); + std::optional max_anisotropy(); + } - texture_2d & operator = (texture_2d const &) = delete; - texture_2d & operator = (texture_2d &&); - - ~texture_2d(); - - static texture_2d null(); - - GLuint id() const { return id_; } - - void bind() const; - - explicit operator bool () const { return id_ != 0; } - - int width() const { return width_; } - int height() const { return height_; } - - geom::vector size() const { return {width_, height_}; } - - void load(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data); - - template - void load(std::size_t width, std::size_t height, Pixel const * data = nullptr) - { - using traits = pixel_traits; - load(traits::internal_format, width, height, traits::format, traits::type, data); - } - - template - void load(basic_pixmap const & p) - { - load(p.width(), p.height(), p.data()); - } - - void pixels(GLenum format, GLenum type, void * data) const; - - template - Pixmap pixels() const - { - using traits = pixel_traits; - Pixmap p({width_, height_}); - pixels(traits::format, traits::type, p.data()); - return p; - } - - static texture_2d from_data(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data); - - template - static texture_2d from_pixmap(Pixmap const & p) - { - texture_2d t; - t.load(p); - return t; - } - - void generate_mipmap(); - void nearest_filter(); - void linear_filter(); - void anisotropy(); - - void repeat(); - void clamp(); - - private: - GLuint id_; - int width_ = 0; - int height_ = 0; - - texture_2d(GLuint id); - }; - - struct texture_3d + template + basic_texture::basic_texture() { - texture_3d(); - texture_3d(texture_3d const &) = delete; - texture_3d(texture_3d &&); + gl::GenTextures(1, &id_); + } - texture_3d & operator = (texture_3d const &) = delete; - texture_3d & operator = (texture_3d &&); - - ~texture_3d(); - - static texture_3d null(); - - GLuint id() const { return id_; } - - void bind() const; - - explicit operator bool () const { return id_ != 0; } - - int width() const { return width_; } - int height() const { return height_; } - int depth() const { return depth_; } - - geom::vector size() const { return {width_, height_, depth_}; } - - void load(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data); - - template - void load(std::size_t width, std::size_t height, std::size_t depth, Pixel const * data = nullptr) - { - using traits = pixel_traits; - load(traits::internal_format, width, height, depth, traits::format, traits::type, data); - } - - template - void load(util::array const & p) - { - load(p.width(), p.height(), p.depth(), p.data()); - } - - void pixels(GLenum format, GLenum type, void * data) const; - - template - Pixmap pixels() const - { - using traits = pixel_traits; - Pixmap p({width_, height_, depth_}); - pixels(traits::format, traits::type, p.data()); - return p; - } - - static texture_3d from_data(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data); - - template - static texture_3d from_pixmap(Pixmap const & p) - { - texture_3d t; - t.load(p); - return t; - } - - void generate_mipmap(); - void nearest_filter(); - void linear_filter(); - void anisotropy(); - - void repeat(); - void clamp(); - - private: - GLuint id_; - int width_ = 0; - int height_ = 0; - int depth_ = 0; - - texture_3d(GLuint id); - }; - - struct texture_2d_array + template + basic_texture::basic_texture(basic_texture && other) + : id_{other.id_} { - texture_2d_array(); - texture_2d_array(texture_2d_array const &) = delete; - texture_2d_array(texture_2d_array &&); + other.id_ = 0; + } - texture_2d_array & operator = (texture_2d_array const &) = delete; - texture_2d_array & operator = (texture_2d_array &&); + template + basic_texture & basic_texture::operator = (basic_texture && other) + { + if (this == &other) return *this; - ~texture_2d_array(); + reset(); + std::swap(id_, other.id_); + return *this; + } - static texture_2d_array null(); + template + basic_texture::~basic_texture() + { + reset(); + } - GLuint id() const { return id_; } + template + basic_texture basic_texture::null() + { + return basic_texture(nullptr); + } - void bind() const; + template + void basic_texture::reset() + { + if (id_ != 0) + gl::DeleteTextures(1, &id_); + id_ = 0; + } - explicit operator bool () const { return id_ != 0; } + template + void basic_texture::bind() const + { + gl::BindTexture(Target, id()); + } - int width() const { return width_; } - int height() const { return height_; } - int depth() const { return depth_; } + template + std::size_t basic_texture::width() const + { + return size_[0]; + } - geom::vector size() const { return {width_, height_, depth_}; } - - void load(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data); - - template - void load(std::size_t width, std::size_t height, std::size_t depth, Pixel const * data = nullptr) + template + std::size_t basic_texture::height() const + { + if constexpr (D >= 2) { - using traits = pixel_traits; - load(traits::internal_format, width, height, depth, traits::format, traits::type, data); + return size_[1]; + } + else + { + return 1; + } + } + + template + std::size_t basic_texture::depth() const + { + if constexpr (D >= 3) + { + return size_[2]; + } + else + { + return 1; + } + } + + template + void basic_texture::load(GLint internal_format, geom::vector const & size, GLenum format, GLenum type, const void * data) + { + bind(); + + if constexpr (D == 1) + { + gl::TexImage1D(Target, 0, internal_format, size[0], 0, format, type, data); + } + else if (D == 2) + { + gl::TexImage2D(Target, 0, internal_format, size[0], size[1], 0, format, type, data); + } + else if (D == 3) + { + gl::TexImage3D(Target, 0, internal_format, size[0], size[1], size[2], 0, format, type, data); } - template - void load(util::array const & p) + size_ = size; + } + + template + template + void basic_texture::load(geom::vector const & size, Pixel const * data) + { + using traits = pixel_traits; + load(traits::internal_format, size, traits::format, traits::type, data); + } + + template + template + void basic_texture::load(util::array const & p) + { + geom::vector size; + for (std::size_t i = 0; i < D; ++i) size[i] = p.dim(i); + load(size, p.data()); + } + + template + void basic_texture::pixels(GLenum format, GLenum type, void * data) const + { + bind(); + gl::GetTexImage(Target, 0, format, type, data); + } + + template + template + Pixmap basic_texture::pixels() const + { + using traits = pixel_traits; + + std::array size; + for (std::size_t i = 0; i < D; ++i) size[i] = size_[i]; + + Pixmap p(size); + pixels(traits::format, traits::type, p.data()); + return p; + } + + template + basic_texture basic_texture::from_data(GLint internal_format, geom::vector const & size, GLenum format, GLenum type, const void * data) + { + basic_texture result; + result.load(internal_format, size, format, type, data); + return result; + } + + template + template + basic_texture basic_texture::from_pixmap(Pixmap const & p) + { + basic_texture result; + result.load(p); + return result; + } + + template + void basic_texture::generate_mipmap() + { + bind(); + gl::GenerateMipmap(Target); + } + + template + void basic_texture::nearest_filter() + { + bind(); + gl::TexParameteri(Target, gl::TEXTURE_MIN_FILTER, gl::NEAREST); + gl::TexParameteri(Target, gl::TEXTURE_MAG_FILTER, gl::NEAREST); + } + + template + void basic_texture::linear_filter() + { + bind(); + gl::TexParameteri(Target, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); + gl::TexParameteri(Target, gl::TEXTURE_MAG_FILTER, gl::LINEAR); + } + + template + void basic_texture::anisotropy() + { + auto level = detail::max_anisotropy(); + if (level) { - load(p.width(), p.height(), p.depth(), p.data()); + bind(); + gl::TexParameterf(Target, gl::TEXTURE_MAX_ANISOTROPY_EXT, *level); } + } - void pixels(GLenum format, GLenum type, void * data) const; + template + void basic_texture::repeat() + { + bind(); - template - Pixmap pixels() const - { - using traits = pixel_traits; - Pixmap p({width_, height_, depth_}); - pixels(traits::format, traits::type, p.data()); - return p; - } + if constexpr (D >= 1) gl::TexParameteri(Target, gl::TEXTURE_WRAP_S, gl::REPEAT); + if constexpr (D >= 2) gl::TexParameteri(Target, gl::TEXTURE_WRAP_T, gl::REPEAT); + if constexpr (D >= 3) gl::TexParameteri(Target, gl::TEXTURE_WRAP_R, gl::REPEAT); + } - static texture_2d_array from_data(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data); + template + void basic_texture::clamp() + { + bind(); - template - static texture_2d_array from_pixmap(Pixmap const & p) - { - texture_2d_array t; - t.load(p); - return t; - } + if constexpr (D >= 1) gl::TexParameteri(Target, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE); + if constexpr (D >= 2) gl::TexParameteri(Target, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE); + if constexpr (D >= 3) gl::TexParameteri(Target, gl::TEXTURE_WRAP_R, gl::CLAMP_TO_EDGE); + } - void generate_mipmap(); - void nearest_filter(); - void linear_filter(); - void anisotropy(); - - void repeat(); - void clamp(); - - private: - GLuint id_; - int width_ = 0; - int height_ = 0; - int depth_ = 0; - - texture_2d_array(GLuint id); - }; + template + basic_texture::basic_texture(std::nullptr_t) + : id_{0} + {} } diff --git a/libs/gfx/source/texture.cpp b/libs/gfx/source/texture.cpp index 3ea803e0..5a634997 100644 --- a/libs/gfx/source/texture.cpp +++ b/libs/gfx/source/texture.cpp @@ -1,484 +1,23 @@ #include #include -namespace psemek::gfx +namespace psemek::gfx::detail { - static std::optional max_anisotropy_level; - - texture_1d::texture_1d() + static std::optional get_max_anisotropy() { - gl::GenTextures(1, &id_); + if (!gl::exts::var_EXT_texture_filter_anisotropic) return std::nullopt; + + float level; + gl::GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &level); + return level; } - texture_1d::texture_1d(GLuint id) - : id_(id) - {} - - texture_1d texture_1d::null() + std::optional max_anisotropy() { - return texture_1d(0); - } + static std::optional level = get_max_anisotropy(); - void texture_1d::bind() const - { - gl::BindTexture(gl::TEXTURE_1D, id_); - } - - texture_1d::texture_1d(texture_1d && other) - : id_(other.id_) - , width_(other.width_) - { - other.id_ = 0; - other.width_ = 0; - } - - texture_1d & texture_1d::operator = (texture_1d && other) - { - if (this == &other) return *this; - - gl::DeleteTextures(1, &id_); - id_ = other.id_; - width_ = other.width_; - other.id_ = 0; - other.width_ = 0; - - return *this; - } - - texture_1d::~texture_1d() - { - gl::DeleteTextures(1, &id_); - } - - void texture_1d::load(GLint internal_format, std::size_t width, GLenum format, GLenum type, const void * data) - { - bind(); - gl::TexImage1D(gl::TEXTURE_1D, 0, internal_format, width, 0, format, type, data); - - width_ = width; - } - - void texture_1d::pixels(GLenum format, GLenum type, void * data) const - { - bind(); - gl::GetTexImage(gl::TEXTURE_1D, 0, format, type, data); - } - - texture_1d texture_1d::from_data(GLint internal_format, std::size_t width, GLenum format, GLenum type, const void * data) - { - texture_1d tex; - tex.load(internal_format, width, format, type, data); - return tex; - } - - void texture_1d::generate_mipmap() - { - bind(); - gl::GenerateMipmap(gl::TEXTURE_1D); - } - - void texture_1d::nearest_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_1D, gl::TEXTURE_MAG_FILTER, gl::NEAREST); - gl::TexParameteri(gl::TEXTURE_1D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_1d::linear_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_1D, gl::TEXTURE_MAG_FILTER, gl::LINEAR); - gl::TexParameteri(gl::TEXTURE_1D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_1d::anisotropy() - { - if (!gl::exts::var_EXT_texture_filter_anisotropic) return; - - if (!max_anisotropy_level) - { - max_anisotropy_level = 0; - gl::GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &(*max_anisotropy_level)); - } - gl::TexParameterf(gl::TEXTURE_1D, gl::TEXTURE_MAX_ANISOTROPY_EXT, *max_anisotropy_level); - } - - void texture_1d::repeat() - { - bind(); - gl::TexParameteri(gl::TEXTURE_1D, gl::TEXTURE_WRAP_S, gl::REPEAT); - } - - void texture_1d::clamp() - { - bind(); - gl::TexParameteri(gl::TEXTURE_1D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE); - } - - texture_2d::texture_2d() - { - gl::GenTextures(1, &id_); - } - - texture_2d::texture_2d(GLuint id) - : id_(id) - {} - - texture_2d texture_2d::null() - { - return texture_2d(0); - } - - void texture_2d::bind() const - { - gl::BindTexture(gl::TEXTURE_2D, id_); - } - - texture_2d::texture_2d(texture_2d && other) - : id_(other.id_) - , width_(other.width_) - , height_(other.height_) - { - other.id_ = 0; - other.width_ = 0; - other.height_ = 0; - } - - texture_2d & texture_2d::operator = (texture_2d && other) - { - if (this == &other) return *this; - - gl::DeleteTextures(1, &id_); - id_ = other.id_; - width_ = other.width_; - height_ = other.height_; - other.id_ = 0; - other.width_ = 0; - other.height_ = 0; - - return *this; - } - - texture_2d::~texture_2d() - { - gl::DeleteTextures(1, &id_); - } - - void texture_2d::load(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data) - { - bind(); - gl::TexImage2D(gl::TEXTURE_2D, 0, internal_format, width, height, 0, format, type, data); - - width_ = width; - height_ = height; - } - - void texture_2d::pixels(GLenum format, GLenum type, void * data) const - { - bind(); - gl::GetTexImage(gl::TEXTURE_2D, 0, format, type, data); - } - - texture_2d texture_2d::from_data(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data) - { - texture_2d tex; - tex.load(internal_format, width, height, format, type, data); - return tex; - } - - void texture_2d::generate_mipmap() - { - bind(); - gl::GenerateMipmap(gl::TEXTURE_2D); - } - - void texture_2d::nearest_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_2d::linear_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_2d::anisotropy() - { - if (!gl::exts::var_EXT_texture_filter_anisotropic) return; - - if (!max_anisotropy_level) - { - max_anisotropy_level = 0; - gl::GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &(*max_anisotropy_level)); - } - gl::TexParameterf(gl::TEXTURE_2D, gl::TEXTURE_MAX_ANISOTROPY_EXT, *max_anisotropy_level); - } - - void texture_2d::repeat() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT); - } - - void texture_2d::clamp() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE); - } - - texture_3d::texture_3d() - { - gl::GenTextures(1, &id_); - } - - texture_3d::texture_3d(GLuint id) - : id_(id) - {} - - texture_3d texture_3d::null() - { - return texture_3d(0); - } - - void texture_3d::bind() const - { - gl::BindTexture(gl::TEXTURE_3D, id_); - } - - texture_3d::texture_3d(texture_3d && other) - : id_(other.id_) - , width_(other.width_) - , height_(other.height_) - , depth_(other.depth_) - { - other.id_ = 0; - other.width_ = 0; - other.height_ = 0; - other.depth_ = 0; - } - - texture_3d & texture_3d::operator = (texture_3d && other) - { - if (this == &other) return *this; - - gl::DeleteTextures(1, &id_); - id_ = other.id_; - width_ = other.width_; - height_ = other.height_; - depth_ = other.depth_; - other.id_ = 0; - other.width_ = 0; - other.height_ = 0; - other.depth_ = 0; - - return *this; - } - - texture_3d::~texture_3d() - { - gl::DeleteTextures(1, &id_); - } - - void texture_3d::load(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data) - { - bind(); - gl::TexImage3D(gl::TEXTURE_3D, 0, internal_format, width, height, depth, 0, format, type, data); - - width_ = width; - height_ = height; - depth_ = depth; - } - - void texture_3d::pixels(GLenum format, GLenum type, void * data) const - { - bind(); - gl::GetTexImage(gl::TEXTURE_3D, 0, format, type, data); - } - - texture_3d texture_3d::from_data(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data) - { - texture_3d tex; - tex.load(internal_format, width, height, depth, format, type, data); - return tex; - } - - void texture_3d::generate_mipmap() - { - bind(); - gl::GenerateMipmap(gl::TEXTURE_3D); - } - - void texture_3d::nearest_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_MAG_FILTER, gl::NEAREST); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_3d::linear_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_MAG_FILTER, gl::LINEAR); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_3d::anisotropy() - { - if (!gl::exts::var_EXT_texture_filter_anisotropic) return; - - if (!max_anisotropy_level) - { - max_anisotropy_level = 0; - gl::GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &(*max_anisotropy_level)); - } - gl::TexParameterf(gl::TEXTURE_3D, gl::TEXTURE_MAX_ANISOTROPY_EXT, *max_anisotropy_level); - } - - void texture_3d::repeat() - { - bind(); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_WRAP_S, gl::REPEAT); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_WRAP_T, gl::REPEAT); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_WRAP_R, gl::REPEAT); - } - - void texture_3d::clamp() - { - bind(); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE); - gl::TexParameteri(gl::TEXTURE_3D, gl::TEXTURE_WRAP_R, gl::CLAMP_TO_EDGE); - } - - texture_2d_array::texture_2d_array() - { - gl::GenTextures(1, &id_); - } - - texture_2d_array::texture_2d_array(GLuint id) - : id_(id) - {} - - texture_2d_array texture_2d_array::null() - { - return texture_2d_array(0); - } - - void texture_2d_array::bind() const - { - gl::BindTexture(gl::TEXTURE_2D_ARRAY, id_); - } - - texture_2d_array::texture_2d_array(texture_2d_array && other) - : id_(other.id_) - , width_(other.width_) - , height_(other.height_) - , depth_(other.depth_) - { - other.id_ = 0; - other.width_ = 0; - other.height_ = 0; - other.depth_ = 0; - } - - texture_2d_array & texture_2d_array::operator = (texture_2d_array && other) - { - if (this == &other) return *this; - - gl::DeleteTextures(1, &id_); - id_ = other.id_; - width_ = other.width_; - height_ = other.height_; - depth_ = other.depth_; - other.id_ = 0; - other.width_ = 0; - other.height_ = 0; - other.depth_ = 0; - - return *this; - } - - texture_2d_array::~texture_2d_array() - { - gl::DeleteTextures(1, &id_); - } - - void texture_2d_array::load(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data) - { - bind(); - gl::TexImage3D(gl::TEXTURE_2D_ARRAY, 0, internal_format, width, height, depth, 0, format, type, data); - - width_ = width; - height_ = height; - depth_ = depth; - } - - void texture_2d_array::pixels(GLenum format, GLenum type, void * data) const - { - bind(); - gl::GetTexImage(gl::TEXTURE_2D_ARRAY, 0, format, type, data); - } - - texture_2d_array texture_2d_array::from_data(GLint internal_format, std::size_t width, std::size_t height, std::size_t depth, GLenum format, GLenum type, const void * data) - { - texture_2d_array tex; - tex.load(internal_format, width, height, depth, format, type, data); - return tex; - } - - void texture_2d_array::generate_mipmap() - { - bind(); - gl::GenerateMipmap(gl::TEXTURE_2D_ARRAY); - } - - void texture_2d_array::nearest_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_MAG_FILTER, gl::NEAREST); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_2d_array::linear_filter() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_MAG_FILTER, gl::LINEAR); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR); - } - - void texture_2d_array::anisotropy() - { - if (!gl::exts::var_EXT_texture_filter_anisotropic) return; - - if (!max_anisotropy_level) - { - max_anisotropy_level = 0; - gl::GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &(*max_anisotropy_level)); - } - gl::TexParameterf(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_MAX_ANISOTROPY_EXT, *max_anisotropy_level); - } - - void texture_2d_array::repeat() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_WRAP_S, gl::REPEAT); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_WRAP_T, gl::REPEAT); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_WRAP_R, gl::REPEAT); - } - - void texture_2d_array::clamp() - { - bind(); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE); - gl::TexParameteri(gl::TEXTURE_2D_ARRAY, gl::TEXTURE_WRAP_R, gl::CLAMP_TO_EDGE); + return level; } }