#include "pch.h" #include "log.h" #include "texture.h" #include "util.h" std::map TextureManager::m_textures; bool TextureManager::load(const char* path, bool generate_mipmaps) { uint16_t id = const_hash(path); if (m_textures.count(id) == 0 || !m_textures[id].ready()) { if (!m_textures[id].load(path)) return false; if (generate_mipmaps) m_textures[id].create_mipmaps(); } return true; } void TextureManager::assign(uint16_t id, GLuint tex, int w/* = -1*/, int h/* = -1*/, GLuint internal_format/* = GL_RGBA8*/, GLuint format/* = GL_RGBA*/) { m_textures[id].assign(tex, w, h, internal_format, format); } Texture2D& TextureManager::get(uint16_t id) { return m_textures[id]; } void TextureManager::invalidate() { for (auto& t : m_textures) { t.second.destroy(); } m_textures.clear(); } bool Texture2D::create(int width, int height, GLint internal_format, GLint format, const uint8_t* data) { destroy(); m_width = width; m_height = height; m_format = format; m_iformat = internal_format; glGenTextures(1, &m_tex); //LOG("TEX create %d", m_tex); bind(); auto ifmt = GL_UNSIGNED_BYTE; if (internal_format == GL_RGBA32F) ifmt = GL_FLOAT; if (internal_format == GL_RGBA16F) ifmt = GL_HALF_FLOAT; glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, ifmt, data); unbind(); return true; } bool Texture2D::create(const Image& img) { static GLint formats[] = { GL_RED, GL_RG, GL_RGB, GL_RGBA }; static GLint iformats[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 }; return create(img.width, img.height, iformats[img.comp - 1], formats[img.comp - 1], img.data()); } void Texture2D::create_mipmaps() { bind(); glGenerateMipmap(GL_TEXTURE_2D); unbind(); has_mips = true; } void Texture2D::assign(GLuint tex, int w/* = -1*/, int h/* = -1*/, GLuint internal_format/* = GL_RGBA8*/, GLuint format/* = GL_RGBA*/) { m_tex = tex; m_width = w; m_height = h; m_format = format; m_iformat = internal_format; } bool Texture2D::load(std::string filename) { LOG("load texture %s", filename.c_str()); Image img; if (!img.load(filename)) return false; return create(img); } bool Texture2D::load_file(std::string filename) { LOG("load texture %s", filename.c_str()); Image img; if (!img.load_file(filename)) return false; return create(img); } void Texture2D::update(const uint8_t* data) { bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_width, m_height, m_format, GL_UNSIGNED_BYTE, data); } glm::vec2 Texture2D::size() const { return { m_width, m_height }; } bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/) { #if USE_SAMPLER glGenSamplers(1, &id); #endif // USE_SAMPLER if (id == 0) return false; set(filter, wrap); return true; } void Sampler::set(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/) { #if USE_SAMPLER glSamplerParameteri(id, GL_TEXTURE_WRAP_S, wrap); glSamplerParameteri(id, GL_TEXTURE_WRAP_T, wrap); glSamplerParameteri(id, GL_TEXTURE_WRAP_R, wrap); glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, filter); glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter); #endif // USE_SAMPLER } void Sampler::set_filter(GLint filter_min, GLint filter_mag) { #if USE_SAMPLER glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, filter_min); glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, filter_mag); #endif // USE_SAMPLER } void Sampler::bind(int unit) { current_unit = unit; #if USE_SAMPLER glBindSampler(unit, id); #endif // USE_SAMPLER } void Sampler::unbind() { #if USE_SAMPLER glBindSampler(current_unit, 0); #endif // USE_SAMPLER }