psemek/libs/gfx/source/texture.cpp
2020-10-03 20:41:52 +03:00

484 lines
11 KiB
C++

#include <psemek/gfx/texture.hpp>
#include <optional>
namespace psemek::gfx
{
static std::optional<float> max_anisotropy_level;
texture_1d::texture_1d()
{
gl::GenTextures(1, &id_);
}
texture_1d::texture_1d(GLuint id)
: id_(id)
{}
texture_1d texture_1d::null()
{
return texture_1d(0);
}
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);
}
}