diff options
Diffstat (limited to 'micro/tex.c')
| -rw-r--r-- | micro/tex.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/micro/tex.c b/micro/tex.c new file mode 100644 index 0000000..25f0fe9 --- /dev/null +++ b/micro/tex.c @@ -0,0 +1,159 @@ +#include "tex.h" + +#include <glad/glad.h> +#include <GLFW/glfw3.h> + +// TODO: write my own qoi implemenation, so that this isn't just here +#define QOI_IMPLEMENTATION +#include <qoi.h> + +#include "renderer.h" +#include "context.h" + +static +struct texture load_texture_from_handle(u32 handle, int width, int height) +{ + struct texture tex; + tex.handle = handle; + tex.width = width; + tex.height = height; + return tex; +} + +static +u32 get_texture_handle(u8 *data, int width, int height, u32 type) +{ + u32 handle; + glGenTextures(1, &handle); + glBindTexture(GL_TEXTURE_2D, handle); + glTexImage2D( + GL_TEXTURE_2D, + 0, + type, + width, + height, + 0, + type, + GL_UNSIGNED_BYTE, + data + ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + return handle; +} + +struct texture load_texture(const char *file_path) +{ + size_t size; + char *file_dat = read_file(file_path, &size); + + qoi_desc desc; + void *image_dat = qoi_decode(file_dat, size, &desc, 4); + + struct texture tex = load_texture_from_mem( + image_dat, + desc.width, + desc.height + ); + + mem_free(file_dat); + mem_free(image_dat); + + return tex; +} + +struct texture load_texture_from_mem(u8 *data, int width, int height) +{ + struct texture tex; + tex.width = width; + tex.height = height; + + tex.handle = get_texture_handle(data, width, height, GL_RGBA); + glGenerateMipmap(GL_TEXTURE_2D); + + return tex; +} + +void free_texture(struct texture tex) +{ + glDeleteTextures(1, &tex.handle); +} + +bool is_texture_init(struct texture tex) +{ + return tex.handle != 0 && tex.width > 0 && tex.height > 0; +} + +struct render_texture create_render_texture( + int width, + int height, + bool add_depth +) +{ + u32 fbo; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + struct texture depth = {0}; + + u32 color_handle = get_texture_handle(NULL, width, height, GL_RGB); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + color_handle, + 0 + ); + + struct texture color = load_texture_from_handle( + color_handle, + width, + height + ); + + if (add_depth) { + u32 depth_handle = get_texture_handle( + NULL, + width, + height, + GL_DEPTH_COMPONENT + ); + + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, + depth_handle, + 0 + ); + + depth = load_texture_from_handle( + depth_handle, + width, + height + ); + } + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + log_warn("framebuffer %d could not be completed", fbo); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + struct render_texture rtex; + rtex.handle = fbo; + rtex.color = color; + rtex.depth = depth; + rtex.width = width; + rtex.height = height; + return rtex; +} + +void free_render_texture(struct render_texture rtex) +{ + glDeleteFramebuffers(1, &rtex.handle); + free_texture(rtex.color); + if (is_texture_init(rtex.depth)) + free_texture(rtex.depth); +} |
