texture: Use texture abstraction

This commit is contained in:
Archie Hilton 2024-05-26 20:46:09 +01:00
parent c904055632
commit a60def7a02
4 changed files with 160 additions and 53 deletions

View File

@ -3,6 +3,7 @@ add_executable(Exponent
GLProgramLoader.cc
Quad.cc
Mesh.cc
texture.cc
)
target_link_libraries(Exponent PUBLIC glfw glm::glm ${PNG_LIBRARY})

View File

@ -3,6 +3,7 @@
#include "glm/ext/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/trigonometric.hpp"
#include "src/texture.hh"
#include <exception>
#include <glm/ext.hpp>
#include <glm/glm.hpp>
@ -23,59 +24,9 @@ Quad::Quad(std::span<float> verts, const Uniform &uniform_data)
color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
png_uint_32 width = 0, height = 0;
int interlace_type = 0, bit_depth = 0, color_type = 0;
FILE *fp = fopen("./res/tex/util/missing.png", "rb");
png_const_bytep header[8] = {0};
if (fp == NULL) {
spdlog::error("Can't find texture file!");
throw std::exception();
}
fread(header, 1, 8, fp);
png_structp png_ptr =
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(png_ptr);
setjmp(png_jmpbuf(png_ptr));
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
png_read_png(png_ptr, info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |
PNG_TRANSFORM_EXPAND,
NULL);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL);
setjmp(png_jmpbuf(png_ptr));
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
size_t data_length = rowbytes * height;
png_byte *data = (png_byte *)malloc(data_length);
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
for (int x = 0; x < height; x++) {
memcpy(data + (rowbytes * (height - x - 1)), row_pointers[x], rowbytes);
}
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
tex_id = TextureLoader::get_instance()
->load_texture("./res/tex/util/missing.png")
->get_texture_id();
}
glm::vec2 Quad::get_position_vector() { return glm::vec2(m_pos_x, m_pos_y); }

120
src/texture.cc Normal file
View File

@ -0,0 +1,120 @@
#include "texture.hh"
#include <GL/gl.h>
#include <exception>
#include <glad/gl.h>
#include <png.h>
#include <pngconf.h>
#include <spdlog/spdlog.h>
#include <string>
#include <unordered_map>
TextureLoader *TextureLoader::m_instance = NULL;
TextureLoader *TextureLoader::get_instance() {
if (m_instance == NULL) {
m_instance = new TextureLoader();
}
return m_instance;
}
TextureLoader::TextureLoader() { m_texture_cache.clear(); }
TextureLoader::~TextureLoader() {
for (std::pair<std::string, Texture *> st : m_texture_cache) {
delete (st.second);
}
}
Texture *TextureLoader::load_texture(const std::string &path) {
// Cache Hit
if (m_texture_cache.contains(path)) {
return m_texture_cache.at(path);
}
// Cache miss - we have to load it and create it
m_texture_cache.emplace(std::make_pair(path, new Texture(path)));
return m_texture_cache.at(path);
}
Texture::Texture(const std::string &path) {
png_uint_32 width = 0, height = 0;
int interlace_type = 0, bit_depth = 0, color_type = 0;
spdlog::trace("Creating texture with path {}");
// First - check the path actually exists
FILE *fp = fopen(path.c_str(), "rb");
if (fp == NULL) {
spdlog::error("Cant find texture at path {}", path);
// TODO Make my own exception for this and log it upstream
throw std::exception();
}
png_byte header[4] = {0};
fread(header, 1, 4, fp);
// I'm not sure why this cast has to be there but clangd doesn't like it not
// being there...
// FIXME: for some reason, this fails.
/*
if (!png_sig_cmp(header, 0, 4)) {
spdlog::error("Texture file {} does not appear to be a png file.", path);
throw std::exception();
}
*/
png_structp png_ptr =
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(png_ptr);
setjmp(png_jmpbuf(png_ptr));
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 4);
png_read_png(png_ptr, info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |
PNG_TRANSFORM_EXPAND,
NULL);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL);
setjmp(png_jmpbuf(png_ptr));
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
size_t data_length = rowbytes * height;
png_byte *data = (png_byte *)malloc(data_length);
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
for (int x = 0; x < height; x++) {
memcpy(data + (rowbytes * (height - x - 1)), row_pointers[x], rowbytes);
}
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
glGenTextures(1, &m_gl_texture_id);
glBindTexture(GL_TEXTURE_2D, m_gl_texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
Texture::~Texture() {
spdlog::trace("Deleting texture id {}", m_gl_texture_id);
glDeleteTextures(1, &m_gl_texture_id);
}
GLuint Texture::get_texture_id() { return m_gl_texture_id; }

35
src/texture.hh Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <glad/gl.h>
#include <memory>
#include <string>
#include <unordered_map>
class Texture {
private:
GLuint m_gl_texture_id;
public:
Texture(const std::string &path);
~Texture();
Texture(const Texture &t) = delete;
GLuint get_texture_id();
};
class TextureLoader {
private:
static TextureLoader *m_instance;
std::unordered_map<std::string, Texture *> m_texture_cache;
TextureLoader();
~TextureLoader();
public:
Texture *load_texture(const std::string &path);
static TextureLoader *get_instance();
TextureLoader(const TextureLoader &tl) = delete;
};