diff options
Diffstat (limited to 'src/renderer')
-rw-r--r-- | src/renderer/archive/render.c | 413 | ||||
-rw-r--r-- | src/renderer/archive/render.h | 46 | ||||
-rw-r--r-- | src/renderer/archive/render_backend.h (renamed from src/renderer/render_backend.h) | 0 | ||||
-rw-r--r-- | src/renderer/archive/render_types.h | 210 | ||||
-rw-r--r-- | src/renderer/backends/backend_dx11.c | 4 | ||||
-rw-r--r-- | src/renderer/backends/backend_dx11.h | 27 | ||||
-rw-r--r-- | src/renderer/cleanroom/types.h | 130 | ||||
-rw-r--r-- | src/renderer/ral.h (renamed from src/renderer/cleanroom/ral.h) | 5 | ||||
-rw-r--r-- | src/renderer/ral_types.h | 93 | ||||
-rw-r--r-- | src/renderer/render.c | 395 | ||||
-rw-r--r-- | src/renderer/render.h | 41 | ||||
-rw-r--r-- | src/renderer/render_types.h | 277 |
12 files changed, 926 insertions, 715 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/render_backend.h b/src/renderer/archive/render_backend.h index da30bcc..da30bcc 100644 --- a/src/renderer/render_backend.h +++ b/src/renderer/archive/render_backend.h 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 diff --git a/src/renderer/backends/backend_dx11.c b/src/renderer/backends/backend_dx11.c index d991f03..7e48853 100644 --- a/src/renderer/backends/backend_dx11.c +++ b/src/renderer/backends/backend_dx11.c @@ -1,3 +1,5 @@ -#if CEL_REND_BACKEND_DX11 +#if defined(CEL_REND_BACKEND_DX11) +#include <d3d11.h> +#include <d3dcompiler.h> #endif
\ No newline at end of file diff --git a/src/renderer/backends/backend_dx11.h b/src/renderer/backends/backend_dx11.h new file mode 100644 index 0000000..163ca97 --- /dev/null +++ b/src/renderer/backends/backend_dx11.h @@ -0,0 +1,27 @@ +#pragma once +#include "ral.h" + +#define GPU_SWAPCHAIN_IMG_COUNT 2 + +typedef struct gpu_swapchain { +} gpu_swapchain; +typedef struct gpu_device { + // VkPhysicalDevice physical_device; + // VkDevice logical_device; + // VkPhysicalDeviceProperties properties; + // VkPhysicalDeviceFeatures features; + // VkPhysicalDeviceMemoryProperties memory; + // VkCommandPool pool; +} gpu_device; +typedef struct gpu_pipeline { +} gpu_pipeline; + +typedef struct gpu_renderpass { + // VkRenderPass vk_handle; + // VkFramebuffer framebuffers[GPU_SWAPCHAIN_IMG_COUNT]; + // u32 +} gpu_renderpass; + +typedef struct gpu_cmd_encoder { + // VkCommandBuffer cmd_buffer; +} gpu_cmd_encoder;
\ No newline at end of file diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h index 7a6cfbd..0a28b1c 100644 --- a/src/renderer/cleanroom/types.h +++ b/src/renderer/cleanroom/types.h @@ -3,22 +3,11 @@ #include "defines.h" #include "maths_types.h" #include "str.h" +#include "render_types.h" -CORE_DEFINE_HANDLE(buffer_handle); -CORE_DEFINE_HANDLE(texture_handle); -CORE_DEFINE_HANDLE(sampler_handle); -CORE_DEFINE_HANDLE(shader_handle); -CORE_DEFINE_HANDLE(model_handle); +// typedef struct transform_hierarchy { +// } transform_hierarchy; -typedef struct transform_hierarchy { -} transform_hierarchy; - -/** @brief Texture Description - used by texture creation functions */ -typedef struct texture_desc { - // gpu_texture_type tex_type; - // gpu_texture_format format; - // u32x2 extents; -} texture_desc; /* - render_types.h @@ -27,102 +16,10 @@ typedef struct texture_desc { - render.h ? */ -// gpu types -typedef enum gpu_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 { - CEL_TEXTURE_TYPE_2D, - CEL_TEXTURE_TYPE_3D, - CEL_TEXTURE_TYPE_2D_ARRAY, - CEL_TEXTURE_TYPE_CUBE_MAP, - CEL_TEXTURE_TYPE_COUNT -} gpu_texture_type; - -typedef enum gpu_texture_format { - CEL_TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, - CEL_TEXTURE_FORMAT_DEPTH_DEFAULT, - CEL_TEXTURE_FORMAT_COUNT -} gpu_texture_format; - /* render_types */ typedef struct model pbr_material; typedef struct model bp_material; // blinn-phong -#include "maths_types.h" - -typedef enum vertex_format { - VERTEX_STATIC_3D, - VERTEX_SPRITE, - VERTEX_SKINNED, - VERTEX_COUNT -} vertex_format; - -typedef union vertex { - struct { - vec3 position; - vec4 colour; - vec2 tex_coords; - vec3 normal; - } static_3d; /** @brief standard vertex format for static geometry in 3D */ - - struct { - vec2 position; - vec4 colour; - vec2 tex_coords; - } sprite; /** @brief vertex format for 2D sprites or quads */ - - struct { - vec3 position; - vec4 colour; - vec2 tex_coords; - vec3 normal; - vec4i bone_ids; // Integer vector for bone IDs - vec4 bone_weights; // Weight of each bone's influence - } skinned_3d; /** @brief vertex format for skeletal (animated) geometry in 3D */ -} vertex; - -KITC_DECL_TYPED_ARRAY(vertex) -KITC_DECL_TYPED_ARRAY(u32) - -typedef struct geometry_data { - vertex_format format; - vertex_darray vertices; - bool has_indices; - u32_darray indices; - vec3 colour; /** Optional: set vertex colours */ -} geometry_data; - -void geo_set_vertex_colours(geometry_data* geo, vec4 colour); - -typedef struct mesh { - buffer_handle vertex_buffer; - buffer_handle index_buffer; - u32 index_count; - bool has_indices; - geometry_data* vertices; // NULL means it has been freed -} mesh; - -/* Hot reloading: -C side - reload_model(): - - load model from disk using existing loader - - remove from transform graph so it isnt tried to be drawn - - - -*/ - -// TODO: move to some sort of render layer (not inside the abstraction layer) -typedef struct model { - str8 debug_name; - mesh* meshes; - u32 mesh_count; -} model; // ? How to tie together materials and shaders @@ -149,27 +46,6 @@ typedef struct model { /* --- Renderer layer */ /* render.h */ -typedef struct renderer { - void* backend_context; -} renderer; - -bool renderer_init(renderer* ren); -void renderer_shutdown(renderer* ren); - -// frontend -- these can be called from say a loop in an example, or via FFI -texture_handle texture_create(const char* debug_name, texture_desc description, const u8* data); - -// Frontend Resources -void texture_data_upload(texture_handle texture); -buffer_handle buffer_create(const char* debug_name, u64 size); -bool buffer_destroy(buffer_handle buffer); -sampler_handle sampler_create(); - -void shader_hot_reload(const char* filepath); - -// models and meshes are implemented **in terms of the above** -mesh mesh_create(geometry_data* geometry); -model_handle model_load(const char* debug_name, const char* filepath); // Drawing diff --git a/src/renderer/cleanroom/ral.h b/src/renderer/ral.h index 15eb027..fd83e76 100644 --- a/src/renderer/cleanroom/ral.h +++ b/src/renderer/ral.h @@ -11,8 +11,9 @@ */ #pragma once -#include "cleanroom/types.h" +#include "ral_types.h" #include "defines.h" +#include "str.h" // Forward declare structs typedef struct gpu_swapchain gpu_swapchain; @@ -25,7 +26,7 @@ typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission enum pipeline_kind { GRAPHICS, COMPUTE, -} pipeline_kind; +}; typedef struct shader_desc { const char* debug_name; diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h new file mode 100644 index 0000000..9b1ef62 --- /dev/null +++ b/src/renderer/ral_types.h @@ -0,0 +1,93 @@ +/** + * @file ral_types.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once + +#include "defines.h" +#include "maths_types.h" +#include "darray.h" + +#ifndef RENDERER_TYPED_HANDLES +CORE_DEFINE_HANDLE(buffer_handle); +CORE_DEFINE_HANDLE(texture_handle); +CORE_DEFINE_HANDLE(sampler_handle); +CORE_DEFINE_HANDLE(shader_handle); +CORE_DEFINE_HANDLE(model_handle); +#define ABSENT_MODEL_HANDLE 999999999 +#define RENDERER_TYPED_HANDLES +#endif + +// gpu types +typedef enum gpu_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 { + CEL_TEXTURE_TYPE_2D, + CEL_TEXTURE_TYPE_3D, + CEL_TEXTURE_TYPE_2D_ARRAY, + CEL_TEXTURE_TYPE_CUBE_MAP, + CEL_TEXTURE_TYPE_COUNT +} gpu_texture_type; + +typedef enum gpu_texture_format { + CEL_TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, + CEL_TEXTURE_FORMAT_DEPTH_DEFAULT, + CEL_TEXTURE_FORMAT_COUNT +} gpu_texture_format; + +/** @brief Texture Description - used by texture creation functions */ +typedef struct texture_desc { + // gpu_texture_type tex_type; + // gpu_texture_format format; + // u32x2 extents; +} texture_desc; + +typedef enum vertex_format { + VERTEX_STATIC_3D, + VERTEX_SPRITE, + VERTEX_SKINNED, + VERTEX_COUNT +} vertex_format; + +typedef union vertex { + struct { + vec3 position; + vec4 colour; + vec2 tex_coords; + vec3 normal; + } static_3d; /** @brief standard vertex format for static geometry in 3D */ + + struct { + vec2 position; + vec4 colour; + vec2 tex_coords; + } sprite; /** @brief vertex format for 2D sprites or quads */ + + struct { + vec3 position; + vec4 colour; + vec2 tex_coords; + vec3 normal; + vec4i bone_ids; // Integer vector for bone IDs + vec4 bone_weights; // Weight of each bone's influence + } skinned_3d; /** @brief vertex format for skeletal (animated) geometry in 3D */ +} vertex; + +#ifndef TYPED_VERTEX_ARRAY +KITC_DECL_TYPED_ARRAY(vertex) +KITC_DECL_TYPED_ARRAY(u32) +#define TYPED_VERTEX_ARRAY +#endif
\ No newline at end of file diff --git a/src/renderer/render.c b/src/renderer/render.c index b1e2a46..8cd7421 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -1,36 +1,9 @@ -#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 }; +#include "render.h" +#include "camera.h" bool renderer_init(renderer* ren) { - INFO("Renderer init"); + // INFO("Renderer init"); // NOTE: all platforms use GLFW at the moment but thats subject to change glfwInit(); @@ -48,7 +21,7 @@ bool renderer_init(renderer* ren) { 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"); + // ERROR("Failed to create GLFW window\n"); glfwTerminate(); return false; } @@ -56,358 +29,26 @@ bool renderer_init(renderer* ren) { glfwMakeContextCurrent(ren->window); - DEBUG("init graphics api backend"); - if (!gfx_backend_init(ren)) { - FATAL("Couldnt load graphics api backend"); - return false; - } + // 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->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"); + // ren->skinned = + // shader_create_separate("assets/shaders/skinned.vert", "assets/shaders/blinn_phong.frag"); - default_material_init(); + // 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 render_frame_begin(renderer* ren) {} +void render_frame_end(renderer* ren) {} +void render_frame_draw(renderer* ren) {} -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 +void gfx_backend_draw_frame(renderer* ren, camera* camera, mat4 model, texture* tex) {}
\ No newline at end of file diff --git a/src/renderer/render.h b/src/renderer/render.h index 31cf3b0..0aeeac2 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -10,37 +10,34 @@ */ #pragma once -#include "camera.h" -#include "loaders.h" #include "render_types.h" -#include "transform_hierarchy.h" +#include "ral_types.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); +// ! TEMP +typedef struct camera camera; +void gfx_backend_draw_frame(renderer* ren, camera* camera, mat4 model, texture* tex); + +// frontend -- these can be called from say a loop in an example, or via FFI +texture_handle texture_create(const char* debug_name, texture_desc description, const u8* data); + +// Frontend Resources +// TODO: void texture_data_upload(texture_handle texture); +void texture_data_upload(texture* tex); +texture texture_data_load(const char* path, bool invert_y); +buffer_handle buffer_create(const char* debug_name, u64 size); +bool buffer_destroy(buffer_handle buffer); +sampler_handle sampler_create(); -void draw_skinned_model(renderer* ren, camera* cam, model* model, transform tf, scene* scene); +void shader_hot_reload(const char* filepath); -void model_destroy(model* model); +// models and meshes are implemented **in terms of the above** +mesh mesh_create(geometry_data* geometry); -// --- -texture texture_data_load(const char* path, bool invert_y); // #frontend +model_handle model_load(const char* debug_name, const char* filepath);
\ No newline at end of file diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 3bce88f..bc9692f 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -1,60 +1,71 @@ -// /** -// * @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 +/** + * @file render_types.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once + +#include "ral_types.h" +#include "ral.h" +#if defined(CEL_PLATFORM_WINDOWS) +#include "backend_dx11.h" +#endif -#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; +struct GLFWwindow; + +/** @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 renderer { - struct GLFWwindow *window; /** Currently all platforms use GLFW*/ - void *backend_state; /** Graphics API-specific state */ + struct GLFWwindow* window; + void* backend_context; renderer_config config; - // shaders - shader blinn_phong; - shader skinned; + gpu_device* device; + gpu_pipeline* static_opaque_pipeline; } renderer; -// // --- Lighting & Materials +typedef struct geometry_data { + vertex_format format; + vertex_darray* vertices; // TODO: make it not a pointe + bool has_indices; + u32_darray indices; + vec3 colour; /** Optional: set vertex colours */ +} geometry_data; + +void geo_set_vertex_colours(geometry_data* geo, vec4 colour); + +typedef struct mesh { + buffer_handle vertex_buffer; + buffer_handle index_buffer; + u32 index_count; + bool has_indices; + geometry_data* vertices; // NULL means it has been freed +} mesh; + +/* Hot reloading: +C side - reload_model(): + - load model from disk using existing loader + - remove from transform graph so it isnt tried to be drawn +*/ + +typedef struct model { + str8 name; + mesh* meshes; + u32 mesh_count; +} model; typedef struct texture { u32 texture_id; - char name[MAX_TEXTURE_NAME_LEN]; + char name[256]; void *image_data; void *backend_data; u32 width; @@ -63,148 +74,42 @@ typedef struct texture { 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(); +typedef struct blinn_phong_material { + char name[256]; + 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; -#ifndef TYPED_MATERIAL_ARRAY -KITC_DECL_TYPED_ARRAY(material) // creates "material_darray" -#define TYPED_MATERIAL_ARRAY -#endif +// the default blinn-phong material. MUST be initialised with the function below +extern material DEFAULT_MATERIAL; +void default_material_init(); -#ifndef TYPED_ANIMATION_CLIP_ARRAY -KITC_DECL_TYPED_ARRAY(animation_clip) // creates "material_darray" -#define TYPED_ANIMATION_CLIP_ARRAY +#ifndef TYPED_MESH_ARRAY +KITC_DECL_TYPED_ARRAY(mesh) +#define TYPED_MESH_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 +#ifndef TYPED_MODEL_ARRAY +KITC_DECL_TYPED_ARRAY(model) +#define TYPED_MODEL_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_MATERIAL_ARRAY +KITC_DECL_TYPED_ARRAY(material) +#define TYPED_MATERIAL_ARRAY +#endif -// #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 +#ifndef TYPED_ANIMATION_CLIP_ARRAY +#include "animation.h" +KITC_DECL_TYPED_ARRAY(animation_clip) +#define TYPED_ANIMATION_CLIP_ARRAY +#endif
\ No newline at end of file |