From 90dd96cbc9b09cdc75977b115a9b61fa7547baef Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sun, 25 Feb 2024 17:35:27 +1100 Subject: boilerplate for more examples --- src/renderer/render_types.h | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'src/renderer') diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index e24fc24..f63f3f8 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -57,7 +57,7 @@ typedef struct mesh { u32 *indices; u32 indices_len; size_t material_index; - u32 vbo, vao; /** OpenGL data */ + u32 vbo, vao; /** OpenGL data. TODO: dont leak OpenGL details */ } mesh; #ifndef TYPED_MESH_ARRAY @@ -67,9 +67,39 @@ KITC_DECL_TYPED_ARRAY(mesh) // creates "mesh_darray" typedef struct model { str8 name; + mesh_darray meshes; + aabb_3d bbox; + // TODO: materials + bool is_loaded; + bool is_uploaded; } model; #ifndef TYPED_MODEL_ARRAY KITC_DECL_TYPED_ARRAY(model) // creates "model_darray" #define TYPED_MODEL_ARRAY -#endif \ No newline at end of file +#endif + +// --- 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; \ No newline at end of file -- cgit v1.2.3-70-g09d2 From cd1f6de2fda8b29a55d9ca9abb7b31e774d8d165 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Tue, 5 Mar 2024 20:50:20 +1100 Subject: add render types for material and texture --- src/core.h | 3 ++- src/renderer/render_types.h | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) (limited to 'src/renderer') diff --git a/src/core.h b/src/core.h index 8a3d037..1b3e28b 100644 --- a/src/core.h +++ b/src/core.h @@ -13,10 +13,11 @@ typedef struct core { input_state input; text_system_state text; screenspace_state screenspace; + model_darray* models; } core; // --- Lifecycle core* core_bringup(); void core_shutdown(core* core); -void core_input_update(core* core); \ No newline at end of file +void core_input_update(core* core); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index f63f3f8..45851fe 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -13,7 +13,11 @@ struct GLFWwindow; +#define MAX_MATERIAL_NAME_LEN 256 +#define MAX_TEXTURE_NAME_LEN 256 + #ifndef RESOURCE_HANDLE_DEFS +CORE_DEFINE_HANDLE(model_handle); CORE_DEFINE_HANDLE(texture_handle); #define RESOURCE_HANDLE_DEFS #endif @@ -36,6 +40,42 @@ typedef struct renderer { renderer_config config; } renderer; +// --- Lighting & Materials + +typedef struct texture { + u32 texture_id; + char name[MAX_TEXTURE_NAME_LEN]; + void *image_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 + /** @brief Vertex format for a static mesh */ typedef struct vertex { vec3 position; @@ -69,7 +109,7 @@ typedef struct model { str8 name; mesh_darray meshes; aabb_3d bbox; - // TODO: materials + material_darray *materials; bool is_loaded; bool is_uploaded; } model; @@ -102,4 +142,4 @@ typedef enum gpu_texture_format { TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, TEXTURE_FORMAT_DEPTH_DEFAULT, TEXTURE_FORMAT_COUNT -} gpu_texture_format; \ No newline at end of file +} gpu_texture_format; -- cgit v1.2.3-70-g09d2 From b459aa07581a948ee252d7e543c10675b602f146 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Tue, 5 Mar 2024 20:50:37 +1100 Subject: wip: port obj loader --- src/renderer/render.c | 78 ++++++++++- src/renderer/render.h | 4 +- src/resources/obj.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++- xmake.lua | 3 +- 4 files changed, 440 insertions(+), 4 deletions(-) (limited to 'src/renderer') diff --git a/src/renderer/render.c b/src/renderer/render.c index 4e9ad89..f12954f 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -1,10 +1,19 @@ +#define STB_IMAGE_IMPLEMENTATION +#include + +#define STB_TRUETYPE_IMPLEMENTATION +#include + #include "render.h" +#include #include #include "log.h" #include "render_backend.h" +material DEFAULT_MATERIAL = { 0 }; + bool renderer_init(renderer* ren) { INFO("Renderer init"); @@ -39,4 +48,71 @@ void render_frame_end(renderer* ren) { // present frame glfwSwapBuffers(ren->window); glfwPollEvents(); -} \ No newline at end of file +} + +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); +} + +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); + 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 texture_data_upload(texture* tex) { + TRACE("Upload texture data"); + u32 texture_id; + glGenTextures(1, &texture_id); + glBindTexture(GL_TEXTURE_2D, texture_id); + tex->texture_id = texture_id; + + // set the texture wrapping parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + // set texture filtering parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex->width, tex->height, 0, tex->channel_type, + GL_UNSIGNED_BYTE, tex->image_data); + glGenerateMipmap(GL_TEXTURE_2D); + DEBUG("Freeing texture image data after uploading to GPU"); + // stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around +} diff --git a/src/renderer/render.h b/src/renderer/render.h index c89c364..c4e0dd6 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -13,4 +13,6 @@ void renderer_shutdown(renderer* ren); void render_frame_begin(renderer* ren); void render_frame_end(renderer* ren); -// --- \ No newline at end of file +// --- +texture texture_data_load(const char* path, bool invert_y); // #frontend +void texture_data_upload(texture* tex); // #backend diff --git a/src/resources/obj.c b/src/resources/obj.c index b646f58..9e12f79 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -1 +1,358 @@ -// TODO: Port code from old repo \ No newline at end of file +/** + * @file obj.c + * @brief Wavefront OBJ loader. + * @copyright Copyright (c) 2024 + */ +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "darray.h" +#include "log.h" +#include "maths.h" +#include "render.h" +#include "render_types.h" + +struct face { + u32 vertex_indices[3]; + u32 normal_indices[3]; + u32 uv_indices[3]; +}; +typedef struct face face; + +KITC_DECL_TYPED_ARRAY(vec3) +KITC_DECL_TYPED_ARRAY(vec2) +KITC_DECL_TYPED_ARRAY(face) + +// Forward declarations +void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray *tmp_normals, + vec2_darray *tmp_uvs, face_darray *tmp_faces, material_darray *materials, + bool material_loaded, char current_material_name[256]); +bool load_material_lib(const char *path, material_darray *materials); +bool model_load_obj_str(const char *file_string, model *out_model, bool invert_textures_y); + +model_handle model_load_obj(core *core, const char *path, bool invert_textures_y) { + const char *file_string = string_from_file(path); + model model; + + bool success = model_load_obj_str(file_string, &model, invert_textures_y); + + if (!success) { + exit(-1); // FIXME: Return some sort of result type? + } + + u32 index = model_darray_len(core->models); + model_darray_push(core->models, model); + return (model_handle){ .raw = index }; +} + +bool model_load_obj_str(const char *file_string, model *out_model, bool invert_textures_y) { + TRACE("Load OBJ from string"); + + // Setup temps + vec3_darray *tmp_positions = vec3_darray_new(1000); + vec3_darray *tmp_normals = vec3_darray_new(1000); + vec2_darray *tmp_uvs = vec2_darray_new(1000); + face_darray *tmp_faces = face_darray_new(1000); + + mesh_darray *meshes = mesh_darray_new(1); + material_darray *materials = material_darray_new(1); + + // Other state + bool object_set = false; + bool material_loaded = false; + char current_material_name[64]; + + char *pch; + char *rest = file_string; + pch = strtok_r((char *)file_string, "\n", &rest); + + int line_num = 0; + char last_char_type = 'a'; + + while (pch != NULL) { + line_num++; + char line_header[128]; + int offset = 0; + + // skip whitespace + char *p = pch; + + skip_space(pch); + + if (*p == '\0') { + /* the string is empty */ + } else { + // read the first word of the line + int res = sscanf(pch, "%s %n", line_header, &offset); + // printf("header: %s, offset : %d res: %d\n",line_header, offset, res); + if (res != 1) { + break; + } + + if (strcmp(line_header, "o") == 0 || strcmp(line_header, "g") == 0) { + // if we're currently parsing one + if (!object_set) { + object_set = true; + } else { + create_submesh(meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, materials, + material_loaded, current_material_name); + object_set = false; + } + } else if (strcmp(line_header, "v") == 0) { + // special logic: if we went from faces back to vertices trigger a mesh output. + // PS: I hate OBJ + if (last_char_type == 'f') { + create_submesh(meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, materials, + material_loaded, current_material_name); + object_set = false; + } + + last_char_type = 'v'; + vec3 vertex; + sscanf(pch + offset, "%f %f %f", &vertex.x, &vertex.y, &vertex.z); + + vec3_darray_push(tmp_positions, vertex); + } else if (strcmp(line_header, "vt") == 0) { + last_char_type = 't'; + vec2 uv; + char copy[1024]; + memcpy(copy, pch + offset, strlen(pch + offset) + 1); + char *p = pch + offset; + while (isspace((unsigned char)*p)) ++p; + + // I can't remember what is going on here + memset(copy, 0, 1024); + memcpy(copy, pch + offset, strlen(pch + offset) + 1); + int res = sscanf(copy, "%f %f", &uv.x, &uv.y); + memset(copy, 0, 1024); + memcpy(copy, pch + offset, strlen(pch + offset) + 1); + if (res != 1) { + // da frick? some .obj files have 3 uvs instead of 2 + f32 dummy; + int res2 = sscanf(copy, "%f %f %f", &uv.x, &uv.y, &dummy); + } + + if (invert_textures_y) { + uv.y = -uv.y; // flip Y axis to be consistent with how other PNGs are being handled + // `texture_load` will flip it again + } + vec2_darray_push(tmp_uvs, uv); + } else if (strcmp(line_header, "vn") == 0) { + last_char_type = 'n'; + vec3 normal; + sscanf(pch + offset, "%f %f %f", &normal.x, &normal.y, &normal.z); + vec3_darray_push(tmp_normals, normal); + } else if (strcmp(line_header, "f") == 0) { + last_char_type = 'f'; + struct face f; + sscanf(pch + offset, "%d/%d/%d %d/%d/%d %d/%d/%d", &f.vertex_indices[0], &f.uv_indices[0], + &f.normal_indices[0], &f.vertex_indices[1], &f.uv_indices[1], &f.normal_indices[1], + &f.vertex_indices[2], &f.uv_indices[2], &f.normal_indices[2]); + // printf("f %d/%d/%d %d/%d/%d %d/%d/%d\n", f.vertex_indices[0], f.uv_indices[0], + // f.normal_indices[0], + // f.vertex_indices[1], f.uv_indices[1], f.normal_indices[1], + // f.vertex_indices[2], f.uv_indices[2], f.normal_indices[2]); + face_darray_push(tmp_faces, f); + } else if (strcmp(line_header, "mtllib") == 0) { + char path[1024] = "assets/"; + sscanf(pch + offset, "%s", path + 7); + if (!load_material_lib(path, materials)) { + ERROR("couldnt load material lib"); + } + } else if (strcmp(line_header, "usemtl") == 0) { + material_loaded = true; + sscanf(pch + offset, "%s", current_material_name); + } + } + + pch = strtok_r(NULL, "\n", &rest); + } + + // last mesh or if one wasnt created with 'o' directive + if (face_darray_len(tmp_faces) > 0) { + TRACE("Last leftover mesh"); + create_submesh(meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, materials, + material_loaded, current_material_name); + } + + // Free data + free((char *)file_string); + vec3_darray_free(tmp_positions); + vec3_darray_free(tmp_normals); + vec2_darray_free(tmp_uvs); + face_darray_free(tmp_faces); + TRACE("Freed temporary OBJ loading data"); + + memset(out_model, 0, sizeof(model)); + if (mesh_darray_len(meshes) > 256) { + printf("num meshes: %ld\n", mesh_darray_len(meshes)); + } + for (int i = 0; i < mesh_darray_len(meshes); i++) { + mesh_darray_push(&out_model->meshes, ((mesh *)meshes->data)[i]); + // TODO: bounding box calculation for each mesh + } + // TODO: bounding box calculation for model + + for (int i = 0; i < material_darray_len(materials); i++) { + material_darray_push(&out_model->materials, ((material *)materials->data)[i]); + } + + return true; +} + +/** + * @brief Takes the current positions, normals, uvs arrays and constructs the vertex array + * from those indices. + */ +void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray *tmp_normals, + vec2_darray *tmp_uvs, face_darray *tmp_faces, material_darray *materials, + bool material_loaded, char current_material_name[256]) { + size_t num_verts = face_darray_len(tmp_faces) * 3; + vertex_darray *out_vertices = vertex_darray_new(num_verts); + + face_darray_iter face_iter = face_darray_iter_new(tmp_faces); + struct face *f; + + while ((f = face_darray_iter_next(&face_iter))) { + for (int j = 0; j < 3; j++) { + vertex vert = { 0 }; + vert.position = tmp_positions->data[f->vertex_indices[j] - 1]; + if (vec3_darray_len(tmp_normals) == 0) { + vert.normal = vec3_create(0.0, 0.0, 0.0); + } else { + vert.normal = tmp_normals->data[f->normal_indices[j] - 1]; + } + vert.uv = tmp_uvs->data[f->uv_indices[j] - 1]; + vertex_darray_push(out_vertices, vert); + } + } + + DEBUG("Loaded submesh\n vertices: %zu\n uvs: %zu\n normals: %zu\n faces: %zu", + vec3_darray_len(tmp_positions), vec2_darray_len(tmp_uvs), vec3_darray_len(tmp_normals), + face_darray_len(tmp_faces)); + + // Clear current object faces + face_darray_clear(tmp_faces); + + mesh m = { .vertices = out_vertices }; + if (material_loaded) { + // linear scan to find material + bool found = false; + DEBUG("Num of materials : %ld", material_darray_len(materials)); + material_darray_iter mat_iter = material_darray_iter_new(materials); + blinn_phong_material *cur_material; + while ((cur_material = material_darray_iter_next(&mat_iter))) { + printf("Material name %s vs %s \n", cur_material->name, current_material_name); + if (strcmp(cur_material->name, current_material_name) == 0) { + DEBUG("Found match"); + m.material_index = mat_iter.current_idx - 1; + found = true; + break; + } + } + + if (!found) { + // TODO: default material + m.material_index = 0; + DEBUG("Set default material"); + } + } + mesh_darray_push(meshes, m); +} + +bool load_material_lib(const char *path, material_darray *materials) { + TRACE("BEGIN load material lib at %s", path); + + const char *file_string = string_from_file(path); + if (file_string == NULL) { + ERROR("couldnt load %s", path); + return false; + } + + char *pch; + char *saveptr; + pch = strtok_r((char *)file_string, "\n", &saveptr); + + material current_material = DEFAULT_MATERIAL; + + bool material_set = false; + + while (pch != NULL) { + char line_header[128]; + int offset = 0; + // read the first word of the line + int res = sscanf(pch, "%s %n", line_header, &offset); + if (res != 1) { + break; + } + + // When we see "newmtl", start a new material, or flush the previous one + if (strcmp(line_header, "newmtl") == 0) { + if (material_set) { + // a material was being parsed, so flush that one and start a new one + material_darray_push(materials, current_material); + DEBUG("pushed material with name %s", current_material.name); + WARN("Reset current material"); + current_material = DEFAULT_MATERIAL; + } else { + material_set = true; + } + // scan the new material name + char material_name[64]; + sscanf(pch + offset, "%s", current_material.name); + DEBUG("material name %s\n", current_material.name); + // current_material.name = material_name; + } else if (strcmp(line_header, "Ka") == 0) { + // ambient + sscanf(pch + offset, "%f %f %f", ¤t_material.ambient_colour.x, + ¤t_material.ambient_colour.y, ¤t_material.ambient_colour.z); + } else if (strcmp(line_header, "Kd") == 0) { + // diffuse + sscanf(pch + offset, "%f %f %f", ¤t_material.diffuse.x, ¤t_material.diffuse.y, + ¤t_material.diffuse.z); + } else if (strcmp(line_header, "Ks") == 0) { + // specular + sscanf(pch + offset, "%f %f %f", ¤t_material.specular.x, ¤t_material.specular.y, + ¤t_material.specular.z); + } else if (strcmp(line_header, "Ns") == 0) { + // specular exponent + sscanf(pch + offset, "%f", ¤t_material.spec_exponent); + } else if (strcmp(line_header, "map_Kd") == 0) { + char diffuse_map_path[1024] = "assets/"; + sscanf(pch + offset, "%s", diffuse_map_path + 7); + printf("load from %s\n", diffuse_map_path); + // -------------- + texture diffuse_texture = texture_data_load(diffuse_map_path, true); + current_material.diffuse_texture = diffuse_texture; + strcpy(current_material.diffuse_tex_path, diffuse_map_path); + texture_data_upload(¤t_material.diffuse_texture); + // -------------- + } else if (strcmp(line_header, "map_Ks") == 0) { + char specular_map_path[1024] = "assets/"; + sscanf(pch + offset, "%s", specular_map_path + 7); + // -------------- + texture specular_texture = texture_data_load(specular_map_path, true); + current_material.specular_texture = specular_texture; + strcpy(current_material.specular_tex_path, specular_map_path); + texture_data_upload(¤t_material.specular_texture); + // -------------- + } else if (strcmp(line_header, "map_Bump") == 0) { + // TODO + } + + pch = strtok_r(NULL, "\n", &saveptr); + } + + // last mesh or if one wasnt created with 'o' directive + // TRACE("Last leftover material"); + material_darray_push(materials, current_material); + + INFO("Loaded %ld materials", material_darray_len(materials)); + TRACE("END load material lib"); + return true; +} diff --git a/xmake.lua b/xmake.lua index e43d2ff..39bcab0 100644 --- a/xmake.lua +++ b/xmake.lua @@ -69,6 +69,7 @@ target("core_config") add_files("src/platform/*.c") add_files("src/renderer/*.c") add_files("src/renderer/backends/*.c") + add_files("src/resources/*.c") add_files("src/std/*.c") add_files("src/std/containers/*.c") add_files("src/systems/*.c") @@ -108,4 +109,4 @@ target("demo") set_group("examples") add_deps("core_static") add_files("examples/demo/demo.c") - set_rundir("$(projectdir)") \ No newline at end of file + set_rundir("$(projectdir)") -- cgit v1.2.3-70-g09d2 From 3854bef8b853a369c4fc3a39abff5e2e9cd77625 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Tue, 5 Mar 2024 21:27:34 +1100 Subject: why is it crashing on file loading now? --- examples/obj_loading/ex_obj_loading.c | 3 +++ src/platform/file.c | 6 +++++- src/renderer/render.h | 1 + src/resources/loaders.h | 3 +-- src/resources/obj.c | 4 +++- src/std/str.h | 7 ++++++- xmake.lua | 1 + 7 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src/renderer') diff --git a/examples/obj_loading/ex_obj_loading.c b/examples/obj_loading/ex_obj_loading.c index 3b2354a..87aeb2d 100644 --- a/examples/obj_loading/ex_obj_loading.c +++ b/examples/obj_loading/ex_obj_loading.c @@ -6,6 +6,9 @@ int main() { core* core = core_bringup(); + // Set up our scene + model_handle cube = model_load_obj(core, "assets/models/obj/cube/cube.obj", true); + // Main loop while (!glfwWindowShouldClose(core->renderer.window)) { input_update(&core->input); diff --git a/src/platform/file.c b/src/platform/file.c index 44aa9d0..4eeee46 100644 --- a/src/platform/file.c +++ b/src/platform/file.c @@ -12,6 +12,7 @@ const char *string_from_file(const char *path) { FILE *f = fopen(path, "rb"); + printf("Hello\n"); if (f == NULL) { ERROR("Error reading file: %s. errno: %d", path, errno); return NULL; @@ -20,6 +21,7 @@ const char *string_from_file(const char *path) { ERROR("Error reading file: %s. errno: %d", path, errno); return NULL; } + printf("Hello2\n"); fseek(f, 0, SEEK_END); long fsize = ftell(f); rewind(f); @@ -29,6 +31,8 @@ const char *string_from_file(const char *path) { fclose(f); string[fsize] = '\0'; + printf("Hello3\n"); + printf("Hello %s\n", string); return string; } @@ -60,4 +64,4 @@ str8_opt str8_from_file(arena *a, str8 path) { result.has_value = true; return result; -} \ No newline at end of file +} diff --git a/src/renderer/render.h b/src/renderer/render.h index c4e0dd6..d1de515 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -1,6 +1,7 @@ #pragma once #include "render_types.h" +#include "loaders.h" // --- Lifecycle /** @brief initialise the render system frontend */ diff --git a/src/resources/loaders.h b/src/resources/loaders.h index ba38ec4..8904655 100644 --- a/src/resources/loaders.h +++ b/src/resources/loaders.h @@ -3,7 +3,6 @@ #include "defines.h" struct core; -typedef u32 model_handle; model_handle model_load_obj(struct core *core, const char *path, bool invert_texture_y); -model_handle model_load_gltf(struct core *core, const char *path, bool invert_texture_y); \ No newline at end of file +model_handle model_load_gltf(struct core *core, const char *path, bool invert_texture_y); diff --git a/src/resources/obj.c b/src/resources/obj.c index 9e12f79..05aa96e 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -36,7 +36,9 @@ bool load_material_lib(const char *path, material_darray *materials); bool model_load_obj_str(const char *file_string, model *out_model, bool invert_textures_y); model_handle model_load_obj(core *core, const char *path, bool invert_textures_y) { + printf("Path %s\n", path); const char *file_string = string_from_file(path); + printf("Loaded file %s\n", file_string); model model; bool success = model_load_obj_str(file_string, &model, invert_textures_y); @@ -89,7 +91,7 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t } else { // read the first word of the line int res = sscanf(pch, "%s %n", line_header, &offset); - // printf("header: %s, offset : %d res: %d\n",line_header, offset, res); + /* printf("header: %s, offset : %d res: %d\n",line_header, offset, res); */ if (res != 1) { break; } diff --git a/src/std/str.h b/src/std/str.h index f6f8820..9f96430 100644 --- a/src/std/str.h +++ b/src/std/str.h @@ -70,4 +70,9 @@ str8 str8_concat(arena* a, str8 left, str8 right); static inline bool str8_is_null_term(str8 a) { return a.buf[a.len] == 0; // This doesn't seem safe. YOLO -} \ No newline at end of file +} + +// TODO: move or delete this and replace with handling using our internal type +static void skip_space(char *p) { + while (isspace((unsigned char)*p)) ++p; +} diff --git a/xmake.lua b/xmake.lua index 39bcab0..450b97d 100644 --- a/xmake.lua +++ b/xmake.lua @@ -60,6 +60,7 @@ target("core_config") add_includedirs("src/platform/", {public = true}) add_includedirs("src/renderer/", {public = true}) add_includedirs("src/renderer/backends/", {public = true}) + add_includedirs("src/resources/", {public = true}) add_includedirs("src/std/", {public = true}) add_includedirs("src/std/containers", {public = true}) add_includedirs("src/systems/", {public = true}) -- cgit v1.2.3-70-g09d2 From d5ae547334b5f8229313182705da42c5e904a633 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Tue, 5 Mar 2024 22:18:45 +1100 Subject: loads and runs now (no visuals yet) --- assets/models/obj/cube/cube.mtl | 3 +-- assets/models/obj/cube/cube.obj | 4 ++-- src/core.c | 5 ++--- src/empty.c | 4 +--- src/platform/file.c | 4 ---- src/renderer/render.h | 2 +- src/renderer/render_types.h | 2 +- src/resources/obj.c | 17 ++++++++--------- src/std/str.h | 2 +- 9 files changed, 17 insertions(+), 26 deletions(-) (limited to 'src/renderer') diff --git a/assets/models/obj/cube/cube.mtl b/assets/models/obj/cube/cube.mtl index 83a0e8c..9a17b69 100644 --- a/assets/models/obj/cube/cube.mtl +++ b/assets/models/obj/cube/cube.mtl @@ -10,5 +10,4 @@ Ke 0.0 0.0 0.0 Ni 1.450000 d 1.000000 illum 2 -map_Kd container.jpg - +map_Kd models/obj/cube/container.jpg diff --git a/assets/models/obj/cube/cube.obj b/assets/models/obj/cube/cube.obj index db3bda6..430e5da 100644 --- a/assets/models/obj/cube/cube.obj +++ b/assets/models/obj/cube/cube.obj @@ -1,7 +1,7 @@ # cube.obj # -mtllib cube.mtl +mtllib models/obj/cube/cube.mtl o cube v -0.500000 -0.500000 0.500000 @@ -44,4 +44,4 @@ f 2/1/5 8/2/5 4/3/5 f 4/3/5 8/2/5 6/4/5 s 6 f 7/1/6 1/2/6 5/3/6 -f 5/3/6 1/2/6 3/4/6 \ No newline at end of file +f 5/3/6 1/2/6 3/4/6 diff --git a/src/core.c b/src/core.c index affd8c8..024b2d7 100644 --- a/src/core.c +++ b/src/core.c @@ -45,8 +45,7 @@ core* core_bringup() { } */ - // c->underworld.models = model_darray_new(10); - // c->underworld.renderables = render_entity_darray_new(10); + c->models = model_darray_new(10); return c; -} \ No newline at end of file +} diff --git a/src/empty.c b/src/empty.c index d58a94f..b40cc85 100644 --- a/src/empty.c +++ b/src/empty.c @@ -1,5 +1,3 @@ // For some reason on Mac we need an empty file so that 'ar' has something // to run. -int add(int a, int b) { - return a + b; -} \ No newline at end of file +int add(int a, int b) { return a + b; } \ No newline at end of file diff --git a/src/platform/file.c b/src/platform/file.c index 4eeee46..ec9259a 100644 --- a/src/platform/file.c +++ b/src/platform/file.c @@ -12,7 +12,6 @@ const char *string_from_file(const char *path) { FILE *f = fopen(path, "rb"); - printf("Hello\n"); if (f == NULL) { ERROR("Error reading file: %s. errno: %d", path, errno); return NULL; @@ -21,7 +20,6 @@ const char *string_from_file(const char *path) { ERROR("Error reading file: %s. errno: %d", path, errno); return NULL; } - printf("Hello2\n"); fseek(f, 0, SEEK_END); long fsize = ftell(f); rewind(f); @@ -31,8 +29,6 @@ const char *string_from_file(const char *path) { fclose(f); string[fsize] = '\0'; - printf("Hello3\n"); - printf("Hello %s\n", string); return string; } diff --git a/src/renderer/render.h b/src/renderer/render.h index d1de515..e095e1c 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -1,7 +1,7 @@ #pragma once -#include "render_types.h" #include "loaders.h" +#include "render_types.h" // --- Lifecycle /** @brief initialise the render system frontend */ diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 45851fe..12b912d 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -107,7 +107,7 @@ KITC_DECL_TYPED_ARRAY(mesh) // creates "mesh_darray" typedef struct model { str8 name; - mesh_darray meshes; + mesh_darray *meshes; aabb_3d bbox; material_darray *materials; bool is_loaded; diff --git a/src/resources/obj.c b/src/resources/obj.c index d56e212..994e12a 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -11,8 +11,8 @@ #include #include "core.h" -#include "file.h" #include "darray.h" +#include "file.h" #include "log.h" #include "maths.h" #include "render.h" @@ -39,7 +39,7 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t model_handle model_load_obj(core *core, const char *path, bool invert_textures_y) { printf("Path %s\n", path); const char *file_string = string_from_file(path); - printf("Loaded file %s\n", file_string); + /* printf("Loaded file %s\n", file_string); */ model model; bool success = model_load_obj_str(file_string, &model, invert_textures_y); @@ -195,15 +195,14 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t if (mesh_darray_len(meshes) > 256) { printf("num meshes: %ld\n", mesh_darray_len(meshes)); } - for (int i = 0; i < mesh_darray_len(meshes); i++) { - mesh_darray_push(&out_model->meshes, ((mesh *)meshes->data)[i]); - // TODO: bounding box calculation for each mesh - } + out_model->meshes = meshes; + /* for (int i = 0; i < mesh_darray_len(meshes); i++) { */ + /* mesh_darray_push(&out_model->meshes, ((mesh *)meshes->data)[i]); */ + /* } */ + // TODO: bounding box calculation for each mesh // TODO: bounding box calculation for model - for (int i = 0; i < material_darray_len(materials); i++) { - material_darray_push(&out_model->materials, ((material *)materials->data)[i]); - } + out_model->materials = materials; return true; } diff --git a/src/std/str.h b/src/std/str.h index 518d508..b87864e 100644 --- a/src/std/str.h +++ b/src/std/str.h @@ -75,6 +75,6 @@ static inline bool str8_is_null_term(str8 a) { } // TODO: move or delete this and replace with handling using our internal type -static void skip_space(char *p) { +static void skip_space(char* p) { while (isspace((unsigned char)*p)) ++p; } -- cgit v1.2.3-70-g09d2 From 14424312813b55c62e44ef5c2152e27301733497 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Tue, 5 Mar 2024 23:03:20 +1100 Subject: pass mesh and material darrays for happy path. we will probably swap to an arena allocator for the temp darrays soon but not right yet --- src/renderer/render.c | 1 + src/resources/loaders.h | 1 + src/resources/obj.c | 38 +++++++++++++++++++++----------------- src/std/containers/darray.h | 14 +++++++++++--- 4 files changed, 34 insertions(+), 20 deletions(-) (limited to 'src/renderer') diff --git a/src/renderer/render.c b/src/renderer/render.c index f12954f..a0cc559 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -96,6 +96,7 @@ texture texture_data_load(const char* path, bool invert_y) { } void texture_data_upload(texture* tex) { + printf("Texture name %s\n", tex->name); TRACE("Upload texture data"); u32 texture_id; glGenTextures(1, &texture_id); diff --git a/src/resources/loaders.h b/src/resources/loaders.h index 8904655..858e4d1 100644 --- a/src/resources/loaders.h +++ b/src/resources/loaders.h @@ -1,6 +1,7 @@ #pragma once #include "defines.h" +#include "render_types.h" struct core; diff --git a/src/resources/obj.c b/src/resources/obj.c index fca6b0e..5fbfcdd 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -39,12 +39,16 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t model_handle model_load_obj(core *core, const char *path, bool invert_textures_y) { TRACE("Loading model at Path %s\n", path); const char *file_string = string_from_file(path); - model model; + + model model = { 0 }; + model.meshes = mesh_darray_new(1); + model.materials = material_darray_new(1); bool success = model_load_obj_str(file_string, &model, invert_textures_y); if (!success) { - exit(-1); // FIXME: Return some sort of result type? + FATAL("Couldnt load OBJ file at path %s", path); + ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); } u32 index = model_darray_len(core->models); @@ -61,9 +65,6 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t vec2_darray *tmp_uvs = vec2_darray_new(1000); face_darray *tmp_faces = face_darray_new(1000); - mesh_darray *meshes = mesh_darray_new(1); - material_darray *materials = material_darray_new(1); - // Other state bool object_set = false; bool material_loaded = false; @@ -101,16 +102,16 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t if (!object_set) { object_set = true; } else { - create_submesh(meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, materials, - material_loaded, current_material_name); + create_submesh(out_model->meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, + out_model->materials, material_loaded, current_material_name); object_set = false; } } else if (strcmp(line_header, "v") == 0) { // special logic: if we went from faces back to vertices trigger a mesh output. // PS: I hate OBJ if (last_char_type == 'f') { - create_submesh(meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, materials, - material_loaded, current_material_name); + create_submesh(out_model->meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, + out_model->materials, material_loaded, current_material_name); object_set = false; } @@ -163,8 +164,9 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t } else if (strcmp(line_header, "mtllib") == 0) { char path[1024] = "assets/"; sscanf(pch + offset, "%s", path + 7); - if (!load_material_lib(path, materials)) { + if (!load_material_lib(path, out_model->materials)) { ERROR("couldnt load material lib"); + return false; } } else if (strcmp(line_header, "usemtl") == 0) { material_loaded = true; @@ -178,8 +180,8 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t // last mesh or if one wasnt created with 'o' directive if (face_darray_len(tmp_faces) > 0) { TRACE("Last leftover mesh"); - create_submesh(meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, materials, - material_loaded, current_material_name); + create_submesh(out_model->meshes, tmp_positions, tmp_normals, tmp_uvs, tmp_faces, + out_model->materials, material_loaded, current_material_name); } // Free data @@ -190,16 +192,16 @@ bool model_load_obj_str(const char *file_string, model *out_model, bool invert_t face_darray_free(tmp_faces); TRACE("Freed temporary OBJ loading data"); - memset(out_model, 0, sizeof(model)); - if (mesh_darray_len(meshes) > 256) { - printf("num meshes: %ld\n", mesh_darray_len(meshes)); + /* memset(out_model, 0, sizeof(model)); */ + if (mesh_darray_len(out_model->meshes) > 256) { + printf("num meshes: %ld\n", mesh_darray_len(out_model->meshes)); } - out_model->meshes = meshes; + /* out_model->meshes = meshes; */ // TODO: bounding box calculation for each mesh // TODO: bounding box calculation for model - out_model->materials = materials; + /* out_model->materials = materials; */ return true; } @@ -347,6 +349,8 @@ bool load_material_lib(const char *path, material_darray *materials) { pch = strtok_r(NULL, "\n", &saveptr); } + TRACE("end load material lib"); + // last mesh or if one wasnt created with 'o' directive // TRACE("Last leftover material"); material_darray_push(materials, current_material); diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index 729b4cf..85e8048 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -33,14 +33,22 @@ #define PREFIX static + /* if (arena != NULL) {\ */ + /* d = arena_alloc(arena, sizeof(T##_darray));\ */ + /* data = arena_alloc(arena, starting_capacity * sizeof(T));\ */ + /* } else {\ */ + /* }\ */ + #define KITC_DECL_TYPED_ARRAY(T) \ typedef typed_array(T) T##_darray; \ typedef typed_array_iterator(T) T##_darray_iter; \ \ /* Create a new one growable array */ \ - PREFIX T##_darray *T##_darray_new(size_t starting_capacity) { \ - T##_darray *d = malloc(sizeof(T##_darray)); \ - T *data = malloc(starting_capacity * sizeof(T)); \ + PREFIX T##_darray *T##_darray_new(size_t starting_capacity) { \ + T##_darray *d;\ + T *data ; \ + d = malloc(sizeof(T##_darray)); \ + data = malloc(starting_capacity * sizeof(T));\ \ d->len = 0; \ d->capacity = starting_capacity; \ -- cgit v1.2.3-70-g09d2 From c7fabc44e62152c877b565c1da27a2e1d6f584f3 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 9 Mar 2024 16:34:46 +1100 Subject: renderer functions necessary for model drawing --- src/renderer/backends/backend_opengl.c | 82 +++++++++++++++++++ src/renderer/render.c | 139 +++++++++++++++++++++++++++++++++ src/renderer/render.h | 17 ++++ src/renderer/render_backend.h | 7 ++ src/renderer/render_types.h | 2 + 5 files changed, 247 insertions(+) (limited to 'src/renderer') diff --git a/src/renderer/backends/backend_opengl.c b/src/renderer/backends/backend_opengl.c index 6022dbf..ea6cb00 100644 --- a/src/renderer/backends/backend_opengl.c +++ b/src/renderer/backends/backend_opengl.c @@ -2,6 +2,7 @@ #define CEL_PLATFORM_LINUX #include "defines.h" +#include "file.h" #include "log.h" #include "maths_types.h" #include "render_types.h" @@ -59,4 +60,85 @@ void clear_screen(vec3 colour) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } +void bind_texture(shader s, texture *tex, u32 slot) { + // printf("bind texture slot %d with texture id %d \n", slot, tex->texture_id); + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_2D, tex->texture_id); +} + +void bind_mesh_vertex_buffer(void *_backend, mesh *mesh) { glBindVertexArray(mesh->vao); } + +static inline GLenum to_gl_prim_topology(enum cel_primitive_topology primitive) { + switch (primitive) { + case CEL_PRIMITIVE_TOPOLOGY_TRIANGLE: + return GL_TRIANGLES; + case CEL_PRIMITIVE_TOPOLOGY_POINT: + case CEL_PRIMITIVE_TOPOLOGY_LINE: + case CEL_PRIMITIVE_TOPOLOGY_LINE_STRIP: + case CEL_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: + case CEL_PRIMITIVE_TOPOLOGY_COUNT: + break; + } +} + +void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) { + u32 gl_primitive = to_gl_prim_topology(primitive); + glDrawArrays(gl_primitive, start_index, count); +} + +shader shader_create_separate(const char *vert_shader, const char *frag_shader) { + INFO("Load shaders at %s and %s", vert_shader, frag_shader); + int success; + char info_log[512]; + + u32 vertex = glCreateShader(GL_VERTEX_SHADER); + const char *vertex_shader_src = string_from_file(vert_shader); + if (vertex_shader_src == NULL) { + ERROR("EXIT: couldnt load shader"); + exit(-1); + } + glShaderSource(vertex, 1, &vertex_shader_src, NULL); + glCompileShader(vertex); + glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(vertex, 512, NULL, info_log); + printf("%s\n", info_log); + ERROR("EXIT: vertex shader compilation failed"); + exit(-1); + } + + // fragment shader + u32 fragment = glCreateShader(GL_FRAGMENT_SHADER); + const char *fragment_shader_src = string_from_file(frag_shader); + if (fragment_shader_src == NULL) { + ERROR("EXIT: couldnt load shader"); + exit(-1); + } + glShaderSource(fragment, 1, &fragment_shader_src, NULL); + glCompileShader(fragment); + glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(fragment, 512, NULL, info_log); + printf("%s\n", info_log); + ERROR("EXIT: fragment shader compilation failed"); + exit(-1); + } + + u32 shader_prog; + shader_prog = glCreateProgram(); + + glAttachShader(shader_prog, vertex); + glAttachShader(shader_prog, fragment); + glLinkProgram(shader_prog); + glDeleteShader(vertex); + glDeleteShader(fragment); + free((char *)vertex_shader_src); + free((char *)fragment_shader_src); + + shader s = { .program_id = shader_prog }; + return s; +} + +void set_shader(shader s) { glUseProgram(s.program_id); } + #endif \ No newline at end of file diff --git a/src/renderer/render.c b/src/renderer/render.c index a0cc559..dc541d2 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -5,13 +5,21 @@ #include #include "render.h" +#include "render_types.h" #include #include +#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 1080 +#define SCR_HEIGHT 800 + material DEFAULT_MATERIAL = { 0 }; bool renderer_init(renderer* ren) { @@ -20,6 +28,12 @@ bool renderer_init(renderer* ren) { // NOTE: all platforms use GLFW at the moment but thats subject to change glfwInit(); + DEBUG("init graphics api (OpenGL) backend"); + 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); + // glfw window creation GLFWwindow* window = glfwCreateWindow(ren->config.scr_width, ren->config.scr_height, ren->config.window_name, NULL, NULL); @@ -37,6 +51,9 @@ bool renderer_init(renderer* ren) { return false; } + ren->blinn_phong = + shader_create_separate("assets/shaders/blinn_phong.vert", "assets/shaders/blinn_phong.frag"); + return true; } @@ -63,6 +80,128 @@ void default_material_init() { texture_data_upload(&DEFAULT_MATERIAL.specular_texture); } +void draw_model(renderer* ren, camera* camera, model* model, transform tf) { + // 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); + + 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); + draw_mesh(ren, m, tf, &(DEFAULT_MATERIAL), &view, &proj); + } +} + +void draw_mesh(renderer* ren, mesh* mesh, transform 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 transform + 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); + // upload view & projection matrices + 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 model_upload_meshes(renderer* ren, model* model) { + INFO("Upload mesh vertex data to GPU for model %s", model->name); + // DEBUG("Loading model with handle %d", model_handle.raw); + // model m = models->data[model_handle.raw]; + + 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++) { + 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; + + // TODO: convert this garbage into a function + f32 verts[num_vertices * 8]; + // for each face + for (int i = 0; i < (num_vertices / 3); i++) { + // for each vert in face + for (int j = 0; j < 3; j++) { + size_t stride = (i * 24) + j * 8; + // printf("i: %d, stride: %ld, loc %d\n", i, stride, i * 3 + j); + vertex vert = model->meshes->data[mesh_i].vertices->data[i]; + // printf("pos %f %f %f\n", vert.position.x, vert.position.y, vert.position.z); + // printf("norm %f %f %f\n", vert.normal.x, vert.normal.y, vert.normal.z); + // printf("tex %f %f\n", vert.uv.x, vert.uv.y); + verts[stride + 0] = + ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].position.x; + verts[stride + 1] = + ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].position.y; + verts[stride + 2] = + ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].position.z; + verts[stride + 3] = + ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].normal.x; + verts[stride + 4] = + ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].normal.y; + verts[stride + 5] = + ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].normal.z; + verts[stride + 6] = ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].uv.x; + verts[stride + 7] = ((vertex*)model->meshes->data[mesh_i].vertices->data)[i * 3 + j].uv.y; + } + } + + // 4. upload data + glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, 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, 8 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + // normal vector attribute + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + // tex coords + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glEnableVertexAttribArray(2); + } + + 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); diff --git a/src/renderer/render.h b/src/renderer/render.h index e095e1c..65ace4e 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -1,5 +1,6 @@ #pragma once +#include "camera.h" #include "loaders.h" #include "render_types.h" @@ -14,6 +15,22 @@ void renderer_shutdown(renderer* ren); void render_frame_begin(renderer* ren); void render_frame_end(renderer* ren); +// --- models meshes +void model_upload_meshes(renderer* ren, model* model); +void draw_model(renderer* ren, camera* camera, model* model, transform tf); +void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* view, mat4* proj); + // --- texture texture_data_load(const char* path, bool invert_y); // #frontend void texture_data_upload(texture* tex); // #backend + +// --- 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/render_backend.h b/src/renderer/render_backend.h index 61c7ab5..a524f7f 100644 --- a/src/renderer/render_backend.h +++ b/src/renderer/render_backend.h @@ -12,4 +12,11 @@ void gfx_backend_shutdown(renderer* ren); void clear_screen(vec3 colour); +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 diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 12b912d..746dfce 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -38,6 +38,8 @@ 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; } renderer; // --- Lighting & Materials -- cgit v1.2.3-70-g09d2 From a42c7d493a4b064b858dcd36623e13bc7099df9e Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 9 Mar 2024 16:38:15 +1100 Subject: chore: format --- README.md | 3 ++- src/camera.h | 3 ++- src/maths/maths.h | 15 +++++---------- src/renderer/render.h | 8 ++++---- src/renderer/render_backend.h | 4 ++-- 5 files changed, 15 insertions(+), 18 deletions(-) (limited to 'src/renderer') diff --git a/README.md b/README.md index ed073fa..ef09262 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,5 @@ All third-party dependencies are licensed under their own license. * Formatting * `xmake format` * Lint (no change) `find src/ -iname *.h -o -iname *.c | xargs clang-format --style=file --dry-run --Werror` - * Format (edit in place) `find src/ -iname *.h -o -iname *.c | xargs clang-format -i --style=file` \ No newline at end of file + * Format (edit in place) `find src/ \( -iname "*.h" -o -iname "*.c" \) | xargs clang-format -i --style=file` + * `clang-format` must be installed! \ No newline at end of file diff --git a/src/camera.h b/src/camera.h index df91712..f7bc6eb 100644 --- a/src/camera.h +++ b/src/camera.h @@ -23,4 +23,5 @@ typedef struct camera { camera camera_create(vec3 pos, vec3 front, vec3 up, f32 fov); /** @brief get a 4x4 transform matrix for the view and perspective projection */ -void camera_view_projection(camera *c, f32 screen_height, f32 screen_width,mat4 *out_view, mat4 *out_proj); \ No newline at end of file +void camera_view_projection(camera *c, f32 screen_height, f32 screen_width, mat4 *out_view, + mat4 *out_proj); \ No newline at end of file diff --git a/src/maths/maths.h b/src/maths/maths.h index fb1bba7..d832739 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -20,7 +20,7 @@ // Dimension 3 static inline vec3 vec3_create(f32 x, f32 y, f32 z) { return (vec3){ x, y, z }; } -#define vec3(x,y,z) (vec3_create(x, y, z)) +#define vec3(x, y, z) (vec3_create(x, y, z)) static inline vec3 vec3_add(vec3 a, vec3 b) { return (vec3){ a.x + b.x, a.y + b.y, a.z + b.z }; } static inline vec3 vec3_sub(vec3 a, vec3 b) { return (vec3){ a.x - b.x, a.y - b.y, a.z - b.z }; } static inline vec3 vec3_mult(vec3 a, f32 s) { return (vec3){ a.x * s, a.y * s, a.z * s }; } @@ -56,20 +56,15 @@ static inline vec2 vec2_create(f32 x, f32 y) { return (vec2){ x, y }; } // --- Quaternion Implementations -static inline f32 quat_dot(quat a, quat b) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -} +static inline f32 quat_dot(quat a, quat b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } static inline quat quat_normalise(quat a) { - f32 length = sqrtf( - quat_dot(a, a) // same as len squared + f32 length = sqrtf(quat_dot(a, a) // same as len squared ); - return (quat) { a.x/length, a.y/length,a.z/length,a.w/length }; + return (quat){ a.x / length, a.y / length, a.z / length, a.w / length }; } -static inline quat quat_ident() { - return (quat) { .x = 0.0, .y = 0.0, .z = 0.0, .w = 1.0 }; -} +static inline quat quat_ident() { return (quat){ .x = 0.0, .y = 0.0, .z = 0.0, .w = 1.0 }; } // --- Matrix Implementations diff --git a/src/renderer/render.h b/src/renderer/render.h index 65ace4e..35c2d91 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -27,10 +27,10 @@ void texture_data_upload(texture* tex); // #backend // --- Uniforms /** @brief upload a vec3 of f32 to a uniform */ -void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value); +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); +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); +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 +void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value); \ No newline at end of file diff --git a/src/renderer/render_backend.h b/src/renderer/render_backend.h index a524f7f..7e1c16c 100644 --- a/src/renderer/render_backend.h +++ b/src/renderer/render_backend.h @@ -12,11 +12,11 @@ void gfx_backend_shutdown(renderer* ren); void clear_screen(vec3 colour); -void bind_texture(shader s, texture *tex, u32 slot); +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); +shader shader_create_separate(const char* vert_shader, const char* frag_shader); void set_shader(shader s); // --- Uniforms -- cgit v1.2.3-70-g09d2 From 6c581ff56dfcc22c25538e305e58efd967dd640a Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Thu, 14 Mar 2024 21:54:55 +1100 Subject: lights, camera, action --- assets/shaders/blinn_phong.frag | 76 ++++++++++++++++++++++++++++++++++- examples/obj_loading/ex_obj_loading.c | 39 ++++++++++++++++-- src/renderer/render.c | 48 +++++++++++++++++++--- src/renderer/render.h | 2 +- src/renderer/render_types.h | 34 +++++++++++++++- src/resources/obj.c | 23 +++++++---- xmake.lua | 3 ++ 7 files changed, 205 insertions(+), 20 deletions(-) (limited to 'src/renderer') diff --git a/assets/shaders/blinn_phong.frag b/assets/shaders/blinn_phong.frag index a284948..095b19a 100644 --- a/assets/shaders/blinn_phong.frag +++ b/assets/shaders/blinn_phong.frag @@ -9,6 +9,25 @@ struct Material { float shininess; }; +struct DirLight { + vec3 direction; + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + +struct PointLight { + vec3 position; + // fall off properties + float constant; + float linear; + float quadratic; + + vec3 ambient; + vec3 diffuse; + vec3 specular; +}; + in VS_OUT { vec3 FragPos; vec3 Normal; @@ -16,6 +35,61 @@ in VS_OUT { vec4 FragPosLightSpace; } fs_in; +// --- Uniforms +#define NUM_POINT_LIGHTS 4 +uniform vec3 viewPos; +uniform Material material; +uniform DirLight dirLight; +uniform PointLight pointLights[NUM_POINT_LIGHTS]; + +// --- Function prototypes +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir); + void main() { - FragColor = vec4(1.0); + vec3 norm = normalize(fs_in.Normal); + vec3 viewDir = normalize(viewPos - fs_in.FragPos); + + vec3 result = CalcDirLight(dirLight, norm, viewDir); + for (int i = 0; i < 4; i++) { + result += CalcPointLight(pointLights[i], norm, fs_in.FragPos, viewDir); + } + + FragColor = vec4(result, 1.0); +} + +vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) +{ + vec3 lightDir = normalize(-light.direction); + // diffuse shading + float diff = max(dot(normal, lightDir), 0.0); + // specular shading + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // combine result + vec3 ambient = light.ambient * vec3(texture(material.diffuse, fs_in.TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, fs_in.TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, fs_in.TexCoords)); + return (ambient + diffuse + specular); +} + +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos); + // diffuse + float diff = max(dot(normal, lightDir), 0.0); + // specular + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + // attentuation + float distance = length(light.position - fragPos); + float attentuation = 1.0 / (light.constant + light.linear * distance * light.quadratic * (distance * distance)); + // result + vec3 ambient = light.ambient * vec3(texture(material.diffuse, fs_in.TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, fs_in.TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, fs_in.TexCoords)); + ambient *= attentuation; + diffuse *= attentuation; + specular *= attentuation; + return (ambient + diffuse + specular); } \ No newline at end of file diff --git a/examples/obj_loading/ex_obj_loading.c b/examples/obj_loading/ex_obj_loading.c index bdadd7e..02ed606 100644 --- a/examples/obj_loading/ex_obj_loading.c +++ b/examples/obj_loading/ex_obj_loading.c @@ -1,4 +1,5 @@ #include +#include #include "camera.h" #include "core.h" @@ -7,6 +8,14 @@ #include "render.h" #include "render_types.h" +const vec3 pointlight_positions[4] = { + {0.7, 0.2, 2.0}, + {2.3, -3.3, -4.0}, + {-4.0, 2.0, -12.0}, + {0.0, 0.0, -3.0}, +}; +point_light point_lights[4]; + int main() { core* core = core_bringup(); @@ -22,6 +31,30 @@ int main() { vec3 camera_pos = vec3(3., 4., 10.); vec3 camera_front = vec3_normalise(vec3_negate(camera_pos)); camera cam = camera_create(camera_pos, camera_front, VEC3_Y, deg_to_rad(45.0)); + // 4. create lights + + // directional (sun) light setup + directional_light dir_light = {.direction = (vec3){-0.2, -1.0, -0.3}, + .ambient = (vec3){0.2, 0.2, 0.2}, + .diffuse = (vec3){0.5, 0.5, 0.5}, + .specular = (vec3){1.0, 1.0, 1.0}}; + // point lights setup + for (int i = 0; i < 4; i++) { + point_lights[i].position = pointlight_positions[i]; + point_lights[i].ambient = (vec3){0.05, 0.05, 0.05}; + point_lights[i].diffuse = (vec3){0.8, 0.8, 0.8}; + point_lights[i].specular = (vec3){1.0, 1.0, 1.0}; + point_lights[i].constant = 1.0; + point_lights[i].linear = 0.09; + point_lights[i].quadratic = 0.032; + } + + scene our_scene = { + .dir_light = dir_light, + .n_point_lights = 4 + }; + memcpy(&our_scene.point_lights, &point_lights, sizeof(point_light[4])); + // --- Enter Main loop while (!glfwWindowShouldClose(core->renderer.window)) { @@ -30,10 +63,10 @@ int main() { render_frame_begin(&core->renderer); - // Draw the cube - transform cube_tf = + // Draw the backpack + transform model_tf = transform_create(VEC3_ZERO, quat_ident(), 2.0); // make the backpack a bit bigger - draw_model(&core->renderer, &cam, backpack, cube_tf); + draw_model(&core->renderer, &cam, backpack, model_tf, &our_scene); render_frame_end(&core->renderer); } diff --git a/src/renderer/render.c b/src/renderer/render.c index dc541d2..1c979e5 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -80,7 +80,7 @@ void default_material_init() { texture_data_upload(&DEFAULT_MATERIAL.specular_texture); } -void draw_model(renderer* ren, camera* camera, model* model, transform tf) { +void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene* scene) { // TRACE("Drawing model: %s", model->name); mat4 view; mat4 proj; @@ -88,13 +88,22 @@ void draw_model(renderer* ren, camera* camera, model* model, transform tf) { 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); - draw_mesh(ren, m, tf, &(DEFAULT_MATERIAL), &view, &proj); + material* mat = &model->materials->data[m->material_index]; + draw_mesh(ren, m, tf, mat, &view, &proj); } } @@ -127,8 +136,6 @@ void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* vie void model_upload_meshes(renderer* ren, model* model) { INFO("Upload mesh vertex data to GPU for model %s", model->name); - // DEBUG("Loading model with handle %d", model_handle.raw); - // model m = models->data[model_handle.raw]; size_t num_meshes = mesh_darray_len(model->meshes); u32 VBOs[num_meshes]; @@ -148,7 +155,7 @@ void model_upload_meshes(renderer* ren, model* model) { 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); + // TRACE("Uploading vertex array data: %d verts", num_vertices); total_verts += num_vertices; // TODO: convert this garbage into a function @@ -256,3 +263,34 @@ void texture_data_upload(texture* tex) { DEBUG("Freeing texture image data after uploading to GPU"); // stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around } + +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/render.h b/src/renderer/render.h index 35c2d91..10702e3 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -17,7 +17,7 @@ void render_frame_end(renderer* ren); // --- models meshes void model_upload_meshes(renderer* ren, model* model); -void draw_model(renderer* ren, camera* camera, model* model, transform tf); +void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene* scene); void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* view, mat4* proj); // --- diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 746dfce..483e392 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -78,6 +78,27 @@ KITC_DECL_TYPED_ARRAY(material) // creates "material_darray" #define TYPED_MATERIAL_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; @@ -90,8 +111,6 @@ KITC_DECL_TYPED_ARRAY(vertex) // creates "vertex_darray" #define TYPED_VERTEX_ARRAY #endif -// --- Models & Meshes - typedef struct mesh { vertex_darray *vertices; u32 vertex_size; /** size in bytes of each vertex including necessary padding */ @@ -121,6 +140,17 @@ 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 { diff --git a/src/resources/obj.c b/src/resources/obj.c index 658967e..221e3aa 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -35,7 +35,7 @@ KITC_DECL_TYPED_ARRAY(face) void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray *tmp_normals, vec2_darray *tmp_uvs, face_darray *tmp_faces, material_darray *materials, bool material_loaded, char current_material_name[256]); -bool load_material_lib(const char *path, material_darray *materials); +bool load_material_lib(const char *path, str8 relative_path, material_darray *materials); bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_model, bool invert_textures_y); @@ -182,7 +182,7 @@ bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_ sscanf(pch + offset, "%s", filename); char mtllib_path[1024]; snprintf(mtllib_path, sizeof(mtllib_path), "%s/%s", relative_path.buf, filename); - if (!load_material_lib(mtllib_path, out_model->materials)) { + if (!load_material_lib(mtllib_path, relative_path, out_model->materials)) { ERROR("couldnt load material lib"); return false; } @@ -262,7 +262,6 @@ void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray material_darray_iter mat_iter = material_darray_iter_new(materials); blinn_phong_material *cur_material; while ((cur_material = material_darray_iter_next(&mat_iter))) { - printf("Material name %s vs %s \n", cur_material->name, current_material_name); if (strcmp(cur_material->name, current_material_name) == 0) { DEBUG("Found match"); m.material_index = mat_iter.current_idx - 1; @@ -280,7 +279,7 @@ void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray mesh_darray_push(meshes, m); } -bool load_material_lib(const char *path, material_darray *materials) { +bool load_material_lib(const char *path,str8 relative_path, material_darray *materials) { TRACE("BEGIN load material lib at %s", path); const char *file_string = string_from_file(path); @@ -338,9 +337,12 @@ bool load_material_lib(const char *path, material_darray *materials) { // specular exponent sscanf(pch + offset, "%f", ¤t_material.spec_exponent); } else if (strcmp(line_header, "map_Kd") == 0) { - char diffuse_map_path[1024] = "assets/"; - sscanf(pch + offset, "%s", diffuse_map_path + 7); + char diffuse_map_filename[1024]; + sscanf(pch + offset, "%s", diffuse_map_filename); + char diffuse_map_path[1024]; + snprintf(diffuse_map_path, sizeof(diffuse_map_path), "%s/%s", relative_path.buf, diffuse_map_filename); printf("load from %s\n", diffuse_map_path); + // -------------- texture diffuse_texture = texture_data_load(diffuse_map_path, true); current_material.diffuse_texture = diffuse_texture; @@ -348,8 +350,13 @@ bool load_material_lib(const char *path, material_darray *materials) { texture_data_upload(¤t_material.diffuse_texture); // -------------- } else if (strcmp(line_header, "map_Ks") == 0) { - char specular_map_path[1024] = "assets/"; - sscanf(pch + offset, "%s", specular_map_path + 7); + // char specular_map_path[1024] = "assets/"; + // sscanf(pch + offset, "%s", specular_map_path + 7); + char specular_map_filename[1024]; + sscanf(pch + offset, "%s", specular_map_filename); + char specular_map_path[1024]; + snprintf(specular_map_path, sizeof(specular_map_path), "%s/%s", relative_path.buf, specular_map_filename); + printf("load from %s\n", specular_map_path); // -------------- texture specular_texture = texture_data_load(specular_map_path, true); current_material.specular_texture = specular_texture; diff --git a/xmake.lua b/xmake.lua index 15159ef..611b537 100644 --- a/xmake.lua +++ b/xmake.lua @@ -14,8 +14,11 @@ add_cflags("-Wall", "-Wextra", "-Wundef", "-Wdouble-promotion") if is_mode("debug") then add_cflags("-g") -- Add debug symbols in debug mode +elseif is_mode("release") then + add_defines("CRELEASE") end + -- Platform defines and system packages if is_plat("linux") then add_defines("CEL_PLATFORM_LINUX") -- cgit v1.2.3-70-g09d2 From b240374c23365e33727d78ca74e901bcb383e077 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Thu, 14 Mar 2024 21:55:25 +1100 Subject: chore: format --- examples/obj_loading/ex_obj_loading.c | 28 ++++++++++++---------------- src/renderer/render.c | 6 +++--- src/resources/obj.c | 8 +++++--- 3 files changed, 20 insertions(+), 22 deletions(-) (limited to 'src/renderer') diff --git a/examples/obj_loading/ex_obj_loading.c b/examples/obj_loading/ex_obj_loading.c index 02ed606..6f1f12a 100644 --- a/examples/obj_loading/ex_obj_loading.c +++ b/examples/obj_loading/ex_obj_loading.c @@ -9,10 +9,10 @@ #include "render_types.h" const vec3 pointlight_positions[4] = { - {0.7, 0.2, 2.0}, - {2.3, -3.3, -4.0}, - {-4.0, 2.0, -12.0}, - {0.0, 0.0, -3.0}, + { 0.7, 0.2, 2.0 }, + { 2.3, -3.3, -4.0 }, + { -4.0, 2.0, -12.0 }, + { 0.0, 0.0, -3.0 }, }; point_light point_lights[4]; @@ -34,28 +34,24 @@ int main() { // 4. create lights // directional (sun) light setup - directional_light dir_light = {.direction = (vec3){-0.2, -1.0, -0.3}, - .ambient = (vec3){0.2, 0.2, 0.2}, - .diffuse = (vec3){0.5, 0.5, 0.5}, - .specular = (vec3){1.0, 1.0, 1.0}}; + directional_light dir_light = { .direction = (vec3){ -0.2, -1.0, -0.3 }, + .ambient = (vec3){ 0.2, 0.2, 0.2 }, + .diffuse = (vec3){ 0.5, 0.5, 0.5 }, + .specular = (vec3){ 1.0, 1.0, 1.0 } }; // point lights setup for (int i = 0; i < 4; i++) { point_lights[i].position = pointlight_positions[i]; - point_lights[i].ambient = (vec3){0.05, 0.05, 0.05}; - point_lights[i].diffuse = (vec3){0.8, 0.8, 0.8}; - point_lights[i].specular = (vec3){1.0, 1.0, 1.0}; + point_lights[i].ambient = (vec3){ 0.05, 0.05, 0.05 }; + point_lights[i].diffuse = (vec3){ 0.8, 0.8, 0.8 }; + point_lights[i].specular = (vec3){ 1.0, 1.0, 1.0 }; point_lights[i].constant = 1.0; point_lights[i].linear = 0.09; point_lights[i].quadratic = 0.032; } - scene our_scene = { - .dir_light = dir_light, - .n_point_lights = 4 - }; + scene our_scene = { .dir_light = dir_light, .n_point_lights = 4 }; memcpy(&our_scene.point_lights, &point_lights, sizeof(point_light[4])); - // --- Enter Main loop while (!glfwWindowShouldClose(core->renderer.window)) { input_update(&core->input); diff --git a/src/renderer/render.c b/src/renderer/render.c index 1c979e5..7884db6 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -92,7 +92,7 @@ void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene 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 ++) { + for (int i = 0; i < scene->n_point_lights; i++) { point_light_upload_uniforms(ren->blinn_phong, &scene->point_lights[i], '0' + i); } @@ -264,14 +264,14 @@ void texture_data_upload(texture* tex) { // stbi_image_free(tex->image_data); // data is on gpu now so we dont need it around } -void dir_light_upload_uniforms(shader shader, directional_light *light) { +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) { +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"; diff --git a/src/resources/obj.c b/src/resources/obj.c index 221e3aa..710d5f0 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -279,7 +279,7 @@ void create_submesh(mesh_darray *meshes, vec3_darray *tmp_positions, vec3_darray mesh_darray_push(meshes, m); } -bool load_material_lib(const char *path,str8 relative_path, material_darray *materials) { +bool load_material_lib(const char *path, str8 relative_path, material_darray *materials) { TRACE("BEGIN load material lib at %s", path); const char *file_string = string_from_file(path); @@ -340,7 +340,8 @@ bool load_material_lib(const char *path,str8 relative_path, material_darray *mat char diffuse_map_filename[1024]; sscanf(pch + offset, "%s", diffuse_map_filename); char diffuse_map_path[1024]; - snprintf(diffuse_map_path, sizeof(diffuse_map_path), "%s/%s", relative_path.buf, diffuse_map_filename); + snprintf(diffuse_map_path, sizeof(diffuse_map_path), "%s/%s", relative_path.buf, + diffuse_map_filename); printf("load from %s\n", diffuse_map_path); // -------------- @@ -355,7 +356,8 @@ bool load_material_lib(const char *path,str8 relative_path, material_darray *mat char specular_map_filename[1024]; sscanf(pch + offset, "%s", specular_map_filename); char specular_map_path[1024]; - snprintf(specular_map_path, sizeof(specular_map_path), "%s/%s", relative_path.buf, specular_map_filename); + snprintf(specular_map_path, sizeof(specular_map_path), "%s/%s", relative_path.buf, + specular_map_filename); printf("load from %s\n", specular_map_path); // -------------- texture specular_texture = texture_data_load(specular_map_path, true); -- cgit v1.2.3-70-g09d2