/** This file is a part of our_dick Copyright (C) 2020-2022 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #ifndef OUR_DICK_GRAPHICS_OGL_TEXTURE_HPP #define OUR_DICK_GRAPHICS_OGL_TEXTURE_HPP #include "egn/image.hpp" #include "gl_include.hpp" #include namespace gfx::ogl{ //class representing an opengl 2D texture class texture_base { public: //all available wrapping styles as a strongly typed enum enum class wrap : GLint{ CLAMP_EDGE = GL_CLAMP_TO_EDGE, CLAMP_BORDER = GL_CLAMP_TO_BORDER, MIRROR_REPEAT = GL_MIRRORED_REPEAT, REPEAT = GL_REPEAT, MIRROR_CLAMP_EDGE = GL_MIRROR_CLAMP_TO_EDGE, }; //all available minfilter styles as a strongly typed enum enum class minfilter : GLint{ NEAREST = GL_NEAREST, LINEAR = GL_LINEAR, NMIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, LMIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, NMIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, LMIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR, }; //all available magfilter styles as a strongly typed enum enum class magfilter : GLint{ NEAREST = GL_NEAREST, LINEAR = GL_LINEAR, }; protected: GLuint m_tex_id = 0; //handle to texture object GLsizei m_width = 0; GLsizei m_height = 0; GLenum m_format = 0; GLenum m_type = GL_UNSIGNED_BYTE; bool m_mipmapped = true; texture_base(void) = default; texture_base(GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap); texture_base(const texture_base&); texture_base(texture_base&&); ~texture_base(void); texture_base& operator=(const texture_base&); texture_base& operator=(texture_base&&); public: GLuint raw(void)const; //change wrap mode for both x and y void set_wrap_mode(wrap w); void set_wrap_mode(wrap w, wrap h); //change wrap mode for one direction void set_wrap_x(wrap w); void set_wrap_y(wrap h); void set_border_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a = 1.0f); void set_filter(minfilter min, magfilter mag); void set_mag_filter(magfilter m); void set_min_filter(minfilter m); magfilter get_mag_filter(void)const; minfilter get_min_filter(void)const; rml::vec4f get_border_color(void)const; wrap get_wrap_x(void)const; wrap get_wrap_y(void)const; GLsizei get_width(void)const; GLsizei get_height(void)const; void enable_auto_mipmap(bool enable); void generate_mipmap(void); //release ownership of this texture object GLuint release(void); }; class texture : public texture_base { public: //create the texture with no image data texture(void); texture(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap = true); texture(GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap = true); //create the texture with image data from 'i' texture(const egn::image& i, bool mipmap = true); texture(const texture&); texture(texture&&); ~texture(void) = default; texture& operator=(const texture&); texture& operator=(texture&&); //overwrite the current image data with 'i' bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type); bool set_image(const egn::image& i); bool set_subimage(const unsigned char* data, GLenum format, GLenum type, GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h); bool set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset); //bind to target void bind(GLuint target = GL_TEXTURE_2D)const; //bind to given texture unit and load into given program uniform location void bind_unit(GLuint tunit)const; private: bool create_texture_storage_(void); }; class texture_array; //Represents a single layer of a texture_array class texture_slice { private: texture_array* m_owner; size_t m_level; public: texture_slice(texture_array* tex, int level); texture_slice(const texture_slice&) = default; texture_slice(texture_slice&&) = default; ~texture_slice(void) = default; texture_slice& operator=(const texture_slice&) = default; texture_slice& operator=(texture_slice&&) = default; bool valid(void)const; GLuint raw(void)const; int get_level(void)const; GLsizei get_width(void)const; GLsizei get_height(void)const; bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type); bool set_image(const egn::image& i); bool set_subimage(const unsigned char* data, GLenum format, GLenum type, GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h); bool set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset); }; class texture_array : public texture_base { private: size_t m_levels = 0; public: texture_array(void); texture_array(size_t layers); texture_array(const egn::image& i, size_t layers, bool mipmap = true); texture_array(GLenum format, GLsizei w, GLsizei h, GLenum type, size_t layers, bool mipmap = true); texture_array(const texture_array&); texture_array(texture_array&&); ~texture_array(void) = default; texture_array& operator=(const texture_array&); texture_array& operator=(texture_array&&); //overwrite the current image data with 'i' bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, size_t layer); bool set_image(const egn::image& i, size_t layer); bool set_subimage(const unsigned char* data, GLenum format, GLenum type, GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h, size_t layer); bool set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset, size_t layer); //bind to target void bind(GLuint target = GL_TEXTURE_2D_ARRAY)const; //bind to given texture unit and load into given program uniform location void bind_unit(GLuint tunit)const; texture_slice operator[](size_t layer); private: bool create_texture_storage_(void); }; class texture_view { //TODO //lookup glTextureView to remind yourself }; } #endif