summaryrefslogtreecommitdiff
path: root/micro/tex.c
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-04-06 17:04:05 -0400
committeriamcheeseman <[email protected]>2026-04-06 17:06:53 -0400
commit957c64c7b8b5e98d8a03dd84c7e27e7991fb9dbc (patch)
treef5fc230703791cee8d8e7851fb87eaef07ae63a2 /micro/tex.c
Initial commit
Diffstat (limited to 'micro/tex.c')
-rw-r--r--micro/tex.c159
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);
+}