Skip to content

File Texture.h

File List > render > Texture.h

Go to the documentation of this file

#pragma once
#include <iostream>
#include <string>
#include <GL/glew.h>

#include "glm/glm.hpp"

/*
 * How to add a texture:
 * 1. Assign a (GLuint) slot for the texture (slot 0-14 are currently in use)
 * 2. Create a function that allocates a TextureRes in TextureLib
 * 3. Call that function and bind the texture to the slot chosen in the rendering loop
 * 4. Pass the slot number to the shader
 */

class Texture
{
public:

    enum TextureType
    {
        NONE_TEXTURE,            
        RGBA_TEXTURE,            
        RGB_TEXTURE,             
        HDR_TEXTURE = 4,         
        HDR_CUBE_TEXTURE = 5,    
        BUFFER_TEXTURE = 6,      
        HDR_BUFFER_TEXTURE,      
        FLOAT_BUFFER_TEXTURE,    
        RG_TEXTURE,              
        LAYERED_TEXTURE,         
        LIGHTING_CACHE = 30,     
        DEPTH_CUBE_TEXTURE = 31, 
        DEPTH_TEXTURE            
    };
private:

    int im_w = 0, im_h = 0, im_bpp = 0; 
    std::string tex_path;                
    GLuint tex_ID = 0;                   

    void _cpyInfo(const Texture& _tex);

    void _delTexture();

    void _deepCopyFrom(const Texture& _tex);

    void _resetTexID(GLuint _ID) { if (tex_ID > 0 && tex_ID != _ID)_delTexture(); tex_ID = _ID; }

public:

    TextureType tex_type = NONE_TEXTURE; 
    GLuint tex_slot_offset = 0;                       

    Texture(const std::string& texpath, TextureType tex_type, GLuint tile_type);

    Texture(int _w, int _h, TextureType tex_type, GLuint tile_type);

    Texture(int _w, int _h, GLuint _layout, const void* _ptr,
        GLint _min_filter = GL_LINEAR, GLint _mag_filter = GL_LINEAR,
        GLint _wrap_s = GL_REPEAT, GLint _wrap_t = GL_REPEAT);

    Texture(int _w, int _h, GLuint _ID, TextureType _type, std::string _name);

    Texture(int _w, int _h, TextureType _type);

    Texture();

    Texture(const Texture& tex);

    Texture(Texture&& tex) noexcept;

    Texture& operator=(const Texture& tex);

    Texture& operator=(Texture&& tex)noexcept;

    ~Texture();

    void Resize(const glm::vec2& size);

    void Resize(GLuint x, GLuint y);

    void OffsetSlot(GLuint _offset) { tex_slot_offset += _offset; };

public:
    void Bind(GLuint slot = -1) const;

    void BindC(GLuint slot = -1, GLuint read_or_write = GL_READ_WRITE, GLuint _level = 0) const;

    void BindU(GLuint slot = -1) const;

    static inline void BindM(GLuint _id, GLuint _slot = 0, TextureType _type=RGBA_TEXTURE);

    void UnbindC(GLuint slot = -1, GLuint read_or_write = GL_READ_WRITE, GLuint _level = 0) const;

    void Unbind() const;

public:
    inline int GetW() const { return im_w; }

    inline int GetH() const { return im_h; }

    inline glm::vec2 GetSize() const { return { im_w, im_h }; };

    inline int GetBPP() const { return im_bpp; }

    GLuint GetTexID() const { return tex_ID; }

    std::string GetTexName() const { return tex_path; }

public:
    using TexStorageInfo = const std::tuple<GLuint, GLuint, GLuint, GLuint>;

    inline static TexStorageInfo ParseFormat(TextureType _type);

    template<GLuint Type>
    inline static void SetTexParam(GLuint _id, GLuint _fil_min, GLuint _fil_max, GLuint _warp_s = 0, GLuint _warp_t = 0, GLuint _lev_min = 0, GLuint _lev_max = 0, GLuint _warp_r = 0);

public: 

    void GenIrradiaceConvFrom(const Texture& _Tar_Tex);

    void GenIBLSpecularFrom(const Texture& _Tar_Tex, bool to_cubemap = false);

    void GenIBLDiffuseFrom(const Texture& _Tar_Tex, bool to_cubemap = false);

    void GenCubeMapFrom(const Texture& _Tar_Tex, int res = 1024);

    void GenERectMapFrom(const Texture& _Tar_Tex, int _w = 2048, int _h = 1024);

    void ConvertDepthFrom(const Texture& _Tar_Tex);

    void ConvertDepthCubeFrom(const Texture& _Tar_Tex);

    void ConvertPNGFrom(const Texture& _Tar_Tex);

    void FillColor(const glm::vec4 col);

private:
    void GenIrradianceConv(GLuint _tar_ID, int _tar_w, int _tar_h, TextureType _tar_type = HDR_TEXTURE);
    void GenIBLSpecular(GLuint _tar_ID, int _tar_w, int _tar_h, TextureType _tar_type = HDR_TEXTURE, bool to_cubemap = false);
    void GenIBLDiffuse(GLuint _tar_ID, int _tar_w, int _tar_h, TextureType _tar_type = HDR_TEXTURE, bool to_cubemap = false);
    void GenCubeMap(GLuint _tar_ID, int _tar_res, TextureType _tar_type = HDR_TEXTURE);
    void GenERectMap(GLuint _tar_ID, int _w, int _h, TextureType _tar_type = HDR_TEXTURE);
    void ConvertDepth(GLuint _tar_ID, int _w, int _h, TextureType _tar_type = DEPTH_TEXTURE);
    void ConvertDepthCube(GLuint _tar_ID, int _w, int _h, TextureType _tar_type = DEPTH_CUBE_TEXTURE);
    void ConvertPNG(GLuint _tar_ID, int _w, int _h);

public:

    void SaveTexture(std::string _path, bool force_png=false, bool force_cube=false) const;

    void PrintTexture() const;
};

#include <unordered_map>

class TextureLib {


public:

    static std::string root_dir; 

    static Texture::TextureType ParseFileEXT(std::string path);

    using TextureRes = std::shared_ptr<Texture>; 

public:
    enum NoiseType
    {
        NONE_NOISE,     
        UNIFORM_NOISE,  
        GAUSSIAN_NOISE, 
        UNI_2D_NOISE    
    };

private:
    static std::unordered_map<std::string, TextureRes> t_tex_list; 

public:
    static TextureRes GetTexture(const std::string& _name);

    static TextureRes LoadTexture(std::string _name);

    static GLuint GetTextureID(const std::string& _name);

    static void ResetTexLib();

public:
    static TextureRes Noise_2D_4x4();

    static TextureRes Noise_2D_4x4xN(int n=6);

    static TextureRes Noise_2D_16x16xN(int n=6);

    static TextureRes IBL_LUT();

    static TextureRes LTC1();

    static TextureRes LTC2();

private:
    static void GenNoiseTexture(NoiseType _type, int _w, int _h);

    static void GenNoiseTextures(NoiseType _type, int _w, int _h, int _n);
};