summaryrefslogtreecommitdiff
path: root/src/renderer/archive
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/archive')
-rw-r--r--src/renderer/archive/render.c413
-rw-r--r--src/renderer/archive/render.h46
-rw-r--r--src/renderer/archive/render_backend.h39
-rw-r--r--src/renderer/archive/render_types.h210
4 files changed, 708 insertions, 0 deletions
diff --git a/src/renderer/archive/render.c b/src/renderer/archive/render.c
new file mode 100644
index 0000000..b1e2a46
--- /dev/null
+++ b/src/renderer/archive/render.c
@@ -0,0 +1,413 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "animation.h"
+#include "maths_types.h"
+#include "mem.h"
+#include "transform_hierarchy.h"
+#define STB_IMAGE_IMPLEMENTATION
+#include <stb_image.h>
+
+#define STB_TRUETYPE_IMPLEMENTATION
+#include <stb_truetype.h>
+
+#include "render.h"
+#include "render_types.h"
+
+#include <glad/glad.h>
+#include <glfw3.h>
+
+#include "defines.h"
+#include "log.h"
+#include "maths.h"
+#include "render_backend.h"
+
+// FIXME: get rid of these and store dynamic screen realestate
+// in renderer
+#define SCR_WIDTH 1000
+#define SCR_HEIGHT 1000
+
+material DEFAULT_MATERIAL = { 0 };
+
+bool renderer_init(renderer* ren) {
+ INFO("Renderer init");
+
+ // NOTE: all platforms use GLFW at the moment but thats subject to change
+ glfwInit();
+
+#if defined(CEL_REND_BACKEND_OPENGL)
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+#elif defined(CEL_REND_BACKEND_VULKAN)
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+#endif
+
+ // glfw window creation
+ GLFWwindow* window = glfwCreateWindow(ren->config.scr_width, ren->config.scr_height,
+ ren->config.window_name, NULL, NULL);
+ if (window == NULL) {
+ ERROR("Failed to create GLFW window\n");
+ glfwTerminate();
+ return false;
+ }
+ ren->window = window;
+
+ glfwMakeContextCurrent(ren->window);
+
+ DEBUG("init graphics api backend");
+ if (!gfx_backend_init(ren)) {
+ FATAL("Couldnt load graphics api backend");
+ return false;
+ }
+
+ ren->blinn_phong =
+ shader_create_separate("assets/shaders/blinn_phong.vert", "assets/shaders/blinn_phong.frag");
+
+ ren->skinned =
+ shader_create_separate("assets/shaders/skinned.vert", "assets/shaders/blinn_phong.frag");
+
+ default_material_init();
+
+ return true;
+}
+
+void renderer_shutdown(renderer* ren) {}
+
+void render_frame_begin(renderer* ren) {
+ vec3 color = ren->config.clear_colour;
+ clear_screen(color);
+}
+void render_frame_end(renderer* ren) {
+ // present frame
+ glfwSwapBuffers(ren->window);
+ glfwPollEvents();
+}
+
+void default_material_init() {
+ INFO("Load default material")
+ DEFAULT_MATERIAL.ambient_colour = (vec3){ 0.5, 0.5, 0.5 };
+ DEFAULT_MATERIAL.diffuse = (vec3){ 0.8, 0.8, 0.8 };
+ DEFAULT_MATERIAL.specular = (vec3){ 1.0, 1.0, 1.0 };
+ DEFAULT_MATERIAL.diffuse_texture = texture_data_load("assets/textures/white1x1.png", false);
+ DEFAULT_MATERIAL.specular_texture = texture_data_load("assets/textures/black1x1.png", false);
+ DEFAULT_MATERIAL.spec_exponent = 32.0;
+ strcpy(DEFAULT_MATERIAL.name, "Default");
+ texture_data_upload(&DEFAULT_MATERIAL.diffuse_texture);
+ texture_data_upload(&DEFAULT_MATERIAL.specular_texture);
+}
+
+void model_destroy(model* model) {
+ TRACE("Freeing all data for model %s", model->name);
+ arena_free_all(&model->animation_data_arena);
+ arena_free_storage(&model->animation_data_arena);
+ mesh_darray_free(model->meshes);
+ material_darray_free(model->materials);
+ if (model->is_uploaded) {
+ // Delete gpu buffer data
+ for (u32 i = 0; i < mesh_darray_len(model->meshes); i++) {
+ // FIXME: dont leak Opengl
+ glDeleteBuffers(1, &model->meshes->data[i].vbo);
+ glDeleteVertexArrays(1, &model->meshes->data[i].vao);
+ }
+ }
+}
+
+typedef struct draw_ctx {
+ model_darray* models;
+ renderer* ren;
+ camera* cam;
+ scene* scene;
+} draw_ctx;
+bool draw_scene_node(transform_node* node, void* ctx_data) {
+ if (!node || !node->parent) return true;
+ draw_ctx* ctx = ctx_data;
+ model* m = &ctx->models->data[node->model.raw];
+ draw_model(ctx->ren, ctx->cam, m, &node->world_matrix_tf, ctx->scene);
+ return true;
+}
+
+void draw_scene(arena* frame, model_darray* models, renderer* ren, camera* camera,
+ transform_hierarchy* tfh, scene* scene) {
+ draw_ctx* ctx = arena_alloc(frame, sizeof(draw_ctx));
+ ctx->models = models;
+ ctx->ren = ren;
+ ctx->cam = camera;
+ ctx->scene = scene;
+ transform_hierarchy_dfs(transform_hierarchy_root_node(tfh), draw_scene_node, true, ctx);
+}
+
+void draw_model(renderer* ren, camera* camera, model* model, mat4* model_tf, scene* scene) {
+ // TRACE("Drawing model: %s", model->name);
+ mat4 view;
+ mat4 proj;
+ camera_view_projection(camera, SCR_HEIGHT, SCR_WIDTH, &view, &proj);
+
+ set_shader(ren->blinn_phong);
+
+ // set camera uniform
+ uniform_vec3f(ren->blinn_phong.program_id, "viewPos", &camera->position);
+ // set light uniforms
+ dir_light_upload_uniforms(ren->blinn_phong, &scene->dir_light);
+ for (int i = 0; i < scene->n_point_lights; i++) {
+ point_light_upload_uniforms(ren->blinn_phong, &scene->point_lights[i], '0' + i);
+ }
+
+ for (size_t i = 0; i < mesh_darray_len(model->meshes); i++) {
+ mesh* m = &model->meshes->data[i];
+ if (vertex_darray_len(m->vertices) == 0) {
+ continue;
+ }
+ // TRACE("Drawing mesh %d", i);
+ material* mat = &model->materials->data[m->material_index];
+ draw_mesh(ren, m, model_tf, mat, &view, &proj);
+ }
+}
+
+void draw_mesh(renderer* ren, mesh* mesh, mat4* model_tf, material* mat, mat4* view, mat4* proj) {
+ shader lighting_shader = ren->blinn_phong;
+
+ // bind buffer
+ bind_mesh_vertex_buffer(ren->backend_state, mesh);
+
+ // bind textures
+ bind_texture(lighting_shader, &mat->diffuse_texture, 0); // bind to slot 0
+ bind_texture(lighting_shader, &mat->specular_texture, 1); // bind to slot 1
+ uniform_f32(lighting_shader.program_id, "material.shininess", 32.);
+
+ // upload model, view, and projection matrices
+ uniform_mat4f(lighting_shader.program_id, "model", model_tf);
+ uniform_mat4f(lighting_shader.program_id, "view", view);
+ uniform_mat4f(lighting_shader.program_id, "projection", proj);
+
+ // draw triangles
+ u32 num_vertices = vertex_darray_len(mesh->vertices);
+ draw_primitives(CEL_PRIMITIVE_TOPOLOGY_TRIANGLE, 0, num_vertices);
+}
+
+void draw_skinned_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* view,
+ mat4* proj) {
+ shader lighting_shader = ren->skinned;
+
+ // bind buffer
+ bind_mesh_vertex_buffer(ren->backend_state, mesh);
+
+ // bind textures
+ bind_texture(lighting_shader, &mat->diffuse_texture, 0); // bind to slot 0
+ bind_texture(lighting_shader, &mat->specular_texture, 1); // bind to slot 1
+
+ // Uniforms
+ uniform_f32(lighting_shader.program_id, "material.shininess", 32.);
+ mat4 trans = mat4_translation(tf.position);
+ mat4 rot = mat4_rotation(tf.rotation);
+ mat4 scale = mat4_scale(tf.scale);
+ mat4 model_tf = mat4_mult(trans, mat4_mult(rot, scale));
+ uniform_mat4f(lighting_shader.program_id, "model", &model_tf);
+ uniform_mat4f(lighting_shader.program_id, "view", view);
+ uniform_mat4f(lighting_shader.program_id, "projection", proj);
+
+ // bone transforms
+ size_t n_bones = mesh->bones->len;
+
+ // for now assume correct ordering
+ mat4* bone_transforms = malloc(n_bones * sizeof(mat4));
+ mat4 parent = mat4_ident();
+ for (int bone_i = 0; bone_i < n_bones; bone_i++) {
+ joint j = mesh->bones->data[bone_i];
+ transform tf = mesh->bones->data[bone_i].transform_components;
+ tf.position.y = -tf.position.y;
+ mat4 local = transform_to_mat(&tf);
+ mat4 inverse = j.inverse_bind_matrix;
+ inverse.data[13] = -inverse.data[13];
+ mat4 intemediate = mat4_mult(local, inverse);
+
+ bone_transforms[bone_i] = intemediate;
+ parent = bone_transforms[bone_i];
+ }
+
+ // premultiply the inverses
+ // for (int bone_i = 0; bone_i < n_bones; bone_i++) {
+ // joint j = mesh->bones->data[bone_i];
+ // // bone_transforms[bone_i] = mat4_mult(bone_transforms[bone_i], j.inverse_bind_matrix);
+ // bone_transforms[bone_i] = mat4_mult(bone_transforms[bone_i], j.inverse_bind_matrix);
+ // }
+
+ glUniformMatrix4fv(glGetUniformLocation(lighting_shader.program_id, "boneMatrices"), n_bones,
+ GL_FALSE, &bone_transforms->data[0]);
+
+ free(bone_transforms);
+
+ // draw triangles
+ u32 num_vertices = vertex_darray_len(mesh->vertices);
+ draw_primitives(CEL_PRIMITIVE_TOPOLOGY_TRIANGLE, 0, num_vertices);
+}
+
+void draw_skinned_model(renderer* ren, camera* cam, model* model, transform tf, scene* scene) {
+ mat4 view;
+ mat4 proj;
+ camera_view_projection(cam, SCR_HEIGHT, SCR_WIDTH, &view, &proj);
+
+ set_shader(ren->skinned);
+
+ // set camera uniform
+ uniform_vec3f(ren->skinned.program_id, "viewPos", &cam->position);
+ // set light uniforms
+ dir_light_upload_uniforms(ren->skinned, &scene->dir_light);
+ for (int i = 0; i < scene->n_point_lights; i++) {
+ point_light_upload_uniforms(ren->skinned, &scene->point_lights[i], '0' + i);
+ }
+
+ for (size_t i = 0; i < mesh_darray_len(model->meshes); i++) {
+ mesh* m = &model->meshes->data[i];
+ if (vertex_darray_len(m->vertices) == 0) {
+ continue;
+ }
+ // material* mat = &model->materials->data[m->material_index];
+ material* mat = &DEFAULT_MATERIAL;
+ draw_skinned_mesh(ren, m, tf, mat, &view, &proj);
+ }
+}
+
+void model_upload_meshes(renderer* ren, model* model) {
+ INFO("Upload mesh vertex data to GPU for model %s", model->name);
+
+ size_t num_meshes = mesh_darray_len(model->meshes);
+ u32 VBOs[num_meshes];
+ u32 VAOs[num_meshes];
+ glGenBuffers(num_meshes, VBOs);
+ glGenVertexArrays(num_meshes, VAOs);
+
+ u64 total_verts = 0;
+
+ TRACE("num meshes %d", num_meshes);
+
+ // upload each mesh to the GPU
+ for (int mesh_i = 0; mesh_i < num_meshes; mesh_i++) {
+ mesh mesh = model->meshes->data[mesh_i];
+ model->meshes->data[mesh_i].vao = VAOs[mesh_i];
+ model->meshes->data[mesh_i].vbo = VBOs[mesh_i];
+ // 3. bind buffers
+ glBindBuffer(GL_ARRAY_BUFFER, VBOs[mesh_i]);
+
+ size_t num_vertices = vertex_darray_len(model->meshes->data[mesh_i].vertices);
+ // TRACE("Uploading vertex array data: %d verts", num_vertices);
+ total_verts += num_vertices;
+
+ size_t static_vertex_size = 2 * sizeof(vec3) + sizeof(vec2);
+ size_t skinned_vertex_size = 2 * sizeof(vec3) + sizeof(vec2) + 4 * sizeof(u32) + sizeof(vec4);
+ size_t vertex_size = mesh.is_skinned ? skinned_vertex_size : static_vertex_size;
+
+ // TRACE("sizeof(vertex) -> %ld, vertex_size -> %ld\n", sizeof(vertex), vertex_size);
+ if (mesh.is_skinned) {
+ assert(vertex_size == (12 + 12 + 8 + 16 + 16));
+ } else {
+ assert(vertex_size == sizeof(vertex));
+ assert(vertex_size == 8 * sizeof(float));
+ }
+
+ size_t buffer_size = vertex_size * num_vertices;
+ u8* bytes = malloc(buffer_size);
+
+ for (int i = 0; i < num_vertices; i++) {
+ u8* p = bytes + vertex_size * i;
+ memcpy(p, &mesh.vertices->data[i], static_vertex_size);
+ if (mesh.is_skinned) {
+ u8* bone_data_offset = p + static_vertex_size;
+ memcpy(bone_data_offset, &mesh.vertex_bone_data->data[i], sizeof(vertex_bone_data));
+ }
+ }
+
+ // 4. upload data
+ glBufferData(GL_ARRAY_BUFFER, buffer_size, bytes, GL_STATIC_DRAW);
+
+ // 5. cont. set mesh vertex layout
+ glBindVertexArray(model->meshes->data[mesh_i].vao);
+ // position attribute
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)0);
+ glEnableVertexAttribArray(0);
+ // normal vector attribute
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)(3 * sizeof(float)));
+ glEnableVertexAttribArray(1);
+ // tex coords
+ glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)(6 * sizeof(float)));
+ glEnableVertexAttribArray(2);
+
+ // skinning (optional)
+ if (mesh.is_skinned) {
+ glEnableVertexAttribArray(3);
+ glVertexAttribIPointer(3, 4, GL_INT, vertex_size, (void*)(8 * sizeof(float)));
+
+ glEnableVertexAttribArray(4);
+ glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)(12 * sizeof(float)));
+ }
+ }
+
+ INFO("Uploaded %d submeshes with a total of %d vertices\n", num_meshes, total_verts);
+
+ // 6. reset buffer
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+texture texture_data_load(const char* path, bool invert_y) {
+ TRACE("Load texture %s", path);
+
+ // load the file data
+ // texture loading
+ int width, height, num_channels;
+ stbi_set_flip_vertically_on_load(invert_y);
+
+#pragma GCC diagnostic ignored "-Wpointer-sign"
+ char* data = stbi_load(path, &width, &height, &num_channels, 0); // STBI_rgb_alpha);
+ if (data) {
+ DEBUG("loaded texture: %s", path);
+ } else {
+ WARN("failed to load texture");
+ }
+
+ unsigned int channel_type;
+ if (num_channels == 4) {
+ channel_type = GL_RGBA;
+ } else {
+ channel_type = GL_RGB;
+ }
+
+ return (texture){ .texture_id = 0,
+ .width = width,
+ .height = height,
+ .channel_count = num_channels,
+ .channel_type = channel_type,
+ .name = "TODO: Texture names",
+ .image_data = data };
+}
+
+void dir_light_upload_uniforms(shader shader, directional_light* light) {
+ uniform_vec3f(shader.program_id, "dirLight.direction", &light->direction);
+ uniform_vec3f(shader.program_id, "dirLight.ambient", &light->ambient);
+ uniform_vec3f(shader.program_id, "dirLight.diffuse", &light->diffuse);
+ uniform_vec3f(shader.program_id, "dirLight.specular", &light->specular);
+}
+
+void point_light_upload_uniforms(shader shader, point_light* light, char index) {
+ char position_str[] = "pointLights[x].position";
+ position_str[12] = (char)index;
+ char ambient_str[] = "pointLights[x].ambient";
+ ambient_str[12] = (char)index;
+ char diffuse_str[] = "pointLights[x].diffuse";
+ diffuse_str[12] = (char)index;
+ char specular_str[] = "pointLights[x].specular";
+ specular_str[12] = (char)index;
+ char constant_str[] = "pointLights[x].constant";
+ constant_str[12] = (char)index;
+ char linear_str[] = "pointLights[x].linear";
+ linear_str[12] = (char)index;
+ char quadratic_str[] = "pointLights[x].quadratic";
+ quadratic_str[12] = (char)index;
+ uniform_vec3f(shader.program_id, position_str, &light->position);
+ uniform_vec3f(shader.program_id, ambient_str, &light->ambient);
+ uniform_vec3f(shader.program_id, diffuse_str, &light->diffuse);
+ uniform_vec3f(shader.program_id, specular_str, &light->specular);
+ uniform_f32(shader.program_id, constant_str, light->constant);
+ uniform_f32(shader.program_id, linear_str, light->linear);
+ uniform_f32(shader.program_id, quadratic_str, light->quadratic);
+} \ No newline at end of file
diff --git a/src/renderer/archive/render.h b/src/renderer/archive/render.h
new file mode 100644
index 0000000..31cf3b0
--- /dev/null
+++ b/src/renderer/archive/render.h
@@ -0,0 +1,46 @@
+/**
+ * @file render.h
+ * @author your name (you@domain.com)
+ * @brief Renderer frontend
+ * @version 0.1
+ * @date 2024-03-21
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+#pragma once
+
+#include "camera.h"
+#include "loaders.h"
+#include "render_types.h"
+#include "transform_hierarchy.h"
+
+// --- Lifecycle
+/** @brief initialise the render system frontend */
+bool renderer_init(renderer* ren);
+/** @brief shutdown the render system frontend */
+void renderer_shutdown(renderer* ren);
+
+void renderer_on_resize(renderer* ren);
+
+struct render_packet;
+
+// --- Frame
+
+void render_frame_begin(renderer* ren);
+void render_frame_end(renderer* ren);
+void render_frame_draw(renderer* ren);
+
+// --- models meshes
+void model_upload_meshes(renderer* ren, model* model);
+void draw_model(renderer* ren, camera* camera, model* model, mat4* tf, scene* scene);
+void draw_mesh(renderer* ren, mesh* mesh, mat4* tf, material* mat, mat4* view, mat4* proj);
+void draw_scene(arena* frame, model_darray* models, renderer* ren, camera* camera,
+ transform_hierarchy* tfh, scene* scene);
+
+void draw_skinned_model(renderer* ren, camera* cam, model* model, transform tf, scene* scene);
+
+void model_destroy(model* model);
+
+// ---
+texture texture_data_load(const char* path, bool invert_y); // #frontend
diff --git a/src/renderer/archive/render_backend.h b/src/renderer/archive/render_backend.h
new file mode 100644
index 0000000..da30bcc
--- /dev/null
+++ b/src/renderer/archive/render_backend.h
@@ -0,0 +1,39 @@
+/**
+ * @brief Renderer backend
+ */
+#pragma once
+
+#include "camera.h"
+#include "maths_types.h"
+#include "render_types.h"
+
+/// --- Lifecycle
+
+/** @brief Initialise the graphics API backend */
+bool gfx_backend_init(renderer* ren);
+void gfx_backend_shutdown(renderer* ren);
+
+void gfx_backend_draw_frame(renderer* ren, camera* camera, mat4 model, texture* tex);
+void gfx_backend_update_global_state(mat4 projection, mat4 view, vec3 view_pos, vec4 ambient_colour,
+ i32 mode);
+
+void clear_screen(vec3 colour);
+
+void texture_data_upload(texture* tex);
+void bind_texture(shader s, texture* tex, u32 slot);
+void bind_mesh_vertex_buffer(void* backend, mesh* mesh);
+void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count);
+
+shader shader_create_separate(const char* vert_shader, const char* frag_shader);
+void set_shader(shader s);
+
+// --- Uniforms
+
+/** @brief upload a vec3 of f32 to a uniform */
+void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value);
+/** @brief upload a single f32 to a uniform */
+void uniform_f32(u32 program_id, const char* uniform_name, f32 value);
+/** @brief upload a integer to a uniform */
+void uniform_i32(u32 program_id, const char* uniform_name, i32 value);
+/** @brief upload a mat4 of f32 to a uniform */
+void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value); \ No newline at end of file
diff --git a/src/renderer/archive/render_types.h b/src/renderer/archive/render_types.h
new file mode 100644
index 0000000..13a6651
--- /dev/null
+++ b/src/renderer/archive/render_types.h
@@ -0,0 +1,210 @@
+// /**
+// * @file render_types.h
+// * @author Omniscient
+// * @brief Type definitions for the majority of data required by the renderer system
+// * @date 2024-02-24
+// *
+// */
+// #pragma once
+
+#include "animation.h"
+#include "darray.h"
+#include "maths.h"
+#include "maths_types.h"
+#include "str.h"
+
+struct GLFWwindow;
+
+#define MAX_MATERIAL_NAME_LEN 256
+#define MAX_TEXTURE_NAME_LEN 256
+
+// #ifndef RESOURCE_HANDLE_DEFS
+// // CORE_DEFINE_HANDLE(model_handle);
+// #define ABSENT_MODEL_HANDLE 999999999
+// // CORE_DEFINE_HANDLE(texture_handle);
+// #define RESOURCE_HANDLE_DEFS
+// #endif
+
+/* @brief Opaque wrapper around a shader program */
+typedef struct shader {
+ u32 program_id;
+} shader;
+
+/** @brief configuration passed to the renderer at init time */
+typedef struct renderer_config {
+ char window_name[256];
+ u32 scr_width, scr_height;
+ vec3 clear_colour; /** colour that the screen gets cleared to every frame */
+} renderer_config;
+
+// typedef struct frame_stats {
+// u64 last_time;
+// } frame_stats;
+
+typedef struct renderer {
+ struct GLFWwindow *window; /** Currently all platforms use GLFW*/
+ void *backend_state; /** Graphics API-specific state */
+ renderer_config config;
+ // shaders
+ shader blinn_phong;
+ shader skinned;
+} renderer;
+
+// // --- Lighting & Materials
+
+typedef struct texture {
+ u32 texture_id;
+ char name[MAX_TEXTURE_NAME_LEN];
+ void *image_data;
+ void *backend_data;
+ u32 width;
+ u32 height;
+ u8 channel_count;
+ u32 channel_type;
+} texture;
+
+typedef struct blinn_phong_material {
+ char name[MAX_MATERIAL_NAME_LEN];
+ texture diffuse_texture;
+ char diffuse_tex_path[256];
+ texture specular_texture;
+ char specular_tex_path[256];
+ vec3 ambient_colour;
+ vec3 diffuse;
+ vec3 specular;
+ f32 spec_exponent;
+ bool is_loaded;
+ bool is_uploaded;
+} blinn_phong_material;
+typedef blinn_phong_material material; // when we start using PBR, this will no longer be the
+// case
+
+// // the default blinn-phong material. MUST be initialised with the function below
+// extern material DEFAULT_MATERIAL;
+// void default_material_init();
+
+#ifndef TYPED_MATERIAL_ARRAY
+KITC_DECL_TYPED_ARRAY(material) // creates "material_darray"
+#define TYPED_MATERIAL_ARRAY
+#endif
+
+#ifndef TYPED_ANIMATION_CLIP_ARRAY
+KITC_DECL_TYPED_ARRAY(animation_clip) // creates "material_darray"
+#define TYPED_ANIMATION_CLIP_ARRAY
+#endif
+
+// // lights
+// typedef struct point_light {
+// vec3 position;
+// f32 constant, linear, quadratic;
+// vec3 ambient;
+// vec3 diffuse;
+// vec3 specular;
+// } point_light;
+
+// typedef struct directional_light {
+// vec3 direction;
+// vec3 ambient;
+// vec3 diffuse;
+// vec3 specular;
+// } directional_light;
+
+// void point_light_upload_uniforms(shader shader, point_light *light, char index);
+// void dir_light_upload_uniforms(shader shader, directional_light *light);
+
+// // --- Models & Meshes
+
+// /** @brief Vertex format for a static mesh */
+typedef struct vertex {
+ vec3 position;
+ vec3 normal;
+ vec2 uv;
+} vertex;
+
+typedef struct vertex_bone_data {
+ vec4u joints; /** @brief 4 indices of joints that influence vectors position */
+ vec4 weights; /** @brief weight (0,1) of each joint */
+} vertex_bone_data;
+
+#include "animation.h"
+#ifndef TYPED_VERTEX_ARRAY
+KITC_DECL_TYPED_ARRAY(vertex) // creates "vertex_darray"
+KITC_DECL_TYPED_ARRAY(vertex_bone_data) // creates "skinned_vertex_darray"
+KITC_DECL_TYPED_ARRAY(joint)
+#define TYPED_VERTEX_ARRAY
+#endif
+
+typedef struct mesh {
+ vertex_darray *vertices;
+ vertex_bone_data_darray *vertex_bone_data; // only used if model needs it
+ joint_darray *bones;
+ bool is_skinned;
+ u32 vertex_size; /** size in bytes of each vertex including necessary padding */
+ bool has_indices;
+ u32 *indices;
+ u32 indices_len;
+ size_t material_index;
+ u32 vbo, vao; /** OpenGL data. TODO: dont leak OpenGL details */
+} mesh;
+
+// #ifndef TYPED_MESH_ARRAY
+// KITC_DECL_TYPED_ARRAY(mesh) // creates "mesh_darray"
+// #define TYPED_MESH_ARRAY
+// #endif
+
+typedef struct model {
+ str8 name;
+ mesh_darray *meshes;
+ aabb_3d bbox;
+ material_darray *materials;
+ animation_clip_darray *animations;
+ arena animation_data_arena;
+ bool is_loaded;
+ bool is_uploaded;
+} model;
+
+// #ifndef TYPED_MODEL_ARRAY
+// KITC_DECL_TYPED_ARRAY(model) // creates "model_darray"
+// #define TYPED_MODEL_ARRAY
+// #endif
+
+// // --- Scene
+
+// // NOTE: This struct won't stay like this for a long time. It's somewhat temporary
+// // in order to get a basic scene working without putting burden on the caller of
+// // draw_model()
+// typedef struct scene {
+// directional_light dir_light;
+// point_light point_lights[4];
+// size_t n_point_lights;
+// } scene;
+
+// // --- Graphics API related
+
+// // typedef enum cel_primitive_topology {
+// // CEL_PRIMITIVE_TOPOLOGY_POINT,
+// // CEL_PRIMITIVE_TOPOLOGY_LINE,
+// // CEL_PRIMITIVE_TOPOLOGY_LINE_STRIP,
+// // CEL_PRIMITIVE_TOPOLOGY_TRIANGLE,
+// // CEL_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
+// // CEL_PRIMITIVE_TOPOLOGY_COUNT
+// // } cel_primitive_topology;
+
+// // typedef enum gpu_texture_type {
+// // TEXTURE_TYPE_2D,
+// // TEXTURE_TYPE_3D,
+// // TEXTURE_TYPE_2D_ARRAY,
+// // TEXTURE_TYPE_CUBE_MAP,
+// // TEXTURE_TYPE_COUNT
+// // } gpu_texture_type;
+
+// // typedef enum gpu_texture_format {
+// // TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM,
+// // TEXTURE_FORMAT_DEPTH_DEFAULT,
+// // TEXTURE_FORMAT_COUNT
+// // } gpu_texture_format;
+
+// // typedef enum pipeline_kind {
+// // GRAPHICS,
+// // COMPUTE,
+// // } pipeline_kind; \ No newline at end of file