diff options
-rw-r--r-- | bindgen/BINDGEN.md | 1 | ||||
-rw-r--r-- | examples/game_demo/game_demo.c | 73 | ||||
-rw-r--r-- | scripts/gen_amalgamation.sh | 5 | ||||
-rw-r--r-- | scripts/gen_apidocs.sh | 3 | ||||
-rw-r--r-- | scripts/header_check.sh | 1 | ||||
-rw-r--r-- | src/animation.c | 56 | ||||
-rw-r--r-- | src/animation.h | 106 | ||||
-rw-r--r-- | src/camera.c | 17 | ||||
-rw-r--r-- | src/camera.h | 34 | ||||
-rw-r--r-- | src/core.c | 89 | ||||
-rw-r--r-- | src/core.h | 40 | ||||
-rw-r--r-- | src/core/README.md | 3 | ||||
-rw-r--r-- | src/core/camera.c | 21 | ||||
-rw-r--r-- | src/core/camera.h | 37 | ||||
-rw-r--r-- | src/core/core.c | 75 | ||||
-rw-r--r-- | src/core/core.h | 21 | ||||
-rw-r--r-- | src/defines.h | 22 | ||||
-rw-r--r-- | src/maths/geometry.h | 42 | ||||
-rw-r--r-- | src/maths/maths.h | 160 | ||||
-rw-r--r-- | src/maths/maths_types.h | 49 | ||||
-rw-r--r-- | src/maths/primitives.c | 71 | ||||
-rw-r--r-- | src/maths/primitives.h | 10 | ||||
-rw-r--r-- | src/new_render/draw.h | 13 | ||||
-rw-r--r-- | src/new_render/immdraw.h | 14 | ||||
-rw-r--r-- | src/new_render/pbr.h | 62 | ||||
-rw-r--r-- | src/new_render/render.c | 34 | ||||
-rw-r--r-- | src/new_render/render.h | 54 | ||||
-rw-r--r-- | src/new_render/render_scene.h | 20 | ||||
-rw-r--r-- | src/new_render/render_types.h | 86 | ||||
-rw-r--r-- | src/new_render/shadows.h | 29 | ||||
-rw-r--r-- | src/new_render/skybox.h | 32 | ||||
-rw-r--r-- | src/platform/file.c | 6 | ||||
-rw-r--r-- | src/platform/file.h | 6 | ||||
-rw-r--r-- | src/platform/path.h | 4 | ||||
-rw-r--r-- | src/ral/README.md | 5 | ||||
-rw-r--r-- | src/ral/backends/metal/backend_metal.h | 0 | ||||
-rw-r--r-- | src/ral/backends/opengl/backend_opengl.h | 76 | ||||
-rw-r--r-- | src/ral/backends/vulkan/backend_vulkan.h | 0 | ||||
-rw-r--r-- | src/ral/ral.h | 5 | ||||
-rw-r--r-- | src/ral/ral_common.c | 19 | ||||
-rw-r--r-- | src/ral/ral_common.h | 39 | ||||
-rw-r--r-- | src/ral/ral_impl.h | 38 | ||||
-rw-r--r-- | src/ral/ral_types.h | 223 | ||||
-rw-r--r-- | src/render/backends/backend_test.c (renamed from src/renderer/backends/backend_test.c) | 0 | ||||
-rw-r--r-- | src/render/backends/metal/README.md (renamed from src/renderer/backends/metal/README.md) | 0 | ||||
-rw-r--r-- | src/render/backends/metal/backend_metal.h (renamed from src/renderer/backends/metal/backend_metal.h) | 0 | ||||
-rw-r--r-- | src/render/backends/metal/backend_metal.m (renamed from src/renderer/backends/metal/backend_metal.m) | 0 | ||||
-rw-r--r-- | src/render/backends/opengl/README.md (renamed from src/renderer/backends/opengl/README.md) | 0 | ||||
-rw-r--r-- | src/render/backends/opengl/backend_opengl.c (renamed from src/renderer/backends/opengl/backend_opengl.c) | 0 | ||||
-rw-r--r-- | src/render/backends/opengl/backend_opengl.h (renamed from src/renderer/backends/opengl/backend_opengl.h) | 0 | ||||
-rw-r--r-- | src/render/backends/opengl/opengl_helpers.h (renamed from src/renderer/backends/opengl/opengl_helpers.h) | 0 | ||||
-rw-r--r-- | src/render/backends/vulkan/README.md (renamed from src/renderer/backends/vulkan/README.md) | 0 | ||||
-rw-r--r-- | src/render/backends/vulkan/backend_vulkan.c (renamed from src/renderer/backends/backend_vulkan.c) | 0 | ||||
-rw-r--r-- | src/render/backends/vulkan/backend_vulkan.h (renamed from src/renderer/backends/backend_vulkan.h) | 0 | ||||
-rw-r--r-- | src/render/backends/vulkan/vulkan_glossary.md (renamed from src/renderer/backends/vulkan/vulkan_glossary.md) | 0 | ||||
-rw-r--r-- | src/render/backends/vulkan_helpers.h (renamed from src/renderer/backends/vulkan_helpers.h) | 0 | ||||
-rw-r--r-- | src/render/bind_group_layouts.h (renamed from src/renderer/bind_group_layouts.h) | 0 | ||||
-rw-r--r-- | src/render/builtin_materials.h (renamed from src/renderer/builtin_materials.h) | 0 | ||||
-rw-r--r-- | src/render/immediate.c (renamed from src/renderer/immediate.c) | 0 | ||||
-rw-r--r-- | src/render/immediate.h (renamed from src/renderer/immediate.h) | 0 | ||||
-rw-r--r-- | src/render/ral.c (renamed from src/renderer/ral.c) | 0 | ||||
-rw-r--r-- | src/render/ral.h (renamed from src/renderer/ral.h) | 50 | ||||
-rw-r--r-- | src/render/ral_types.h | 104 | ||||
-rw-r--r-- | src/render/render.c (renamed from src/renderer/render.c) | 0 | ||||
-rw-r--r-- | src/render/render.h (renamed from src/renderer/render.h) | 10 | ||||
-rw-r--r-- | src/render/render_types.h (renamed from src/renderer/render_types.h) | 0 | ||||
-rw-r--r-- | src/render/renderpasses.c (renamed from src/renderer/renderpasses.c) | 0 | ||||
-rw-r--r-- | src/render/renderpasses.h (renamed from src/renderer/renderpasses.h) | 0 | ||||
-rw-r--r-- | src/render/static_pipeline.h (renamed from src/renderer/static_pipeline.h) | 0 | ||||
-rw-r--r-- | src/renderer/backends/backend_dx11.c | 5 | ||||
-rw-r--r-- | src/renderer/backends/backend_dx11.h | 29 | ||||
-rw-r--r-- | src/renderer/ral_types.h | 268 | ||||
-rw-r--r-- | src/resources/gltf.c | 232 | ||||
-rw-r--r-- | src/resources/loaders.h | 10 | ||||
-rw-r--r-- | src/resources/obj.c | 372 | ||||
-rw-r--r-- | src/scene.c | 91 | ||||
-rw-r--r-- | src/scene.h | 44 | ||||
-rw-r--r-- | src/std/containers/darray.h | 11 | ||||
-rw-r--r-- | src/std/mem.h | 6 | ||||
-rw-r--r-- | src/std/str.c | 88 | ||||
-rw-r--r-- | src/std/str.h | 36 | ||||
-rw-r--r-- | src/systems/input.c | 12 | ||||
-rw-r--r-- | src/systems/input.h | 13 | ||||
-rw-r--r-- | src/systems/terrain.c | 35 | ||||
-rw-r--r-- | src/systems/terrain.h | 50 | ||||
-rw-r--r-- | src/systems/text.h | 82 | ||||
-rw-r--r-- | src/transform_hierarchy.c | 343 | ||||
-rw-r--r-- | src/transform_hierarchy.h | 109 | ||||
-rw-r--r-- | src/ui/ui.h | 13 | ||||
-rw-r--r-- | xmake.lua | 337 |
90 files changed, 2334 insertions, 1717 deletions
diff --git a/bindgen/BINDGEN.md b/bindgen/BINDGEN.md new file mode 100644 index 0000000..20ba803 --- /dev/null +++ b/bindgen/BINDGEN.md @@ -0,0 +1 @@ +This is where we host code generation tools for generating bindings to `celeritas-core` in other languages. diff --git a/examples/game_demo/game_demo.c b/examples/game_demo/game_demo.c new file mode 100644 index 0000000..a9f91ea --- /dev/null +++ b/examples/game_demo/game_demo.c @@ -0,0 +1,73 @@ +// Load a model +// Animate it +// Collide with the ground +// Have a skybox + +#include <assert.h> +#include "camera.h" +#include "core.h" +#include "maths.h" +#include "render.h" +#include "render_scene.h" +#include "render_types.h" +#include "skybox.h" +#include "str.h" +#include "terrain.h" +#include "transform_hierarchy.h" + +static const char* faces[6] = { "assets/demo/skybox/left.jpg", "assets/demo/skybox/right.jpg", + "assets/demo/skybox/front.jpg", "assets/demo/skybox/back.jpg", + "assets/demo/skybox/top.jpg", "assets/demo/skybox/bottom.jpg" }; + +int main() { + Core_Bringup(); + + Vec3 camera_pos = vec3(0.0, 4.0, 8.0); + Camera cam = Camera_Create(camera_pos, vec3_negate(camera_pos), VEC3_Y, 45.0); + SetCamera(cam); // update the camera in RenderScene + + // TODO: Load humanoid model + weapon + // TODO: Animate it with WASD keys + // TODO: Skybox + // TODO: Add a ground terrain + // TODO: Move camera with model + + // --- Terrain + Heightmap terrain = Heightmap_FromImage(str8("assets/demo/heightmap.png")); + Terrain_LoadHeightmap(terrain, true); + assert(Terrain_IsActive()); + + // --- Skybox + Skybox skybox = Skybox_Create(faces, 6); + + // --- Models + ModelHandle player_model = ModelLoad("Player Model", "assets/demo/player.gltf"); + ModelHandle sword_model = ModelLoad("Sword Model", "assets/demo/sword.gltf"); + + // --- Transforms + // TransformHierarchy* scene_tree = TransformHierarchy_Create(); + // TODO: parent camera to model - to start with I can just manually update it every frame + // TODO: query joints of the gltf to get the hand bone to parent a sword to + + RenderEnt player_r = { .model = player_model, .affine = mat4_ident(), .casts_shadows = true }; + + RenderEnt entities[] = { player_r }; + + while (!ShouldExit()) { + Frame_Begin(); + + // BEGIN Draw calls + + // draw the player model with shadows + Render_RenderEntities(entities, 1); + Render_DrawTerrain(); + Skybox_Draw(&skybox); + + // END Draw calls + Frame_Draw(); + Frame_End(); + } + + Core_Shutdown(); + return 0; +} diff --git a/scripts/gen_amalgamation.sh b/scripts/gen_amalgamation.sh new file mode 100644 index 0000000..56df62e --- /dev/null +++ b/scripts/gen_amalgamation.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# Generates a single amalgamation C header file that includes all public types and functions. +# +# This makes including and linking Celeritas very easy. diff --git a/scripts/gen_apidocs.sh b/scripts/gen_apidocs.sh new file mode 100644 index 0000000..afad30e --- /dev/null +++ b/scripts/gen_apidocs.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +# Generates a static webpage for the public C-API of `celeritas-core` diff --git a/scripts/header_check.sh b/scripts/header_check.sh deleted file mode 100644 index 2edd9fe..0000000 --- a/scripts/header_check.sh +++ /dev/null @@ -1 +0,0 @@ -# TODO - check .h files for a valid header with @brief and #pragma once
\ No newline at end of file diff --git a/src/animation.c b/src/animation.c index 7a79529..1c5d893 100644 --- a/src/animation.c +++ b/src/animation.c @@ -2,37 +2,37 @@ #include "log.h" #include "maths.h" -keyframe animation_sample(animation_sampler *sampler, f32 t) { - size_t previous_index = 0; - f32 previous_time = 0.0; - // look forwards - // DEBUG("%d\n", sampler->animation.values.kind); - TRACE("Total timestamps %d", sampler->animation.n_timestamps); - for (u32 i = 0; i < sampler->animation.n_timestamps; i++) { - f32 current_time = sampler->animation.timestamps[i]; - if (current_time > t) { - break; - } - previous_time = sampler->animation.timestamps[i]; - previous_index = i; - } +// keyframe animation_sample(animation_sampler *sampler, f32 t) { +// size_t previous_index = 0; +// f32 previous_time = 0.0; +// // look forwards +// // DEBUG("%d\n", sampler->animation.values.kind); +// TRACE("Total timestamps %d", sampler->animation.n_timestamps); +// for (u32 i = 0; i < sampler->animation.n_timestamps; i++) { +// f32 current_time = sampler->animation.timestamps[i]; +// if (current_time > t) { +// break; +// } +// previous_time = sampler->animation.timestamps[i]; +// previous_index = i; +// } - size_t next_index = (previous_index + 1) % sampler->animation.n_timestamps; - f32 next_time = sampler->animation.timestamps[next_index]; - printf("%d %f %d %f\n", previous_index, previous_time, next_index, next_time); +// size_t next_index = (previous_index + 1) % sampler->animation.n_timestamps; +// f32 next_time = sampler->animation.timestamps[next_index]; +// printf("%d %f %d %f\n", previous_index, previous_time, next_index, next_time); - keyframe prev_value = sampler->animation.values.values[previous_index]; - keyframe next_value = sampler->animation.values.values[next_index]; +// keyframe prev_value = sampler->animation.values.values[previous_index]; +// keyframe next_value = sampler->animation.values.values[next_index]; - printf("%d %d\n", previous_index, next_index); +// printf("%d %d\n", previous_index, next_index); - f32 time_diff = - sampler->animation.timestamps[next_index] - sampler->animation.timestamps[previous_index]; - f32 percent = (t - previous_time) / time_diff; +// f32 time_diff = +// sampler->animation.timestamps[next_index] - sampler->animation.timestamps[previous_index]; +// f32 percent = (t - previous_time) / time_diff; - quat interpolated_rot = - quat_slerp(sampler->animation.values.values[previous_index].rotation, - sampler->animation.values.values[next_index].rotation, percent); +// quat interpolated_rot = +// quat_slerp(sampler->animation.values.values[previous_index].rotation, +// sampler->animation.values.values[next_index].rotation, percent); - return (keyframe){ .rotation = interpolated_rot }; -}
\ No newline at end of file +// return (keyframe){ .rotation = interpolated_rot }; +// } diff --git a/src/animation.h b/src/animation.h index 5462e65..9c7faab 100644 --- a/src/animation.h +++ b/src/animation.h @@ -6,67 +6,67 @@ KITC_DECL_TYPED_ARRAY(f32) -typedef enum interpolation { INTERPOLATION_LINEAR, INTERPOLATION_COUNT } interpolation; +// typedef enum interpolation { INTERPOLATION_LINEAR, INTERPOLATION_COUNT } interpolation; -typedef enum keyframe_kind { - KEYFRAME_ROTATION, - KEYFRAME_TRANSLATION, - KEYFRAME_SCALE, - KEYFRAME_WEIGHTS, -} keyframe_kind; +// typedef enum keyframe_kind { +// KEYFRAME_ROTATION, +// KEYFRAME_TRANSLATION, +// KEYFRAME_SCALE, +// KEYFRAME_WEIGHTS, +// } keyframe_kind; -typedef union keyframe { - quat rotation; - vec3 translation; - vec3 scale; - float* weights; -} keyframe; +// typedef union keyframe { +// quat rotation; +// vec3 translation; +// vec3 scale; +// float* weights; +// } keyframe; -typedef struct keyframes { - keyframe_kind kind; - keyframe* values; - size_t count; -} keyframes; +// typedef struct keyframes { +// keyframe_kind kind; +// keyframe* values; +// size_t count; +// } keyframes; -typedef struct joint { - char* name; // optional - transform transform_components; - mat4 inverse_bind_matrix; - mat4 local_transform; -} joint; +// typedef struct joint { +// char* name; // optional +// transform transform_components; +// mat4 inverse_bind_matrix; +// mat4 local_transform; +// } joint; -typedef struct animation_spline { - f32* timestamps; - size_t n_timestamps; - keyframes values; - interpolation interpolation; -} animation_spline; +// typedef struct animation_spline { +// f32* timestamps; +// size_t n_timestamps; +// keyframes values; +// interpolation interpolation; +// } animation_spline; -typedef struct animation_sampler { - int current_index; - f32 min; - f32 max; - animation_spline animation; -} animation_sampler; +// typedef struct animation_sampler { +// int current_index; +// f32 min; +// f32 max; +// animation_spline animation; +// } animation_sampler; -/** @brief Sample an animation at a given time `t` */ -keyframe animation_sample(animation_sampler* sampler, f32 t); +// /** @brief Sample an animation at a given time `t` */ +// keyframe animation_sample(animation_sampler* sampler, f32 t); -typedef struct animation_clip { - // A clip contains one or more animation curves - // for now I think we can just enumerate all of the properties (assuming *only* one per type is in - // a clip) NULL = this property is not animated in this clip - animation_sampler* rotation; - animation_sampler* translation; - animation_sampler* scale; - animation_sampler* weights; -} animation_clip; +// typedef struct animation_clip { +// // A clip contains one or more animation curves +// // for now I think we can just enumerate all of the properties (assuming *only* one per type is in +// // a clip) NULL = this property is not animated in this clip +// animation_sampler* rotation; +// animation_sampler* translation; +// animation_sampler* scale; +// animation_sampler* weights; +// } animation_clip; -typedef struct skinned_animation { - mat4* joint_matrices; - size_t n_joints; -} skinned_animation; +// typedef struct skinned_animation { +// mat4* joint_matrices; +// size_t n_joints; +// } skinned_animation; -// void animation_update_joint_matrices(animation_clip* ) +// // void animation_update_joint_matrices(animation_clip* ) -void animation_play(animation_clip* clip);
\ No newline at end of file +// void animation_play(animation_clip* clip); diff --git a/src/camera.c b/src/camera.c deleted file mode 100644 index 8ec1251..0000000 --- a/src/camera.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "camera.h" - -#include "maths.h" - -camera camera_create(vec3 pos, vec3 front, vec3 up, f32 fov) { - camera c = { .position = pos, .front = front, .up = up, .fov = fov }; - return c; -} - -void camera_view_projection(camera *c, f32 screen_height, f32 screen_width, mat4 *out_view, - mat4 *out_proj) { - mat4 proj = mat4_perspective(c->fov, screen_width / screen_height, 0.1, 100.0); - vec3 camera_direction = vec3_add(c->position, c->front); - mat4 view = mat4_look_at(c->position, camera_direction, c->up); - *out_view = view; - *out_proj = proj; -}
\ No newline at end of file diff --git a/src/camera.h b/src/camera.h deleted file mode 100644 index ec867c5..0000000 --- a/src/camera.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file camera.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-02-24 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once - -#include "maths_types.h" - -typedef struct camera { - vec3 position; - vec3 front; - vec3 up; - f32 fov; -} camera; - -/** @brief create a 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); - -// TODO: Basic reusable camera controls -/* -Right click + move = pan -Left click = orbit camera -WASD = forward/backward/left/right -*/
\ No newline at end of file diff --git a/src/core.c b/src/core.c deleted file mode 100644 index 1d8fe91..0000000 --- a/src/core.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "core.h" - -#include <stdlib.h> - -#include "glfw3.h" -#include "input.h" -#include "keys.h" -#include "log.h" -#include "mem.h" -#include "render.h" -#include "render_types.h" -#include "scene.h" -// #include "threadpool.h" - -#define SCR_WIDTH 1000 -#define SCR_HEIGHT 1000 - -core g_core; /** @brief global `core` that other files can use */ - -inline core* get_global_core() { return &g_core; } - -void core_bringup() { - INFO("Initiate Core bringup"); - renderer_config conf = { .window_name = { "Celeritas Engine Core" }, - .scr_width = SCR_WIDTH, - .scr_height = SCR_HEIGHT, - .clear_colour = (vec3){ .08, .08, .1 } }; - g_core.renderer.config = conf; - g_core.renderer.backend_context = NULL; - - // threadpool_create(&c->threadpool, 6, 256); - // threadpool_set_ctx(&c->threadpool, c); // Gives the threadpool access to the core - - // initialise all subsystems - if (!renderer_init(&g_core.renderer)) { - // FATAL("Failed to start renderer"); - ERROR_EXIT("Failed to start renderer\n"); - } - if (!input_system_init(&g_core.input, g_core.renderer.window)) { - // the input system needs the glfw window which is created by the renderer - // hence the order here is important - FATAL("Failed to start input system"); - ERROR_EXIT("Failed to start input system\n"); - } - /* - if (!text_system_init(&c->text)) { - // FATAL("Failed to start text system"); - ERROR_EXIT("Failed to start text system\n"); - } - if (!screenspace_2d_init(&c->screenspace)) { - // FATAL("Failed to start screenspace 2d plugin"); - ERROR_EXIT("Failed to start screenspace 2d plugin\n"); - } - */ - - size_t model_data_max = 1024 * 1024 * 1024; - arena model_arena = arena_create(malloc(model_data_max), model_data_max); - - model_pool model_pool = model_pool_create(&model_arena, 256, sizeof(model)); - g_core.models = model_pool; - INFO("Created model pool allocator"); - - INFO("Creating default scene"); - scene_init(&g_core.default_scene); -} - -#include <glfw3.h> - -/* bool should_window_close(core* core) { glfwWindowShouldClose(core->renderer.window); } */ -void core_input_update() { input_update(&g_core.input); } -void core_frame_begin(core* core) { render_frame_begin(&core->renderer); } -void core_frame_end(core* core) { render_frame_end(&core->renderer); } - -void core_shutdown() { - // threadpool_destroy(&core->threadpool); - input_system_shutdown(&g_core.input); - renderer_shutdown(&g_core.renderer); -} - -bool should_exit() { - return key_just_released(KEYCODE_ESCAPE) || glfwWindowShouldClose(g_core.renderer.window); -} - -void frame_begin() { - glfwPollEvents(); - render_frame_begin(&g_core.renderer); -} -void frame_draw() {} -void frame_end() { render_frame_end(&g_core.renderer); } diff --git a/src/core.h b/src/core.h deleted file mode 100644 index 89702fd..0000000 --- a/src/core.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "input.h" -#include "render_types.h" -#include "scene.h" -#include "screenspace.h" -#include "terrain.h" -#include "text.h" -// #include "threadpool.h" - -typedef struct core { - const char* app_name; - // foundations - renderer renderer; - // threadpool threadpool; - // systems - input_state input; - text_system_state text; - terrain_state terrain; - screenspace_state screenspace; - // data storage - scene default_scene; - model_pool models; - // model_darray* models; -} core; - -core* get_global_core(); - -// --- Lifecycle - -/** @brief Throws error if the core cannot be instantiated */ -void core_bringup(); -void core_shutdown(); -bool should_exit(); - -void frame_begin(); -void frame_draw(); -void frame_end(); - -void core_input_update(); diff --git a/src/core/README.md b/src/core/README.md new file mode 100644 index 0000000..19cc1d0 --- /dev/null +++ b/src/core/README.md @@ -0,0 +1,3 @@ +# Core + +Core engine facilities diff --git a/src/core/camera.c b/src/core/camera.c new file mode 100644 index 0000000..428a50d --- /dev/null +++ b/src/core/camera.c @@ -0,0 +1,21 @@ +#include "camera.h" + +#include "maths.h" + +Camera Camera_Create(Vec3 pos, Vec3 front, Vec3 up, f32 fov) { + Camera c = { .position = pos, .front = front, .up = up, .fov = fov }; + return c; +} + +Mat4 Camera_ViewProj(Camera *c, f32 lens_height, f32 lens_width, Mat4 *out_view, Mat4 *out_proj) { + Mat4 proj = mat4_perspective(c->fov, lens_width / lens_height, 0.1, 100.0); + Vec3 camera_direction = vec3_add(c->position, c->front); + Mat4 view = mat4_look_at(c->position, camera_direction, c->up); + if (out_view) { + *out_view = view; + } + if (out_proj) { + *out_proj = proj; + } + return mat4_mult(view, proj); +} diff --git a/src/core/camera.h b/src/core/camera.h new file mode 100644 index 0000000..bacbca9 --- /dev/null +++ b/src/core/camera.h @@ -0,0 +1,37 @@ +/** + * @file camera.h + * @brief + */ +#pragma once + +#include "defines.h" +#include "maths_types.h" + +typedef struct Camera { + Vec3 position; + Vec3 front; + Vec3 up; + f32 fov; +} Camera; + +/** @brief create a camera */ +Camera Camera_Create(Vec3 pos, Vec3 front, Vec3 up, f32 fov); + +/** + * @brief Get 3D camera transform matrix + * @param out_view optionally stores just the view matrix + * @param out_proj optionally stores just the projection matrix + * @returns the camera's view projection matrix pre-multiplied +*/ +PUB Mat4 Camera_ViewProj(Camera* c, f32 lens_height, f32 lens_width, Mat4* out_view, Mat4* out_proj); + +/** @brief Get 2D camera transform matrix */ +PUB Mat4 Camera_View2D(Camera* c); // TODO: 2D cameras + + +// TODO: Basic reusable camera controls +/* +Right click + move = pan +Left click = orbit camera +WASD = forward/backward/left/right +*/ diff --git a/src/core/core.c b/src/core/core.c new file mode 100644 index 0000000..602d35c --- /dev/null +++ b/src/core/core.c @@ -0,0 +1,75 @@ +#include "core.h" + +#include <stdlib.h> + +#include "glfw3.h" +#include "input.h" +#include "keys.h" +#include "log.h" +#include "mem.h" +#include "render.h" +#include "render_types.h" +#include "scene.h" + +// These are only the initial window dimensions +#define SCR_WIDTH 1000 +#define SCR_HEIGHT 1000 + +Core g_core; /** @brief global `Core` that other files can use */ + +struct Core { + const char* app_name; + GLFWwindow* window; + Renderer* renderer; + Input_State input; +}; + +/** @brief Gets the global `Core` singleton */ +inline Core* GetCore() { return &g_core; } + +void Core_Bringup() { + INFO("Initiate Core bringup"); + RendererConfig conf = { .window_name = { "Celeritas Engine Core" }, + .scr_width = SCR_WIDTH, + .scr_height = SCR_HEIGHT, + .clear_colour = (Vec3){ .08, .08, .1 } }; + + // initialise all subsystems + if (!Renderer_Init(conf, g_core.renderer)) { + // FATAL("Failed to start renderer"); + ERROR_EXIT("Failed to start renderer\n"); + } + if (!Input_Init(&g_core.input, g_core.window)) { + // the input system needs the glfw window which is created by the renderer + // hence the order here is important + ERROR_EXIT("Failed to start input system\n"); + } + + size_t model_data_max = 1024 * 1024 * 1024; + arena model_arena = arena_create(malloc(model_data_max), model_data_max); + + // model_pool model_pool = model_pool_create(&model_arena, 256, sizeof(model)); + // g_core.models = model_pool; + // INFO("Created model pool allocator"); + + // INFO("Creating default scene"); + // scene_init(&g_core.default_scene); +} + +#include <glfw3.h> + +void Core_Shutdown() { + Input_Shutdown(&g_core.input); + Renderer_Shutdown(g_core.renderer); +} + +bool ShouldExit() { + return key_just_released(KEYCODE_ESCAPE) || glfwWindowShouldClose(g_core.window); +} + +void Frame_Begin() { + glfwPollEvents(); + Render_FrameBegin(g_core.renderer); +} +void Frame_Draw() {} +void Frame_End() { Render_FrameEnd(g_core.renderer); } diff --git a/src/core/core.h b/src/core/core.h new file mode 100644 index 0000000..7916143 --- /dev/null +++ b/src/core/core.h @@ -0,0 +1,21 @@ +#pragma once + +#include "input.h" +#include "render_types.h" +#include "scene.h" +#include "screenspace.h" +#include "terrain.h" +#include "text.h" + +typedef struct Core Core; + +Core* get_global_core(); + +/** @brief Throws error if the core cannot be instantiated */ +void Core_Bringup(); +void Core_Shutdown(); +bool ShouldExit(); + +void Frame_Begin(); +void Frame_Draw(); +void Frame_End(); diff --git a/src/defines.h b/src/defines.h index a35dbf4..1f0eae7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -38,7 +38,7 @@ _Static_assert(sizeof(i64) == 8, "type i64 should be 8 byte"); _Static_assert(sizeof(f32) == 4, "type f32 should be 4 bytes"); _Static_assert(sizeof(f64) == 8, "type f64 should be 8 bytes"); -_Static_assert(sizeof(ptrdiff_t) == 8, ""); +_Static_assert(sizeof(ptrdiff_t) == 8, "type ptrdiff_t should be 8 bytes"); #define alignof(x) _Alignof(x) @@ -49,20 +49,9 @@ _Static_assert(sizeof(ptrdiff_t) == 8, ""); u32 raw; \ } -/* -Possible platform defines: -#define CEL_PLATFORM_LINUX 1 -#define CEL_PLATFORM_WINDOWS 1 -#define CEL_PLATFORM_MAC 1 -#define CEL_PLATFORM_HEADLESS 1 -*/ +CORE_DEFINE_HANDLE(Handle); // Untyped handle that can be casted to a strongly typed resource handle -/* -Renderer backend defines: -#define CEL_REND_BACKEND_OPENGL 1 -#define CEL_REND_BACKEND_VULKAN 1 -#define CEL_REND_BACKEND_METAL 1 -*/ +#define PUB // For collecting public APIs to expose in an amalgamation header file // NOTE: The below is now handled in xmake.lua // Platform will inform renderer backend (unless user overrides) @@ -72,11 +61,12 @@ Renderer backend defines: #endif #if defined(CEL_PLATFORM_WINDOWS) +#define CEL_REND_BACKEND_OPENGL 1 // #define CEL_REND_BACKEND_DX11 1 -#define CEL_REND_BACKEND_VULKAN 1 +// #define CEL_REND_BACKEND_VULKAN 1 #endif #if defined(CEL_PLATFORM_MAC) // #define CEL_REND_BACKEND_METAL 1 #define CEL_REND_BACKEND_OPENGL 1 -#endif
\ No newline at end of file +#endif diff --git a/src/maths/geometry.h b/src/maths/geometry.h index 937c38a..0df80fc 100644 --- a/src/maths/geometry.h +++ b/src/maths/geometry.h @@ -11,31 +11,31 @@ #include "maths.h" -typedef struct line_3d { - vec3 start, end; -} line_3d; +// typedef struct line_3d { +// vec3 start, end; +// } line_3d; -typedef struct plane { - vec3 normal; -} plane; +// typedef struct plane { +// vec3 normal; +// } plane; -typedef struct cuboid { - vec3 half_extents; -} cuboid; +// typedef struct cuboid { +// vec3 half_extents; +// } cuboid; -typedef struct sphere { - f32 radius; -} sphere; +// typedef struct sphere { +// f32 radius; +// } sphere; -typedef struct cylinder { - f32 radius; - f32 half_height; -} cylinder; +// typedef struct cylinder { +// f32 radius; +// f32 half_height; +// } cylinder; -typedef struct cone { - f32 radius; - f32 half_height; -} cone; +// typedef struct cone { +// f32 radius; +// f32 half_height; +// } cone; // TODO: // capsule @@ -47,4 +47,4 @@ typedef struct cone { // 2d... // line -// circle
\ No newline at end of file +// circle diff --git a/src/maths/maths.h b/src/maths/maths.h index 7c0e06e..76790ea 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -21,65 +21,65 @@ // --- Vector Implementations // Dimension 3 -static inline vec3 vec3_create(f32 x, f32 y, f32 z) { return (vec3){ x, y, z }; } -#define vec3(x, y, z) ((vec3){ 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 }; } -static inline vec3 vec3_div(vec3 a, f32 s) { return (vec3){ a.x / s, a.y / s, a.z / s }; } - -static inline f32 vec3_len_squared(vec3 a) { return (a.x * a.x) + (a.y * a.y) + (a.z * a.z); } -static inline f32 vec3_len(vec3 a) { return sqrtf(vec3_len_squared(a)); } -static inline vec3 vec3_negate(vec3 a) { return (vec3){ -a.x, -a.y, -a.z }; } -static inline vec3 vec3_normalise(vec3 a) { +static inline Vec3 vec3_create(f32 x, f32 y, f32 z) { return (Vec3){ x, y, z }; } +#define vec3(x, y, z) ((Vec3){ 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 }; } +static inline Vec3 vec3_div(Vec3 a, f32 s) { return (Vec3){ a.x / s, a.y / s, a.z / s }; } + +static inline f32 vec3_len_squared(Vec3 a) { return (a.x * a.x) + (a.y * a.y) + (a.z * a.z); } +static inline f32 vec3_len(Vec3 a) { return sqrtf(vec3_len_squared(a)); } +static inline Vec3 vec3_negate(Vec3 a) { return (Vec3){ -a.x, -a.y, -a.z }; } +static inline Vec3 vec3_normalise(Vec3 a) { f32 length = vec3_len(a); return vec3_div(a, length); } -static inline f32 vec3_dot(vec3 a, vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } -static inline vec3 vec3_cross(vec3 a, vec3 b) { +static inline f32 vec3_dot(Vec3 a, Vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } +static inline Vec3 vec3_cross(Vec3 a, Vec3 b) { return ( - vec3){ .x = a.y * b.z - a.z * b.y, .y = a.z * b.x - a.x * b.z, .z = a.x * b.y - a.y * b.x }; + Vec3){ .x = a.y * b.z - a.z * b.y, .y = a.z * b.x - a.x * b.z, .z = a.x * b.y - a.y * b.x }; } -#define VEC3_ZERO ((vec3){ .x = 0.0, .y = 0.0, .z = 0.0 }) -#define VEC3_X ((vec3){ .x = 1.0, .y = 0.0, .z = 0.0 }) -#define VEC3_NEG_X ((vec3){ .x = -1.0, .y = 0.0, .z = 0.0 }) -#define VEC3_Y ((vec3){ .x = 0.0, .y = 1.0, .z = 0.0 }) -#define VEC3_NEG_Y ((vec3){ .x = 0.0, .y = -1.0, .z = 0.0 }) -#define VEC3_Z ((vec3){ .x = 0.0, .y = 0.0, .z = 1.0 }) -#define VEC3_NEG_Z ((vec3){ .x = 0.0, .y = 0.0, .z = -1.0 }) +#define VEC3_ZERO ((Vec3){ .x = 0.0, .y = 0.0, .z = 0.0 }) +#define VEC3_X ((Vec3){ .x = 1.0, .y = 0.0, .z = 0.0 }) +#define VEC3_NEG_X ((Vec3){ .x = -1.0, .y = 0.0, .z = 0.0 }) +#define VEC3_Y ((Vec3){ .x = 0.0, .y = 1.0, .z = 0.0 }) +#define VEC3_NEG_Y ((Vec3){ .x = 0.0, .y = -1.0, .z = 0.0 }) +#define VEC3_Z ((Vec3){ .x = 0.0, .y = 0.0, .z = 1.0 }) +#define VEC3_NEG_Z ((Vec3){ .x = 0.0, .y = 0.0, .z = -1.0 }) -static inline void print_vec3(vec3 v) { printf("{ x: %f, y: %f, z: %f )\n", v.x, v.y, v.z); } +static inline void print_vec3(Vec3 v) { printf("{ x: %f, y: %f, z: %f )\n", (f64)v.x, (f64)v.y, (f64)v.z); } // TODO: Dimension 2 -static inline vec2 vec2_create(f32 x, f32 y) { return (vec2){ x, y }; } -#define vec2(x, y) ((vec2){ x, y }) -static inline vec2 vec2_div(vec2 a, f32 s) { return (vec2){ a.x / s, a.y / s }; } +static inline Vec2 vec2_create(f32 x, f32 y) { return (Vec2){ x, y }; } +#define vec2(x, y) ((Vec2){ x, y }) +static inline Vec2 vec2_div(Vec2 a, f32 s) { return (Vec2){ a.x / s, a.y / s }; } // TODO: Dimension 4 -static inline vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z, w }; } +static inline Vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (Vec4){ x, y, z, w }; } #define vec4(x, y, z, w) (vec4_create(x, y, z, w)) -#define VEC4_ZERO ((vec4){ .x = 0.0, .y = 0.0, .z = 0.0, .w = 0.0 }) +#define VEC4_ZERO ((Vec4){ .x = 0.0, .y = 0.0, .z = 0.0, .w = 0.0 }) // --- 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) { +static inline Quat quat_normalise(Quat a) { 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 }; } -static quat quat_from_axis_angle(vec3 axis, f32 angle, bool normalize) { +static Quat quat_from_axis_angle(Vec3 axis, f32 angle, bool normalize) { const f32 half_angle = 0.5f * angle; f32 s = sinf(half_angle); f32 c = cosf(half_angle); - quat q = (quat){ s * axis.x, s * axis.y, s * axis.z, c }; + Quat q = (Quat){ s * axis.x, s * axis.y, s * axis.z, c }; if (normalize) { return quat_normalise(q); } @@ -87,11 +87,11 @@ static quat quat_from_axis_angle(vec3 axis, f32 angle, bool normalize) { } // TODO: grok this. -static inline quat quat_slerp(quat a, quat b, f32 percentage) { - quat out_quaternion; +static inline Quat quat_slerp(Quat a, Quat b, f32 percentage) { + Quat out_quaternion; - quat q0 = quat_normalise(a); - quat q1 = quat_normalise(b); + Quat q0 = quat_normalise(a); + Quat q1 = quat_normalise(b); // Compute the cosine of the angle between the two vectors. f32 dot = quat_dot(q0, q1); @@ -113,41 +113,43 @@ static inline quat quat_slerp(quat a, quat b, f32 percentage) { // If the inputs are too close for comfort, linearly interpolate // and normalize the result. out_quaternion = - (quat){ q0.x + ((q1.x - q0.x) * percentage), q0.y + ((q1.y - q0.y) * percentage), + (Quat){ q0.x + ((q1.x - q0.x) * percentage), q0.y + ((q1.y - q0.y) * percentage), q0.z + ((q1.z - q0.z) * percentage), q0.w + ((q1.w - q0.w) * percentage) }; return quat_normalise(out_quaternion); } + // TODO: Are there math functions that take floats instead of doubles? + // Since dot is in range [0, DOT_THRESHOLD], acos is safe - f32 theta_0 = cos(dot); // theta_0 = angle between input vectors - f32 theta = theta_0 * percentage; // theta = angle between v0 and result - f32 sin_theta = sin(theta); // compute this value only once - f32 sin_theta_0 = sin(theta_0); // compute this value only once + f64 theta_0 = cos((f64)dot); // theta_0 = angle between input vectors + f64 theta = theta_0 * (f64)percentage; // theta = angle between v0 and result + f64 sin_theta = sin((f64)theta); // compute this value only once + f64 sin_theta_0 = sin((f64)theta_0); // compute this value only once - f32 s0 = cos(theta) - dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0) + f32 s0 = cos(theta) - (f64)dot * sin_theta / sin_theta_0; // == sin(theta_0 - theta) / sin(theta_0) f32 s1 = sin_theta / sin_theta_0; - return (quat){ (q0.x * s0) + (q1.x * s1), (q0.y * s0) + (q1.y * s1), (q0.z * s0) + (q1.z * s1), + return (Quat){ (q0.x * s0) + (q1.x * s1), (q0.y * s0) + (q1.y * s1), (q0.z * s0) + (q1.z * s1), (q0.w * s0) + (q1.w * s1) }; } // --- Matrix Implementations -static inline mat4 mat4_ident() { - return (mat4){ .data = { 1.0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.0 } }; +static inline Mat4 mat4_ident() { + return (Mat4){ .data = { 1.0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.0 } }; } -static inline mat4 mat4_translation(vec3 position) { - mat4 out_matrix = mat4_ident(); +static inline Mat4 mat4_translation(Vec3 position) { + Mat4 out_matrix = mat4_ident(); out_matrix.data[12] = position.x; out_matrix.data[13] = position.y; out_matrix.data[14] = position.z; return out_matrix; } -static inline mat4 mat4_scale(f32 scale) { - mat4 out_matrix = mat4_ident(); +static inline Mat4 mat4_scale(f32 scale) { + Mat4 out_matrix = mat4_ident(); out_matrix.data[0] = scale; out_matrix.data[5] = scale; out_matrix.data[10] = scale; @@ -155,9 +157,9 @@ static inline mat4 mat4_scale(f32 scale) { } // TODO: double check this -static inline mat4 mat4_rotation(quat rotation) { - mat4 out_matrix = mat4_ident(); - quat n = quat_normalise(rotation); +static inline Mat4 mat4_rotation(Quat rotation) { + Mat4 out_matrix = mat4_ident(); + Quat n = quat_normalise(rotation); out_matrix.data[0] = 1.0f - 2.0f * n.y * n.y - 2.0f * n.z * n.z; out_matrix.data[1] = 2.0f * n.x * n.y - 2.0f * n.z * n.w; @@ -174,8 +176,8 @@ static inline mat4 mat4_rotation(quat rotation) { return out_matrix; } -static inline mat4 mat4_mult(mat4 lhs, mat4 rhs) { - mat4 out_matrix = mat4_ident(); +static inline Mat4 mat4_mult(Mat4 lhs, Mat4 rhs) { + Mat4 out_matrix = mat4_ident(); const f32 *m1_ptr = lhs.data; const f32 *m2_ptr = rhs.data; @@ -193,8 +195,8 @@ static inline mat4 mat4_mult(mat4 lhs, mat4 rhs) { return out_matrix; } -static mat4 mat4_transposed(mat4 matrix) { - mat4 out_matrix = mat4_ident(); +static Mat4 mat4_transposed(Mat4 matrix) { + Mat4 out_matrix = mat4_ident(); out_matrix.data[0] = matrix.data[0]; out_matrix.data[1] = matrix.data[4]; out_matrix.data[2] = matrix.data[8]; @@ -216,10 +218,10 @@ static mat4 mat4_transposed(mat4 matrix) { #if defined(CEL_REND_BACKEND_VULKAN) /** @brief Creates a perspective projection matrix compatible with Vulkan */ -static inline mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, +static inline Mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, f32 far_clip) { f32 half_tan_fov = tanf(fov_radians * 0.5f); - mat4 out_matrix = { .data = { 0 } }; + Mat4 out_matrix = { .data = { 0 } }; out_matrix.data[0] = 1.0f / (aspect_ratio * half_tan_fov); out_matrix.data[5] = -1.0f / half_tan_fov; // Flip Y-axis for Vulkan @@ -231,10 +233,10 @@ static inline mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_ } #else /** @brief Creates a perspective projection matrix */ -static inline mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, +static inline Mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, f32 far_clip) { f32 half_tan_fov = tanf(fov_radians * 0.5f); - mat4 out_matrix = { .data = { 0 } }; + Mat4 out_matrix = { .data = { 0 } }; out_matrix.data[0] = 1.0f / (aspect_ratio * half_tan_fov); out_matrix.data[5] = 1.0f / half_tan_fov; out_matrix.data[10] = -((far_clip + near_clip) / (far_clip - near_clip)); @@ -245,10 +247,10 @@ static inline mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_ #endif /** @brief Creates an orthographic projection matrix */ -static inline mat4 mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 near_clip, +static inline Mat4 mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 near_clip, f32 far_clip) { // source: kohi game engine. - mat4 out_matrix = mat4_ident(); + Mat4 out_matrix = mat4_ident(); f32 lr = 1.0f / (left - right); f32 bt = 1.0f / (bottom - top); @@ -265,16 +267,16 @@ static inline mat4 mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f return out_matrix; } -static inline mat4 mat4_look_at(vec3 position, vec3 target, vec3 up) { - mat4 out_matrix; - vec3 z_axis; +static inline Mat4 mat4_look_at(Vec3 position, Vec3 target, Vec3 up) { + Mat4 out_matrix; + Vec3 z_axis; z_axis.x = target.x - position.x; z_axis.y = target.y - position.y; z_axis.z = target.z - position.z; z_axis = vec3_normalise(z_axis); - vec3 x_axis = vec3_normalise(vec3_cross(z_axis, up)); - vec3 y_axis = vec3_cross(x_axis, z_axis); + Vec3 x_axis = vec3_normalise(vec3_cross(z_axis, up)); + Vec3 y_axis = vec3_cross(x_axis, z_axis); out_matrix.data[0] = x_axis.x; out_matrix.data[1] = y_axis.x; @@ -301,26 +303,26 @@ static inline mat4 mat4_look_at(vec3 position, vec3 target, vec3 up) { // --- Transform Implementations #define TRANSFORM_DEFAULT \ - ((transform){ .position = VEC3_ZERO, \ - .rotation = (quat){ .x = 0., .y = 0., .z = 0., .w = 1. }, \ + ((Transform){ .position = VEC3_ZERO, \ + .rotation = (Quat){ .x = 0., .y = 0., .z = 0., .w = 1. }, \ .scale = 1.0, \ .is_dirty = false }) -static transform transform_create(vec3 pos, quat rot, f32 scale) { - return (transform){ .position = pos, .rotation = rot, .scale = scale, .is_dirty = true }; +static Transform transform_create(Vec3 pos, Quat rot, f32 scale) { + return (Transform){ .position = pos, .rotation = rot, .scale = scale, .is_dirty = true }; } -static inline mat4 transform_to_mat(transform *tf) { - mat4 scale = mat4_scale(tf->scale); - mat4 rotation = mat4_rotation(tf->rotation); - mat4 translation = mat4_translation(tf->position); +static inline Mat4 transform_to_mat(Transform *tf) { + Mat4 scale = mat4_scale(tf->scale); + Mat4 rotation = mat4_rotation(tf->rotation); + Mat4 translation = mat4_translation(tf->position); return mat4_mult(translation, mat4_mult(rotation, scale)); // return mat4_mult(mat4_mult(scale, rotation), translation); } // --- Sizing asserts -_Static_assert(alignof(vec3) == 4, "vec3 is 4 byte aligned"); -_Static_assert(sizeof(vec3) == 12, "vec3 is 12 bytes so has no padding"); +_Static_assert(alignof(Vec3) == 4, "Vec3 is 4 byte aligned"); +_Static_assert(sizeof(Vec3) == 12, "Vec3 is 12 bytes so has no padding"); -_Static_assert(alignof(vec4) == 4, "vec4 is 4 byte aligned"); +_Static_assert(alignof(Vec4) == 4, "Vec4 is 4 byte aligned"); diff --git a/src/maths/maths_types.h b/src/maths/maths_types.h index 609672c..f256a9b 100644 --- a/src/maths/maths_types.h +++ b/src/maths/maths_types.h @@ -22,54 +22,53 @@ // --- Types /** @brief 2D Vector */ -typedef struct vec2 { +typedef struct Vec2 { f32 x, y; -} vec2; +} Vec2; /** @brief 3D Vector */ -typedef struct vec3 { +typedef struct Vec3 { f32 x, y, z; -} vec3; +} Vec3; /** @brief 4D Vector */ -typedef struct vec4 { +typedef struct Vec4 { f32 x, y, z, w; -} vec4; +} Vec4; /** @brief Quaternion */ -typedef vec4 quat; +typedef Vec4 Quat; /** @brief 4x4 Matrix */ -typedef struct mat4 { +typedef struct Mat4 { // TODO: use this format for more readable code: vec4 x_axis, y_axis, z_axis, w_axis; f32 data[16]; -} mat4; +} Mat4; /** @brief Three dimensional bounding box */ -typedef struct bbox_3d { - vec3 min; // minimum point of the box - vec3 max; // maximum point of the box -} bbox_3d; +typedef struct Bbox_3D { + Vec3 min; // minimum point of the box + Vec3 max; // maximum point of the box +} Bbox_3d; /** @brief 3D Axis-aligned bounding box */ -typedef bbox_3d aabb_3d; +typedef Bbox_3d Aabb_3D; /** @brief 3D affine transformation */ -typedef struct transform { - vec3 position; - quat rotation; +typedef struct Transform { + Vec3 position; + Quat rotation; f32 scale; bool is_dirty; -} transform; -typedef transform transform3d; +} Transform; -typedef struct vec4i { +typedef struct Vec4i { i32 x, y, z, w; -} vec4i; +} Vec4i; -typedef struct vec4u { +typedef struct Vec4u { u32 x, y, z, w; -} vec4u; +} Vec4u; // --- Some other types typedef struct u32x3 { @@ -96,8 +95,8 @@ typedef struct u32x2 { // Type aliass -typedef struct vec2 f32x2; +typedef struct Vec2 f32x2; #define f32x2(x, y) ((f32x2){ x, y }) -typedef struct vec3 f32x3; +typedef struct Vec3 f32x3; #define f32x3(x, y, z) ((f32x3){ x, y, z }) diff --git a/src/maths/primitives.c b/src/maths/primitives.c index 753dd83..def2712 100644 --- a/src/maths/primitives.c +++ b/src/maths/primitives.c @@ -8,7 +8,7 @@ // --- Helpers #define VERT_3D(arr, pos, norm, uv) \ { \ - vertex v = { .static_3d = { .position = pos, .normal = norm, .tex_coords = uv } }; \ + Vertex v = { .static_3d = { .position = pos, .normal = norm, .tex_coords = uv } }; \ vertex_darray_push(arr, v); \ } @@ -19,23 +19,23 @@ void push_triangle(u32_darray* arr, u32 i0, u32 i1, u32 i2) { } // TODO: move to another file -void geo_free_data(geometry_data* geo) { +void geo_free_data(Geometry* geo) { vertex_darray_free(geo->vertices); geo->vertices = NULL; } -vec3 plane_vertex_positions[] = { - (vec3){ -0.5, 0, -0.5 }, - (vec3){ 0.5, 0, -0.5 }, - (vec3){ -0.5, 0, 0.5 }, - (vec3){ 0.5, 0, 0.5 }, +Vec3 plane_vertex_positions[] = { + (Vec3){ -0.5, 0, -0.5 }, + (Vec3){ 0.5, 0, -0.5 }, + (Vec3){ -0.5, 0, 0.5 }, + (Vec3){ 0.5, 0, 0.5 }, }; -geometry_data geo_create_plane(f32x2 extents) { - vertex_darray* vertices = vertex_darray_new(4); +Geometry geo_create_plane(f32x2 extents) { + Vertex_darray* vertices = vertex_darray_new(4); u32_darray* indices = u32_darray_new(vertices->len); - vec3 vert_pos[4]; + Vec3 vert_pos[4]; memcpy(&vert_pos, plane_vertex_positions, sizeof(plane_vertex_positions)); for (int i = 0; i < 4; i++) { vert_pos[i].x *= extents.x; @@ -51,26 +51,25 @@ geometry_data geo_create_plane(f32x2 extents) { push_triangle(indices, 2, 1, 0); push_triangle(indices, 3, 1, 2); - geometry_data geo = { .format = VERTEX_STATIC_3D, - .vertices = vertices, - .has_indices = true, - .indices = indices, - .colour = (rgba){ 0, 0, 0, 1 } }; + Geometry geo = { + .format = VERTEX_STATIC_3D, .vertices = vertices, .has_indices = true, .indices = indices + }; + // .colour = (rgba){ 0, 0, 0, 1 } }; return geo; } -static const vec3 BACK_BOT_LEFT = (vec3){ 0, 0, 0 }; -static const vec3 BACK_BOT_RIGHT = (vec3){ 1, 0, 0 }; -static const vec3 BACK_TOP_LEFT = (vec3){ 0, 1, 0 }; -static const vec3 BACK_TOP_RIGHT = (vec3){ 1, 1, 0 }; -static const vec3 FRONT_BOT_LEFT = (vec3){ 0, 0, 1 }; -static const vec3 FRONT_BOT_RIGHT = (vec3){ 1, 0, 1 }; -static const vec3 FRONT_TOP_LEFT = (vec3){ 0, 1, 1 }; -static const vec3 FRONT_TOP_RIGHT = (vec3){ 1, 1, 1 }; +static const Vec3 BACK_BOT_LEFT = (Vec3){ 0, 0, 0 }; +static const Vec3 BACK_BOT_RIGHT = (Vec3){ 1, 0, 0 }; +static const Vec3 BACK_TOP_LEFT = (Vec3){ 0, 1, 0 }; +static const Vec3 BACK_TOP_RIGHT = (Vec3){ 1, 1, 0 }; +static const Vec3 FRONT_BOT_LEFT = (Vec3){ 0, 0, 1 }; +static const Vec3 FRONT_BOT_RIGHT = (Vec3){ 1, 0, 1 }; +static const Vec3 FRONT_TOP_LEFT = (Vec3){ 0, 1, 1 }; +static const Vec3 FRONT_TOP_RIGHT = (Vec3){ 1, 1, 1 }; -geometry_data geo_create_cuboid(f32x3 extents) { - vertex_darray* vertices = vertex_darray_new(36); +Geometry geo_create_cuboid(f32x3 extents) { + Vertex_darray* vertices = vertex_darray_new(36); // back faces VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_NEG_Z, vec2(1, 0)); @@ -126,12 +125,11 @@ geometry_data geo_create_cuboid(f32x3 extents) { u32_darray_push(indices, i); } - geometry_data geo = { + Geometry geo = { .format = VERTEX_STATIC_3D, .vertices = vertices, .has_indices = true, .indices = indices, // FIXME: make darray methods that return stack allocated struct - .colour = (rgba){ 0, 0, 0, 1 } }; return geo; @@ -139,28 +137,28 @@ geometry_data geo_create_cuboid(f32x3 extents) { // --- Spheres -vec3 spherical_to_cartesian_coords(f32 rho, f32 theta, f32 phi) { +Vec3 spherical_to_cartesian_coords(f32 rho, f32 theta, f32 phi) { f32 x = rho * sin(phi) * cos(theta); f32 y = rho * cos(phi); f32 z = rho * sin(phi) * sin(theta); return vec3(x, y, z); } -geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_west_lines) { +Geometry geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_west_lines) { assert(east_west_lines >= 3); // sphere will be degenerate and look gacked without at least 3 assert(north_south_lines >= 3); - vertex_darray* vertices = vertex_darray_new(2 + (east_west_lines - 1) * north_south_lines); + Vertex_darray* vertices = vertex_darray_new(2 + (east_west_lines - 1) * north_south_lines); // Create a UV sphere with spherical coordinates // a point P on the unit sphere can be represented P(r, theta, phi) // for each vertex we must convert that to a cartesian R3 coordinate // Top point - vertex top = { .static_3d = { .position = vec3(0, radius, 0), + Vertex top = { .static_3d = { .position = vec3(0, radius, 0), .normal = vec3_normalise(vec3(0, radius, 0)), .tex_coords = vec2(0, 0) } }; - vertex_darray_push(vertices, top); + Vertex_darray_push(vertices, top); // parallels for (u32 i = 0; i < (east_west_lines - 1); i++) { @@ -171,12 +169,12 @@ geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_we for (u32 j = 0; j < east_west_lines; j++) { // theta should range from 0 to 2PI f32 theta = TAU * ((f32)j / (f32)north_south_lines); - vec3 position = spherical_to_cartesian_coords(radius, theta, phi); + Vec3 position = spherical_to_cartesian_coords(radius, theta, phi); // f32 d = vec3_len(position); // print_vec3(position); // printf("Phi %f Theta %f d %d\n", phi, theta, d); // assert(d == radius); // all points on the sphere should be 'radius' away from the origin - vertex v = { .static_3d = { + Vertex v = { .static_3d = { .position = position, .normal = vec3_normalise(position), // normal vector on sphere is same as position @@ -187,7 +185,7 @@ geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_we } // Bottom point - vertex bot = { .static_3d = { .position = vec3(0, -radius, 0), + Vertex bot = { .static_3d = { .position = vec3(0, -radius, 0), .normal = vec3_normalise(vec3(0, -radius, 0)), .tex_coords = vec2(0, 0) } }; vertex_darray_push(vertices, bot); @@ -234,12 +232,11 @@ geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_we } } - geometry_data geo = { + Geometry geo = { .format = VERTEX_STATIC_3D, .vertices = vertices, .has_indices = true, .indices = indices, - .colour = RED_800, }; return geo; } diff --git a/src/maths/primitives.h b/src/maths/primitives.h index be2c6ff..38ae1de 100644 --- a/src/maths/primitives.h +++ b/src/maths/primitives.h @@ -6,8 +6,8 @@ #include "maths_types.h" #include "render_types.h" -geometry_data geo_create_plane(f32x2 extents); -geometry_data geo_create_cuboid(f32x3 extents); -geometry_data geo_create_cylinder(f32 radius, f32 height, u32 resolution); -geometry_data geo_create_uvsphere(f32 radius, u32 north_south_lines, u32 east_west_lines); -geometry_data geo_create_icosphere(f32 radius, f32 n_subdivisions);
\ No newline at end of file +Geometry Geo_CreatePlane(f32x2 extents); +Geometry Geo_CreateCuboid(f32x3 extents); +Geometry Geo_CreateCylinder(f32 radius, f32 height, u32 resolution); +Geometry Geo_CreateUVsphere(f32 radius, u32 north_south_lines, u32 east_west_lines); +Geometry Geo_CreateIcosphere(f32 radius, f32 n_subdivisions); diff --git a/src/new_render/draw.h b/src/new_render/draw.h new file mode 100644 index 0000000..58e104e --- /dev/null +++ b/src/new_render/draw.h @@ -0,0 +1,13 @@ +/** + * @file draw.h + * @brief + */ +#pragma once +#include "defines.h" +#include "maths_types.h" +#include "render_types.h" + +// --- Public APIs + +PUB void EncodeDrawModel(Handle model, Mat4 transform); +PUB void EncodeDrawMesh(Mesh* mesh, Material* material, Mat4 affine); diff --git a/src/new_render/immdraw.h b/src/new_render/immdraw.h new file mode 100644 index 0000000..c2c3a24 --- /dev/null +++ b/src/new_render/immdraw.h @@ -0,0 +1,14 @@ +/** + * @brief Immediate-mode drawing APIs + */ + +#pragma once +#include "defines.h" +#include "maths_types.h" + +// --- Public API + + +void Immdraw_Cuboid(Transform tf); +void Immdraw_Sphere(Transform tf, f32 size); +void Immdraw_TransformGizmo(Transform tf, f32 size); diff --git a/src/new_render/pbr.h b/src/new_render/pbr.h new file mode 100644 index 0000000..7573563 --- /dev/null +++ b/src/new_render/pbr.h @@ -0,0 +1,62 @@ +/** + * @file pbr.h + * @brief PBR render pass + */ + +#pragma once +#include "defines.h" +#include "camera.h" +#include "maths_types.h" +#include "ral/ral.h" +#include "ral/ral_common.h" + +// PBR; + +// --- Public API +typedef struct PBR_Storage PBR_Storage; // Stores all necessary data and handles + +PUB void PBR_Init(PBR_Storage* storage); + +// NOTE: For simplicity's sake we will render this pass directly to the default framebuffer +PUB void PBR_Run( + PBR_Storage* storage + // light data + // camera + // geometry + // materials +); + +typedef struct PBR_Params { + Vec3 albedo; + f32 metallic; + f32 roughness; + f32 ao; +} PBR_Params; + +typedef struct PBR_Textures { + TextureHandle albedo_map; + TextureHandle normal_map; + bool metal_roughness_combined; + TextureHandle metallic_map; + TextureHandle roughness_map; + TextureHandle ao_map; +} PBR_Textures; + +// --- Internal + +typedef struct MaterialMap MaterialMap; +typedef struct RenderEnt RenderEnt; + +GPU_Renderpass* PBR_RPassCreate(); +GPU_Pipeline* PBR_PipelineCreate(GPU_Renderpass* rpass); +void PBR_Execute( + PBR_Storage* storage, + Camera camera, + TextureHandle shadowmap_tex, + MaterialMap* materials, // map of String -> Material + RenderEnt* entities, + size_t entity_count + +); + +// Internally this will need to update material parameters diff --git a/src/new_render/render.c b/src/new_render/render.c new file mode 100644 index 0000000..f5547d5 --- /dev/null +++ b/src/new_render/render.c @@ -0,0 +1,34 @@ +/** + * @brief + */ + +#include "render.h" +#include "maths_types.h" +#include "pbr.h" +#include "ral_common.h" +#include "render_scene.h" +#include "shadows.h" + +struct Renderer { + struct GLFWwindow* window; + RendererConfig config; + GPU_Device device; + GPU_Swapchain swapchain; + GPU_Renderpass* default_renderpass; + bool frame_aborted; + RenderScene scene; + PBR_Storage* pbr; + Shadow_Storage* shadows; + // Terrain_Storage terrain; + // Text_Storage text; + struct ResourcePools* resource_pools; +}; + +bool Renderer_Init(RendererConfig config, Renderer* renderer) { + // set the RAL backend up + + // create our renderpasses + Shadow_Init(renderer->shadows); + + return true; +} diff --git a/src/new_render/render.h b/src/new_render/render.h new file mode 100644 index 0000000..b0b5495 --- /dev/null +++ b/src/new_render/render.h @@ -0,0 +1,54 @@ +/** + * @brief + */ + +#pragma once +#include "defines.h" +#include "maths_types.h" +#include "ral_types.h" +#include "render_types.h" + +typedef struct Renderer Renderer; +typedef struct RendererConfig { + char window_name[256]; + u32 scr_width, scr_height; + Vec3 clear_colour; +} RendererConfig; + +typedef struct RenderCtx { + Mat4 view; + Mat4 projection; +} RenderCtx; + +// --- Lifecycle + +PUB bool Renderer_Init(RendererConfig config, Renderer* renderer); +PUB void Renderer_Shutdown(Renderer* renderer); + +// NOTE: All of these functions grab the Renderer instance off the global Core +PUB void Render_FrameBegin(Renderer* renderer); +PUB void Render_FrameEnd(Renderer* renderer); + +/** @brief */ +PUB void Render_RenderEntities(RenderEnt* entities, size_t entity_count); + +// TODO: Render_FrameDraw(); - this will + +// --- Resources + +PUB TextureHandle TextureUpload(); +PUB ModelHandle ModelLoad(const char* name, const char* filepath); + +// --- Rendering Data + +PUB Mesh Mesh_Create(Geometry* geometry, bool free_on_upload); +PUB void Mesh_Delete(Mesh* mesh); + +// --- Drawing + +// NOTE: These functions use the globally bound camera in RenderScene +PUB void DrawMesh(Mesh* mesh, Material* material, Mat4 model); + +/** @brief the renderer does some internal bookkeeping for terrain so we use the terrain + stored on the Renderer rather than accept it as a parameter */ +PUB void Render_DrawTerrain(); diff --git a/src/new_render/render_scene.h b/src/new_render/render_scene.h new file mode 100644 index 0000000..7591d8f --- /dev/null +++ b/src/new_render/render_scene.h @@ -0,0 +1,20 @@ +/** + * @file render_scene.h + * @brief + */ +#pragma once +#include "defines.h" +#include "render_types.h" +#include "camera.h" + +/** @brief Holds globally bound data for rendering a scene. Typically held by the renderer. + * Whenever you call draw functions you can think of this as an implicit parameter. */ +typedef struct RenderScene { + Camera camera; + PointLight light; +} RenderScene; + +// --- Public APIs + +PUB void SetCamera(Camera camera); +PUB void SetPointLight(PointLight light); diff --git a/src/new_render/render_types.h b/src/new_render/render_types.h new file mode 100644 index 0000000..b27bf2f --- /dev/null +++ b/src/new_render/render_types.h @@ -0,0 +1,86 @@ +/** + * @file render_types.h + * @brief +*/ + +#pragma once +#include "defines.h" +#include "maths_types.h" +#include "ral.h" +#include "maths.h" +#include "ral_types.h" + +// --- Handles +CORE_DEFINE_HANDLE(ModelHandle); +#define ABSENT_MODEL_HANDLE 999999999 + +typedef struct Geometry { + VertexFormat format; + Vertex_darray* vertices; + bool has_indices; + u32_darray* indices; +} Geometry; + +typedef struct u32_opt { + u32 value; + bool has_value; +} u32_opt; + +typedef struct Mesh { + BufferHandle vextex_buffer; + BufferHandle index_buffer; + Geometry* geometry; // NULL means it has been freed CPU-side + bool is_uploaded; // has the data been uploaded to the GPU +} Mesh; + +typedef struct TextureData { + TextureDesc description; + void* image_data; +} TextureData; + +// --- Supported materials +typedef enum MaterialKind { + MAT_BLINN_PHONG, + MAT_PBR, + MAT_PBR_PARAMS, // uses float values to represent a surface uniformly + MAT_COUNT +} MaterialKind; +static const char* material_kind_names[] = { "Blinn Phong", "PBR (Textures)", "PBR (Params)", + "Count (This should be an error)" }; + +typedef struct Material { + char name[64]; +} Material; + +typedef struct Model { + // meshes + // materials +} Model; + +// TODO: function to create a model from a single mesh (like when using primitives) + +// --- Lights +typedef struct PointLight { + Vec3 position; + f32 constant, linear, quadratic; + Vec3 ambient; + Vec3 diffuse; + Vec3 specular; +} PointLight; + +typedef struct DirectionalLight { + Vec3 direction; + Vec3 ambient; + Vec3 diffuse; + Vec3 specular; +} DirectionalLight; + +// --- + +// A renderable 'thing' +typedef struct RenderEnt { + ModelHandle model; + Mat4 affine; // In the future this should be updated by the transform graph + // Bbox_3D bounding_box; + bool casts_shadows; +} RenderEnt; diff --git a/src/new_render/shadows.h b/src/new_render/shadows.h new file mode 100644 index 0000000..82ded5c --- /dev/null +++ b/src/new_render/shadows.h @@ -0,0 +1,29 @@ +/** + * @brief Functions for adding shadows to scene rendering. +*/ + + +#pragma once +#include "defines.h" +#include "ral.h" +#include "render_types.h" + +typedef struct Shadow_Storage Shadow_Storage; + +typedef struct Camera Camera; +typedef struct Mat4 Mat4; + +// --- Public API +PUB void Shadow_Init(Shadow_Storage* storage); + +/** @brief Run shadow map generation for given entities, and store in a texture. + * @note Uses active directional light for now */ +PUB void Shadow_Run(Shadow_Storage* storage, RenderEnt* entities, size_t entity_count); + +/** @brief Get the shadow texture generated from shadowmap pass */ +PUB Handle Shadow_GetShadowMapTexture(Shadow_Storage* storage); + +// --- Internal +GPU_Renderpass* Shadow_RPassCreate(); // Creates the render pass +GPU_Pipeline* Shadow_PipelineCreate(GPU_Renderpass* rpass); // Creates the pipeline +void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform, RenderEnt* entites, size_t entity_count); diff --git a/src/new_render/skybox.h b/src/new_render/skybox.h new file mode 100644 index 0000000..9bdc2ec --- /dev/null +++ b/src/new_render/skybox.h @@ -0,0 +1,32 @@ +/** + * @brief + */ + +#pragma once +#include "backend_opengl.h" +#include "defines.h" +#include "ral_types.h" + +typedef struct CubeMapData { + void* top_image_data; + void* bottom_image_data; + void* left_image_data; + void* right_image_data; + void* front_image_data; + void* back_image_data; + u32 width, height, num_channels; +} CubeMapData; + +PUB void CubeMapData_Load(const char** face_paths, int n); // should always pass n = 6 for now +PUB void CubeMapData_Free(CubeMapData* cubemap); // Frees all the image data for a cubemap +PUB TextureHandle CubeMapData_Upload(CubeMapData* cubemap); + +typedef struct Skybox { + BufferHandle vertex_buffer; + TextureHandle texture; + GPU_Pipeline* pipeline; // "shader" +} Skybox; + +PUB Skybox Skybox_Create(const char** face_paths, int n); // should always pass n = 6 for now + +PUB void Skybox_Draw(Skybox* skybox); diff --git a/src/platform/file.c b/src/platform/file.c index 6030620..33194d7 100644 --- a/src/platform/file.c +++ b/src/platform/file.c @@ -33,7 +33,7 @@ const char *string_from_file(const char *path) { return string; } -str8_opt str8_from_file(arena *a, str8 path) { +str8_opt str8_from_file(arena *a, Str8 path) { char *p = cstr(a, path); str8_opt result = { .has_value = false }; @@ -51,7 +51,7 @@ str8_opt str8_from_file(arena *a, str8 path) { rewind(f); u8 *raw = arena_alloc(a, fsize + 1); - str8 contents = str8_create(raw, fsize); + Str8 contents = str8_create(raw, fsize); contents.buf[contents.len] = '\0'; fread(raw, fsize, 1, f); @@ -90,4 +90,4 @@ FileData load_spv_file(const char *path) { fclose(f); return (FileData){ data, bytesRead }; -}
\ No newline at end of file +} diff --git a/src/platform/file.h b/src/platform/file.h index a8aa8ea..5e5e1e1 100644 --- a/src/platform/file.h +++ b/src/platform/file.h @@ -10,17 +10,17 @@ #include "str.h" typedef struct str8_opt { - str8 contents; + Str8 contents; bool has_value; } str8_opt; const char* string_from_file(const char* path); -str8_opt str8_from_file(arena* a, str8 path); +str8_opt str8_from_file(arena* a, Str8 path); typedef struct { char* data; size_t size; } FileData; -FileData load_spv_file(const char* path);
\ No newline at end of file +FileData load_spv_file(const char* path); diff --git a/src/platform/path.h b/src/platform/path.h index 73063ea..ce53339 100644 --- a/src/platform/path.h +++ b/src/platform/path.h @@ -9,8 +9,8 @@ #include "str.h" typedef struct path_opt { - str8 path; + Str8 path; bool has_value; } path_opt; -path_opt path_parent(arena* a, const char* path); // TODO: convert to using str8
\ No newline at end of file +path_opt path_parent(arena* a, const char* path); // TODO: convert to using str8 diff --git a/src/ral/README.md b/src/ral/README.md new file mode 100644 index 0000000..f66b95a --- /dev/null +++ b/src/ral/README.md @@ -0,0 +1,5 @@ +# RAL + +**Render Abstraction Layer** is a thin abstraction over graphics APIs. Everything in `render` builds on top of the code in +this folder in order to be API-agnostic. It also makes writing graphics code easier as it smooths over some of the discrepancies +between APIs like texture/buffer creation and updating shader values.
\ No newline at end of file diff --git a/src/ral/backends/metal/backend_metal.h b/src/ral/backends/metal/backend_metal.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ral/backends/metal/backend_metal.h diff --git a/src/ral/backends/opengl/backend_opengl.h b/src/ral/backends/opengl/backend_opengl.h new file mode 100644 index 0000000..22162f3 --- /dev/null +++ b/src/ral/backends/opengl/backend_opengl.h @@ -0,0 +1,76 @@ +#pragma once + +#include "ral_impl.h" +#ifdef CEL_REND_BACKEND_OPENGL + +#include "defines.h" +#include "maths_types.h" +#include "ral.h" +#include "ral_types.h" + +#define MAX_PIPELINE_UNIFORM_BUFFERS 32 + +#define OPENGL_DEFAULT_FRAMEBUFFER 0 + +typedef struct GPU_Swapchain{ + u32x2 dimensions; +}GPU_Swapchain; + +typedef struct GPU_Device { +} GPU_Device; + +typedef struct GPU_PipelineLayout{ + void *pad; +}GPU_PipelineLayout; + +typedef struct GPU_Pipeline { + u32 shader_id; + GPU_Renderpass* renderpass; + VertexDescription vertex_desc; + BufferHandle uniform_bindings[MAX_PIPELINE_UNIFORM_BUFFERS]; + u32 uniform_count; + bool wireframe; +} GPU_Pipeline; + +typedef struct GPU_Renderpass { + u32 fbo; + GPU_RenderpassDesc description; +} GPU_Renderpass; + +typedef struct GPU_CmdEncoder { + GPU_Pipeline *pipeline; +} GPU_CmdEncoder; // Recording + +typedef struct gpu_cmd_buffer { + void *pad; +} gpu_cmd_buffer; // Ready for submission + +typedef struct GPU_Buffer { + union { + u32 vbo; + u32 ibo; + u32 ubo; + } id; + union { + u32 vao; + u32 ubo_binding_point + }; // Optional + char* name; + u64 size; +} GPU_Buffer; + +typedef struct GPU_Texture { + u32 id; + void* pad; +} GPU_Texture; + +typedef struct opengl_support { +} opengl_support; + +u32 shader_create_separate(const char *vert_shader, const char *frag_shader); + +void uniform_vec3f(u32 program_id, const char *uniform_name, Vec3 *value); +void uniform_f32(u32 program_id, const char *uniform_name, f32 value); +void uniform_i32(u32 program_id, const char *uniform_name, i32 value); +void uniform_mat4f(u32 program_id, const char *uniform_name, Mat4 *value); +#endif diff --git a/src/ral/backends/vulkan/backend_vulkan.h b/src/ral/backends/vulkan/backend_vulkan.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/ral/backends/vulkan/backend_vulkan.h diff --git a/src/ral/ral.h b/src/ral/ral.h new file mode 100644 index 0000000..ce3b27d --- /dev/null +++ b/src/ral/ral.h @@ -0,0 +1,5 @@ +#pragma once + +#include "ral_types.h" +#include "ral_common.h" +#include "ral_impl.h"
\ No newline at end of file diff --git a/src/ral/ral_common.c b/src/ral/ral_common.c new file mode 100644 index 0000000..89d475b --- /dev/null +++ b/src/ral/ral_common.c @@ -0,0 +1,19 @@ +#include "ral_common.h" +#include "ral_impl.h" + +void backend_pools_init(arena* a, GPU_BackendPools* backend_pools) { + PipelineLayout_pool pipeline_layout_pool = + PipelineLayout_pool_create(a, MAX_PIPELINES, sizeof(GPU_PipelineLayout)); + backend_pools->pipeline_layouts = pipeline_layout_pool; + Pipeline_pool pipeline_pool = Pipeline_pool_create(a, MAX_PIPELINES, sizeof(GPU_Pipeline)); + backend_pools->pipelines = pipeline_pool; + Renderpass_pool rpass_pool = Renderpass_pool_create(a, MAX_RENDERPASSES, sizeof(GPU_Renderpass)); + backend_pools->renderpasses = rpass_pool; +} + +void resource_pools_init(arena* a, struct ResourcePools* res_pools) { + Buffer_pool buf_pool = Buffer_pool_create(a, MAX_BUFFERS, sizeof(GPU_Buffer)); + res_pools->buffers = buf_pool; + Texture_pool tex_pool = Texture_pool_create(a, MAX_TEXTURES, sizeof(GPU_Texture)); + res_pools->textures = tex_pool; +} diff --git a/src/ral/ral_common.h b/src/ral/ral_common.h new file mode 100644 index 0000000..1088404 --- /dev/null +++ b/src/ral/ral_common.h @@ -0,0 +1,39 @@ +#pragma once +#include "defines.h" +#include "buf.h" +#include "mem.h" +#include "ral_types.h" +#include "ral_impl.h" + + +TYPED_POOL(GPU_Buffer, Buffer); +TYPED_POOL(GPU_Texture, Texture); +TYPED_POOL(GPU_PipelineLayout, PipelineLayout); +TYPED_POOL(GPU_Pipeline, Pipeline); +TYPED_POOL(GPU_Renderpass, Renderpass); + +// --- Handy macros +#define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) +#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) + +// --- Pools +typedef struct GPU_BackendPools{ + Pipeline_pool pipelines; + PipelineLayout_pool pipeline_layouts; + Renderpass_pool renderpasses; +} GPU_BackendPools; +void backend_pools_init(arena* a, GPU_BackendPools* backend_pools); + +struct ResourcePools { + Buffer_pool buffers; + Texture_pool textures; +}; +void resource_pools_init(arena* a, struct ResourcePools* res_pools); + + +// --- Vertex formats +bytebuffer vertices_as_bytebuffer(arena* a, VertexFormat format, Vertex_darray* vertices); + +void vertex_desc_add(VertexDescription* builder, const char* name, VertexAttribType type); +VertexDescription static_3d_vertex_description(); +size_t vertex_attrib_size(VertexAttribType attr); diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h new file mode 100644 index 0000000..4d1c17a --- /dev/null +++ b/src/ral/ral_impl.h @@ -0,0 +1,38 @@ +/** + * @brief +*/ +#pragma once +#include "defines.h" +#include "ral_types.h" + +struct GLFWwindow; + +// Forward declare structs - these must be defined in the backend implementation +typedef struct GPU_Swapchain GPU_Swapchain; +typedef struct GPU_Device GPU_Device; +typedef struct GPU_PipelineLayout GPU_PipelineLayout; +typedef struct GPU_Pipeline GPU_Pipeline; +typedef struct GPU_Renderpass GPU_Renderpass; +typedef struct GPU_CmdEncoder GPU_CmdEncoder; // Recording +typedef struct GPU_CmdBuffer GPU_CmdBuffer; // Ready for submission +typedef struct GPU_Buffer GPU_Buffer; +typedef struct GPU_Texture GPU_Texture; + +bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window); +void GPU_Backend_Shutdown(); + +bool GPU_Device_Create(GPU_Device* out_device); +void GPU_Device_Destroy(GPU_Device* device); + +bool GPU_Swapchain_Create(GPU_Swapchain* out_swapchain); +void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain); + +GPU_Renderpass* GPU_Renderpass_Create(GPU_RenderpassDesc description); +void GPU_Renderpass_Destroy(GPU_Renderpass* pass); + +GPU_Pipeline* GPU_GraphicsPipeline_Create(GraphicsPipelineDesc description, GPU_Renderpass* renderpass); +void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline); + +#if defined(CEL_REND_BACKEND_OPENGL) +#include "backend_opengl.h" +#endif diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h new file mode 100644 index 0000000..0ba7f87 --- /dev/null +++ b/src/ral/ral_types.h @@ -0,0 +1,223 @@ +#pragma once +#include "defines.h" +#include "darray.h" +#include "maths_types.h" + +// --- Max size constants +#define MAX_SHADER_DATA_LAYOUTS 8 +#define MAX_SHADER_BINDINGS 8 +#define MAX_BUFFERS 256 +#define MAX_TEXTURES 256 +#define MAX_PIPELINES 128 +#define MAX_RENDERPASSES 128 +#define MAX_VERTEX_ATTRIBUTES 16 + +// --- Handle types +CORE_DEFINE_HANDLE(BufferHandle); +CORE_DEFINE_HANDLE(TextureHandle); +CORE_DEFINE_HANDLE(SamplerHandle); +CORE_DEFINE_HANDLE(ShaderHandle); +CORE_DEFINE_HANDLE(PipelineLayoutHandle); +CORE_DEFINE_HANDLE(PipelineHandle); +CORE_DEFINE_HANDLE(RenderpassHandle); + +// --- Buffers +typedef enum GPU_BufferType{ + BUFFER_DEFAULT, // on Vulkan this would be a storage buffer? + BUFFER_VERTEX, + BUFFER_INDEX, + BUFFER_UNIFORM, + BUFFER_COUNT +} GPU_BufferType; + +static const char* buffer_type_names[] = { + "RAL Buffer Default", "RAL Buffer Vertex", "RAL Buffer Index", + "RAL Buffer Uniform", "RAL Buffer Count", +}; + +typedef enum GPU_BufferFlag { + BUFFER_FLAG_CPU = 1 << 0, + BUFFER_FLAG_GPU = 1 << 1, + BUFFER_FLAG_STORAGE = 1 << 2, + BUFFER_FLAG_COUNT +} GPU_BufferFlag; +typedef u32 GPU_BufferFlags; + +// --- Textures +typedef enum GPU_TextureType { + TEXTURE_TYPE_2D, + TEXTURE_TYPE_3D, + TEXTURE_TYPE_2D_ARRAY, + TEXTURE_TYPE_CUBE_MAP, + TEXTURE_TYPE_COUNT +} GPU_TextureType; + +typedef enum GPU_TextureFormat { + TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, + TEXTURE_FORMAT_DEPTH_DEFAULT, + TEXTURE_FORMAT_COUNT +} GPU_TextureFormat; + +/** @brief Texture Description - used by texture creation functions */ +typedef struct TextureDesc { + GPU_TextureType tex_type; + GPU_TextureFormat format; + u32x2 extents; +} TextureDesc; + +// --- Vertices + +typedef enum VertexFormat { + VERTEX_STATIC_3D, + VERTEX_SPRITE, + VERTEX_SKINNED, + VERTEX_COLOURED_STATIC_3D, + VERTEX_RAW_POS_COLOUR, + VERTEX_COUNT +} VertexFormat; + +typedef union Vertex { + struct { + Vec3 position; + Vec3 normal; + Vec2 tex_coords; + } 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 */ + + struct { + Vec3 position; + Vec2 tex_coords; + Vec3 normal; + Vec4 colour; + } coloured_static_3d; /** @brief vertex format used for debugging */ + + struct { + Vec2 position; + Vec3 colour; + } raw_pos_colour; +} Vertex; + +#ifndef TYPED_VERTEX_ARRAY +KITC_DECL_TYPED_ARRAY(Vertex); +KITC_DECL_TYPED_ARRAY(u32) +#define TYPED_VERTEX_ARRAY +#endif + +/// @strip_prefix(ATTR_) +typedef enum VertexAttribType { + ATTR_F32, + ATTR_F32x2, + ATTR_F32x3, + ATTR_F32x4, + ATTR_U32, + ATTR_U32x2, + ATTR_U32x3, + ATTR_U32x4, + ATTR_I32, + ATTR_I32x2, + ATTR_I32x3, + ATTR_I32x4, +} VertexAttribType; + +typedef struct VertexDescription { + char* debug_label; + const char* attr_names[MAX_VERTEX_ATTRIBUTES]; + VertexAttribType attributes[MAX_VERTEX_ATTRIBUTES]; + u32 attributes_count; + size_t stride; + bool use_full_vertex_size; +} VertexDescription; + +// --- Shaders +typedef enum ShaderVisibility { + VISIBILITY_VERTEX = 1 << 0, + VISIBILITY_FRAGMENT = 1 << 1, + VISIBILITY_COMPUTE = 1 << 2, +} ShaderVisibility ; + +typedef struct ShaderDesc {} ShaderDesc; + +typedef enum ShaderBindingKind { + BINDING_BUFFER, + BINDING_BUFFER_ARRAY, + BINDING_TEXTURE, + BINDING_TEXTURE_ARRAY, + // TODO: sampler + BINDING_COUNT +} ShaderBindingKind; + +typedef struct ShaderBinding { + const char* label; + ShaderBindingKind kind; + ShaderVisibility vis; + union { + struct { u32 size; } bytes; + struct { BufferHandle handle; } buffer; + struct { TextureHandle handle; } texture; + } data; +} ShaderBinding; + +typedef struct ShaderDataLayout { + ShaderBinding* bindings; + size_t binding_count; +} ShaderDataLayout; + +typedef ShaderDataLayout (*FN_GetBindingLayout)(void); + +typedef struct ShaderData { + FN_GetBindingLayout get_layout; + void* data; +} ShaderData; + +// --- Miscellaneous + +typedef enum PrimitiveTopology { + PRIMITIVE_TOPOLOGY_POINT, + PRIMITIVE_TOPOLOGY_LINE, + PRIMITIVE_TOPOLOGY_LINE_STRIP, + PRIMITIVE_TOPOLOGY_TRIANGLE, + PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + PRIMITIVE_TOPOLOGY_COUNT +} PrimitiveTopology; + +typedef enum CullMode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } CullMode; + +typedef struct GraphicsPipelineDesc { + // GPU_Renderpass* renderpass -> takes a renderpass in the create function + const char* debug_name; + VertexDescription vertex_desc; + ShaderDesc vs; /** @brief Vertex shader stage */ + ShaderDesc fs; /** @brief Fragment shader stage */ + + // Roughly equivalent to a descriptor set layout each. each layout can have multiple bindings + // examples: + // - uniform buffer reprensenting view projection matrix + // - texture for shadow map + ShaderData data_layouts[MAX_SHADER_DATA_LAYOUTS]; + u32 data_layouts_count; + + bool wireframe; + bool depth_test; +} GraphicsPipelineDesc; + +typedef struct GPU_RenderpassDesc { + bool default_framebuffer; + bool has_color_target; + TextureHandle color_target; // for now only support one + bool has_depth_stencil; + TextureHandle depth_stencil; +} GPU_RenderpassDesc; diff --git a/src/renderer/backends/backend_test.c b/src/render/backends/backend_test.c index 6347e27..6347e27 100644 --- a/src/renderer/backends/backend_test.c +++ b/src/render/backends/backend_test.c diff --git a/src/renderer/backends/metal/README.md b/src/render/backends/metal/README.md index f87f5c1..f87f5c1 100644 --- a/src/renderer/backends/metal/README.md +++ b/src/render/backends/metal/README.md diff --git a/src/renderer/backends/metal/backend_metal.h b/src/render/backends/metal/backend_metal.h index 9561bb6..9561bb6 100644 --- a/src/renderer/backends/metal/backend_metal.h +++ b/src/render/backends/metal/backend_metal.h diff --git a/src/renderer/backends/metal/backend_metal.m b/src/render/backends/metal/backend_metal.m index 4787755..4787755 100644 --- a/src/renderer/backends/metal/backend_metal.m +++ b/src/render/backends/metal/backend_metal.m diff --git a/src/renderer/backends/opengl/README.md b/src/render/backends/opengl/README.md index f87f5c1..f87f5c1 100644 --- a/src/renderer/backends/opengl/README.md +++ b/src/render/backends/opengl/README.md diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/render/backends/opengl/backend_opengl.c index 70e10d7..70e10d7 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/render/backends/opengl/backend_opengl.c diff --git a/src/renderer/backends/opengl/backend_opengl.h b/src/render/backends/opengl/backend_opengl.h index 8b88cf8..8b88cf8 100644 --- a/src/renderer/backends/opengl/backend_opengl.h +++ b/src/render/backends/opengl/backend_opengl.h diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/render/backends/opengl/opengl_helpers.h index 41018cb..41018cb 100644 --- a/src/renderer/backends/opengl/opengl_helpers.h +++ b/src/render/backends/opengl/opengl_helpers.h diff --git a/src/renderer/backends/vulkan/README.md b/src/render/backends/vulkan/README.md index 220ed64..220ed64 100644 --- a/src/renderer/backends/vulkan/README.md +++ b/src/render/backends/vulkan/README.md diff --git a/src/renderer/backends/backend_vulkan.c b/src/render/backends/vulkan/backend_vulkan.c index 8801230..8801230 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/render/backends/vulkan/backend_vulkan.c diff --git a/src/renderer/backends/backend_vulkan.h b/src/render/backends/vulkan/backend_vulkan.h index 6ca0bb5..6ca0bb5 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/render/backends/vulkan/backend_vulkan.h diff --git a/src/renderer/backends/vulkan/vulkan_glossary.md b/src/render/backends/vulkan/vulkan_glossary.md index 4214f9d..4214f9d 100644 --- a/src/renderer/backends/vulkan/vulkan_glossary.md +++ b/src/render/backends/vulkan/vulkan_glossary.md diff --git a/src/renderer/backends/vulkan_helpers.h b/src/render/backends/vulkan_helpers.h index 23666c6..23666c6 100644 --- a/src/renderer/backends/vulkan_helpers.h +++ b/src/render/backends/vulkan_helpers.h diff --git a/src/renderer/bind_group_layouts.h b/src/render/bind_group_layouts.h index 246d1ef..246d1ef 100644 --- a/src/renderer/bind_group_layouts.h +++ b/src/render/bind_group_layouts.h diff --git a/src/renderer/builtin_materials.h b/src/render/builtin_materials.h index f2db5f4..f2db5f4 100644 --- a/src/renderer/builtin_materials.h +++ b/src/render/builtin_materials.h diff --git a/src/renderer/immediate.c b/src/render/immediate.c index 63a62b8..63a62b8 100644 --- a/src/renderer/immediate.c +++ b/src/render/immediate.c diff --git a/src/renderer/immediate.h b/src/render/immediate.h index f4b1729..f4b1729 100644 --- a/src/renderer/immediate.h +++ b/src/render/immediate.h diff --git a/src/renderer/ral.c b/src/render/ral.c index 9ca99ce..9ca99ce 100644 --- a/src/renderer/ral.c +++ b/src/render/ral.c diff --git a/src/renderer/ral.h b/src/render/ral.h index b76de27..792bb4e 100644 --- a/src/renderer/ral.h +++ b/src/render/ral.h @@ -31,36 +31,36 @@ typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission typedef struct gpu_buffer gpu_buffer; typedef struct gpu_texture gpu_texture; -#define MAX_SHADER_DATA_LAYOUTS 5 -#define MAX_BUFFERS 256 -#define MAX_TEXTURES 256 -#define MAX_PIPELINES 128 -#define MAX_RENDERPASSES 128 +// #define MAX_SHADER_DATA_LAYOUTS 5 +// #define MAX_BUFFERS 256 +// #define MAX_TEXTURES 256 +// #define MAX_PIPELINES 128 +// #define MAX_RENDERPASSES 128 -TYPED_POOL(gpu_buffer, buffer); -TYPED_POOL(gpu_texture, texture); +// TYPED_POOL(gpu_buffer, buffer); +// TYPED_POOL(gpu_texture, texture); -TYPED_POOL(gpu_pipeline_layout, pipeline_layout); -TYPED_POOL(gpu_pipeline, pipeline); -TYPED_POOL(gpu_renderpass, renderpass); +// TYPED_POOL(gpu_pipeline_layout, pipeline_layout); +// TYPED_POOL(gpu_pipeline, pipeline); +// TYPED_POOL(gpu_renderpass, renderpass); -// --- Handy macros -#define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) -#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) +// // --- Handy macros +// #define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) +// #define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) // --- Pools -typedef struct gpu_backend_pools { - pipeline_pool pipelines; - pipeline_layout_pool pipeline_layouts; - renderpass_pool renderpasses; -} gpu_backend_pools; -void backend_pools_init(arena* a, gpu_backend_pools* backend_pools); - -struct resource_pools { - buffer_pool buffers; - texture_pool textures; -}; -void resource_pools_init(arena* a, struct resource_pools* res_pools); +// typedef struct gpu_backend_pools { +// pipeline_pool pipelines; +// pipeline_layout_pool pipeline_layouts; +// renderpass_pool renderpasses; +// } gpu_backend_pools; +// void backend_pools_init(arena* a, gpu_backend_pools* backend_pools); + +// struct resource_pools { +// buffer_pool buffers; +// texture_pool textures; +// }; +// void resource_pools_init(arena* a, struct resource_pools* res_pools); // --- Pipeline description typedef enum pipeline_kind { diff --git a/src/render/ral_types.h b/src/render/ral_types.h new file mode 100644 index 0000000..be95902 --- /dev/null +++ b/src/render/ral_types.h @@ -0,0 +1,104 @@ +/** + * @file ral_types.h + * @author your name (you@domain.com) + * @brief Struct and enum definitions for RAL + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once + +#include "darray.h" +#include "defines.h" +#include "maths_types.h" + +#define MAX_VERTEX_ATTRIBUTES 16 + +/* #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(pipeline_layout_handle); +CORE_DEFINE_HANDLE(pipeline_handle); +CORE_DEFINE_HANDLE(renderpass_handle); +#define ABSENT_MODEL_HANDLE 999999999 + + +// --- Shaders & Bindings + +typedef enum shader_visibility { + VISIBILITY_VERTEX = 1 << 0, + VISIBILITY_FRAGMENT = 1 << 1, + VISIBILITY_COMPUTE = 1 << 2, +} shader_visibility; + +/** @brief Describes the kind of binding a `shader_binding` is for. This changes how we create + * backing data for it. */ +typedef enum shader_binding_type { + /** + * @brief Binds a buffer to a shader + * @note Vulkan: Becomes a Storage Buffer + */ + SHADER_BINDING_BUFFER, + SHADER_BINDING_BUFFER_ARRAY, + SHADER_BINDING_TEXTURE, + SHADER_BINDING_TEXTURE_ARRAY, + SHADER_BINDING_SAMPLER, + /** + * @brief Binds raw data to a shader + * @note Vulkan: Becomes a Uniform Buffer + */ + SHADER_BINDING_BYTES, + // TODO: Acceleration Structure + SHADER_BINDING_COUNT +} shader_binding_type; + +static const char* shader_binding_type_name[] = { "BUFFER", "BUFFER ARRAY", "TEXTURE", + "TEXTURE ARRAY", "SAMPLER", "BYTES", + "COUNT" }; + +// pub trait ShaderBindable: Clone + Copy { +// fn bind_to(&self, context: &mut PipelineContext, index: u32); +// } + +typedef struct shader_binding { + const char* label; + shader_binding_type type; + shader_visibility vis; + bool stores_data; /** @brief if this is true then the shader binding has references to live data, + if false then its just being used to describe a layout and .data + should be zeroed */ + union { + struct { + buffer_handle handle; + } buffer; + struct { + void* data; + size_t size; + } bytes; + struct { + texture_handle handle; + } texture; + } data; /** @brief can store any kind of data that we can bind to a shader / descriptor set */ +} shader_binding; + + +void print_shader_binding(shader_binding b); + +/** @brief A list of bindings that describe what data a shader / pipeline expects + @note This roughly correlates to a descriptor set layout in Vulkan +*/ + +// ? How to tie together materials and shaders + +// Three registers +// 1. low level graphics api calls "ral" +// 2. higher level render calls +// 3. simplified immediate mode API + +// 3 - you don't need to know how the renderer works at all +// 2 - you need to know how the overall renderer is designed +// 1 - you need to understand graphics API specifics diff --git a/src/renderer/render.c b/src/render/render.c index f52e2be..f52e2be 100644 --- a/src/renderer/render.c +++ b/src/render/render.c diff --git a/src/renderer/render.h b/src/render/render.h index 19a8d1a..f0e9a64 100644 --- a/src/renderer/render.h +++ b/src/render/render.h @@ -69,11 +69,6 @@ texture_handle texture_data_upload(texture_data data, bool free_on_upload); material pbr_material_load(char* albedo_path, char* normal_path, bool metal_roughness_combined, char* metallic_path, char* roughness_map, char* ao_map); -buffer_handle buffer_create(const char* debug_name, u64 size); -bool buffer_destroy(buffer_handle buffer); -sampler_handle sampler_create(); - -// models and meshes are implemented **in terms of the above** /** * @brief Creates buffers and returns a struct that holds handles to our resources @@ -89,8 +84,3 @@ void mesh_delete(mesh* mesh); // TODO void draw_mesh(mesh* mesh, mat4* model, camera* cam); model_handle model_load(const char* debug_name, const char* filepath); - -void geo_free_data(geometry_data* geo); -void geo_set_vertex_colours(geometry_data* geo, vec4 colour); - -vertex_description static_3d_vertex_description(); diff --git a/src/renderer/render_types.h b/src/render/render_types.h index b25fa14..b25fa14 100644 --- a/src/renderer/render_types.h +++ b/src/render/render_types.h diff --git a/src/renderer/renderpasses.c b/src/render/renderpasses.c index b93d487..b93d487 100644 --- a/src/renderer/renderpasses.c +++ b/src/render/renderpasses.c diff --git a/src/renderer/renderpasses.h b/src/render/renderpasses.h index 5a5ffee..5a5ffee 100644 --- a/src/renderer/renderpasses.h +++ b/src/render/renderpasses.h diff --git a/src/renderer/static_pipeline.h b/src/render/static_pipeline.h index bf5bc42..bf5bc42 100644 --- a/src/renderer/static_pipeline.h +++ b/src/render/static_pipeline.h diff --git a/src/renderer/backends/backend_dx11.c b/src/renderer/backends/backend_dx11.c deleted file mode 100644 index 7e48853..0000000 --- a/src/renderer/backends/backend_dx11.c +++ /dev/null @@ -1,5 +0,0 @@ -#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 deleted file mode 100644 index 53738aa..0000000 --- a/src/renderer/backends/backend_dx11.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include <d3d11.h> -#include <d3dcompiler.h> - -#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/ral_types.h b/src/renderer/ral_types.h deleted file mode 100644 index f1f261d..0000000 --- a/src/renderer/ral_types.h +++ /dev/null @@ -1,268 +0,0 @@ -/** - * @file ral_types.h - * @author your name (you@domain.com) - * @brief Struct and enum definitions for RAL - * @version 0.1 - * @date 2024-04-27 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once - -#include "darray.h" -#include "defines.h" -#include "maths_types.h" - -#define MAX_VERTEX_ATTRIBUTES 16 - -/* #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(pipeline_layout_handle); -CORE_DEFINE_HANDLE(pipeline_handle); -CORE_DEFINE_HANDLE(renderpass_handle); -#define ABSENT_MODEL_HANDLE 999999999 - -/* #define RENDERER_TYPED_HANDLES */ -/* #endif */ - -/* typedef struct gpu_buffer { */ -/* u32 a; */ -/* } gpu_buffer; */ - -/* #ifndef RAL_TYPED_POOLS */ -/* #define RAL_TYPED_POOLS */ -/* #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 gpu_buffer_type { - CEL_BUFFER_DEFAULT, // on Vulkan this would be a storage buffer? - CEL_BUFFER_VERTEX, - CEL_BUFFER_INDEX, - CEL_BUFFER_UNIFORM, - CEL_BUFFER_COUNT -} gpu_buffer_type; - -static const char* buffer_type_names[] = { - "RAL Buffer Default", "RAL Buffer Vertex", "RAL Buffer Index", - "RAL Buffer Uniform", "RAL Buffer Count", -}; - -typedef enum gpu_buffer_flag { - CEL_BUFFER_FLAG_CPU = 1 << 0, - CEL_BUFFER_FLAG_GPU = 1 << 1, - CEL_BUFFER_FLAG_STORAGE = 1 << 2, - CEL_BUFFER_FLAG_COUNT -} gpu_buffer_flag; -typedef u32 gpu_buffer_flags; - -typedef enum vertex_format { - VERTEX_STATIC_3D, - VERTEX_SPRITE, - VERTEX_SKINNED, - VERTEX_COLOURED_STATIC_3D, - VERTEX_RAW_POS_COLOUR, - VERTEX_COUNT -} vertex_format; - -typedef union vertex { - struct { - vec3 position; - vec3 normal; - vec2 tex_coords; - } 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 */ - - struct { - vec3 position; - vec2 tex_coords; - vec3 normal; - vec4 colour; - } coloured_static_3d; /** @brief vertex format used for debugging */ - - struct { - vec2 position; - vec3 colour; - } raw_pos_colour; -} vertex; - -#ifndef TYPED_VERTEX_ARRAY -KITC_DECL_TYPED_ARRAY(vertex) -KITC_DECL_TYPED_ARRAY(u32) -#define TYPED_VERTEX_ARRAY -#endif - -// TEMP -typedef struct custom_vertex { - vec2 pos; - vec3 color; -} custom_vertex; - -// Vertex attributes -/// @strip_prefix(ATTR_) -typedef enum vertex_attrib_type { - ATTR_F32, - ATTR_F32x2, - ATTR_F32x3, - ATTR_F32x4, - ATTR_U32, - ATTR_U32x2, - ATTR_U32x3, - ATTR_U32x4, - ATTR_I32, - ATTR_I32x2, - ATTR_I32x3, - ATTR_I32x4, -} vertex_attrib_type; - -typedef struct vertex_description { - char* debug_label; - const char* attr_names[MAX_VERTEX_ATTRIBUTES]; - vertex_attrib_type attributes[MAX_VERTEX_ATTRIBUTES]; - u32 attributes_count; - size_t stride; - bool use_full_vertex_size; -} vertex_description; - -// --- Shaders & Bindings - -typedef enum shader_visibility { - VISIBILITY_VERTEX = 1 << 0, - VISIBILITY_FRAGMENT = 1 << 1, - VISIBILITY_COMPUTE = 1 << 2, -} shader_visibility; - -/** @brief Describes the kind of binding a `shader_binding` is for. This changes how we create - * backing data for it. */ -typedef enum shader_binding_type { - /** - * @brief Binds a buffer to a shader - * @note Vulkan: Becomes a Storage Buffer - */ - SHADER_BINDING_BUFFER, - SHADER_BINDING_BUFFER_ARRAY, - SHADER_BINDING_TEXTURE, - SHADER_BINDING_TEXTURE_ARRAY, - SHADER_BINDING_SAMPLER, - /** - * @brief Binds raw data to a shader - * @note Vulkan: Becomes a Uniform Buffer - */ - SHADER_BINDING_BYTES, - // TODO: Acceleration Structure - SHADER_BINDING_COUNT -} shader_binding_type; - -static const char* shader_binding_type_name[] = { "BUFFER", "BUFFER ARRAY", "TEXTURE", - "TEXTURE ARRAY", "SAMPLER", "BYTES", - "COUNT" }; - -// pub trait ShaderBindable: Clone + Copy { -// fn bind_to(&self, context: &mut PipelineContext, index: u32); -// } - -typedef struct shader_binding { - const char* label; - shader_binding_type type; - shader_visibility vis; - bool stores_data; /** @brief if this is true then the shader binding has references to live data, - if false then its just being used to describe a layout and .data - should be zeroed */ - union { - struct { - buffer_handle handle; - } buffer; - struct { - void* data; - size_t size; - } bytes; - struct { - texture_handle handle; - } texture; - } data; /** @brief can store any kind of data that we can bind to a shader / descriptor set */ -} shader_binding; - -#define MAX_LAYOUT_BINDINGS 8 - -void print_shader_binding(shader_binding b); - -/** @brief A list of bindings that describe what data a shader / pipeline expects - @note This roughly correlates to a descriptor set layout in Vulkan -*/ -typedef struct shader_data_layout { - char* name; - shader_binding bindings[MAX_LAYOUT_BINDINGS]; - u32 bindings_count; -} shader_data_layout; - -typedef struct shader_data { - shader_data_layout (*shader_data_get_layout)(void* data); - void* data; -} shader_data; - -/* - Usage: - 1. When we create the pipeline, we must call a function that return a layout without .data - fields - 2. When binding -*/ - -typedef enum gpu_cull_mode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } gpu_cull_mode; - -// ? How to tie together materials and shaders - -// Three registers -// 1. low level graphics api calls "ral" -// 2. higher level render calls -// 3. simplified immediate mode API - -// 3 - you don't need to know how the renderer works at all -// 2 - you need to know how the overall renderer is designed -// 1 - you need to understand graphics API specifics diff --git a/src/resources/gltf.c b/src/resources/gltf.c index c51e30d..e381954 100644 --- a/src/resources/gltf.c +++ b/src/resources/gltf.c @@ -21,24 +21,24 @@ #define CGLTF_IMPLEMENTATION #include <cgltf.h> -extern core g_core; +extern Core g_core; struct face { cgltf_uint indices[3]; }; typedef struct face face; -KITC_DECL_TYPED_ARRAY(vec3) -KITC_DECL_TYPED_ARRAY(vec2) -KITC_DECL_TYPED_ARRAY(vec4u) -KITC_DECL_TYPED_ARRAY(vec4) +KITC_DECL_TYPED_ARRAY(Vec3) +KITC_DECL_TYPED_ARRAY(Vec2) +KITC_DECL_TYPED_ARRAY(Vec4u) +KITC_DECL_TYPED_ARRAY(Vec4) KITC_DECL_TYPED_ARRAY(face) // KITC_DECL_TYPED_ARRAY(joint) -bool model_load_gltf_str(const char *file_string, const char *filepath, str8 relative_path, - model *out_model, bool invert_textures_y); +bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 relative_path, + Model *out_model, bool invert_textures_y); -model_handle model_load_gltf(const char *path, bool invert_texture_y) { +ModelHandle model_load_gltf(const char *path, bool invert_texture_y) { size_t arena_size = 1024; arena scratch = arena_create(malloc(arena_size), arena_size); @@ -49,22 +49,22 @@ model_handle model_load_gltf(const char *path, bool invert_texture_y) { } const char *file_string = string_from_file(path); - model_handle handle; - model *model = model_pool_alloc(&g_core.models, &handle); - model->name = str8_cstr_view(path); - model->meshes = mesh_darray_new(1); - model->materials = material_darray_new(1); + ModelHandle handle; + // modfl *model = model_pool_alloc(&g_core.models, &handle); + // model->name = str8_cstr_view(path); + // model->meshes = mesh_darray_new(1); + // model->materials = material_darray_new(1); - bool success = - model_load_gltf_str(file_string, path, relative_path.path, model, invert_texture_y); + // bool success = + // model_load_gltf_str(file_string, path, relative_path.path, model, invert_texture_y); - if (!success) { - FATAL("Couldnt load GLTF file at path %s", path); - ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); - } + // if (!success) { + // FATAL("Couldnt load GLTF file at path %s", path); + // ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); + // } - arena_free_all(&scratch); - arena_free_storage(&scratch); + // arena_free_all(&scratch); + // arena_free_storage(&scratch); return handle; } @@ -85,31 +85,31 @@ typedef struct model { u32 mesh_count; } model; */ -bool model_load_gltf_str(const char *file_string, const char *filepath, str8 relative_path, - model *out_model, bool invert_textures_y) { - TRACE("Load GLTF 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); - vec4u_darray *tmp_joint_indices = vec4u_darray_new(1000); - vec4_darray *tmp_weights = vec4_darray_new(1000); - // FIXME - // joint_darray *tmp_joints = joint_darray_new(256); - // vertex_bone_data_darray *tmp_vertex_bone_data = vertex_bone_data_darray_new(1000); - - cgltf_options options = { 0 }; +bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 relative_path, + Model *out_model, bool invert_textures_y) { + // TRACE("Load GLTF 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); + // vec4u_darray *tmp_joint_indices = vec4u_darray_new(1000); + // vec4_darray *tmp_weights = vec4_darray_new(1000); + // // FIXME + // // joint_darray *tmp_joints = joint_darray_new(256); + // // vertex_bone_data_darray *tmp_vertex_bone_data = vertex_bone_data_darray_new(1000); + + // cgltf_options options = { 0 }; cgltf_data *data = NULL; - cgltf_result result = cgltf_parse_file(&options, filepath, &data); - if (result != cgltf_result_success) { - WARN("gltf load failed"); - // TODO: cleanup arrays(allocate all from arena ?) - return false; - } + // cgltf_result result = cgltf_parse_file(&options, filepath, &data); + // if (result != cgltf_result_success) { + // WARN("gltf load failed"); + // // TODO: cleanup arrays(allocate all from arena ?) + // return false; + // } - cgltf_load_buffers(&options, data, filepath); - DEBUG("loaded buffers"); + // cgltf_load_buffers(&options, data, filepath); + // DEBUG("loaded buffers"); // // --- Skin // size_t num_skins = data->skins_count; @@ -183,13 +183,13 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel snprintf(normal_map_path, sizeof(normal_map_path), "%s/%s", relative_path.buf, normal_tex_view.texture->image->uri); - material our_material = - pbr_material_load(albedo_map_path, normal_map_path, true, metal_rough_map_path, NULL, NULL); + // material our_material = + // pbr_material_load(albedo_map_path, normal_map_path, true, metal_rough_map_path, NULL, NULL); - our_material.name = malloc(strlen(gltf_material.name) + 1); - strcpy(our_material.name, gltf_material.name); + // our_material.name = malloc(strlen(gltf_material.name) + 1); + // strcpy(our_material.name, gltf_material.name); - material_darray_push(out_model->materials, our_material); + // material_darray_push(out_model->materials, our_material); } // TEMP @@ -214,11 +214,11 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel TRACE("Loading %d vec3 components", accessor->count); - for (cgltf_size v = 0; v < accessor->count; ++v) { - vec3 pos; - cgltf_accessor_read_float(accessor, v, &pos.x, 3); - vec3_darray_push(tmp_positions, pos); - } + // for (cgltf_size v = 0; v < accessor->count; ++v) { + // vec3 pos; + // cgltf_accessor_read_float(accessor, v, &pos.x, 3); + // vec3_darray_push(tmp_positions, pos); + // } } else if (attribute.type == cgltf_attribute_type_normal) { TRACE("Load normals from accessor"); @@ -227,11 +227,11 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel assert(accessor->component_type == cgltf_component_type_r_32f); // CASSERT_MSG(accessor->type == cgltf_type_vec3, "Normal vectors should be a vec3"); - for (cgltf_size v = 0; v < accessor->count; ++v) { - vec3 pos; - cgltf_accessor_read_float(accessor, v, &pos.x, 3); - vec3_darray_push(tmp_normals, pos); - } + // for (cgltf_size v = 0; v < accessor->count; ++v) { + // vec3 pos; + // cgltf_accessor_read_float(accessor, v, &pos.x, 3); + // vec3_darray_push(tmp_normals, pos); + // } } else if (attribute.type == cgltf_attribute_type_texcoord) { TRACE("Load texture coordinates from accessor"); @@ -241,12 +241,12 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel // vec2"); for (cgltf_size v = 0; v < accessor->count; ++v) { - vec2 tex; - bool success = cgltf_accessor_read_float(accessor, v, &tex.x, 2); - if (!success) { - ERROR("Error loading tex coord"); - } - vec2_darray_push(tmp_uvs, tex); + // vec2 tex; + // bool success = cgltf_accessor_read_float(accessor, v, &tex.x, 2); + // if (!success) { + // ERROR("Error loading tex coord"); + // } + // vec2_darray_push(tmp_uvs, tex); } } else if (attribute.type == cgltf_attribute_type_joints) { // FIXME: joints @@ -289,18 +289,18 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel } // mesh.vertex_bone_data = vertex_bone_data_darray_new(1); - if (primitive.material != NULL) { - ERROR("Primitive Material %s", primitive.material->name); - for (u32 i = 0; i < material_darray_len(out_model->materials); i++) { - printf("%s vs %s \n", primitive.material->name, out_model->materials->data[i].name); - if (strcmp(primitive.material->name, out_model->materials->data[i].name) == 0) { - INFO("Found material"); - mat_idx = i; - // mesh.material_index = i; - break; - } - } - } + // if (primitive.material != NULL) { + // ERROR("Primitive Material %s", primitive.material->name); + // for (u32 i = 0; i < material_darray_len(out_model->materials); i++) { + // printf("%s vs %s \n", primitive.material->name, out_model->materials->data[i].name); + // if (strcmp(primitive.material->name, out_model->materials->data[i].name) == 0) { + // INFO("Found material"); + // mat_idx = i; + // // mesh.material_index = i; + // break; + // } + // } + // } // // FIXME // // if (is_skinned) { @@ -322,34 +322,34 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel // // } bool has_indices = false; - vertex_darray *geo_vertices = vertex_darray_new(3); + Vertex_darray *geo_vertices = Vertex_darray_new(3); u32_darray *geo_indices = u32_darray_new(0); // Store vertices - printf("Positions %d Normals %d UVs %d\n", tmp_positions->len, tmp_normals->len, tmp_uvs->len); - assert(tmp_positions->len == tmp_normals->len); - assert(tmp_normals->len == tmp_uvs->len); - for (u32 v_i = 0; v_i < tmp_positions->len; v_i++) { - vertex v = { .static_3d = { - .position = tmp_positions->data[v_i], - .normal = tmp_normals->data[v_i], - .tex_coords = tmp_uvs->data[v_i], - } }; - vertex_darray_push(geo_vertices, v); + // printf("Positions %d Normals %d UVs %d\n", tmp_positions->len, tmp_normals->len, tmp_uvs->len); + // assert(tmp_positions->len == tmp_normals->len); + // assert(tmp_normals->len == tmp_uvs->len); + // for (u32 v_i = 0; v_i < tmp_positions->len; v_i++) { + // vertex v = { .static_3d = { + // .position = tmp_positions->data[v_i], + // .normal = tmp_normals->data[v_i], + // .tex_coords = tmp_uvs->data[v_i], + // } }; + // vertex_darray_push(geo_vertices, v); } // Store indices - cgltf_accessor *indices = primitive.indices; - if (primitive.indices > 0) { - WARN("indices! %d", indices->count); - has_indices = true; - - // store indices - for (cgltf_size i = 0; i < indices->count; ++i) { - cgltf_uint ei; - cgltf_accessor_read_uint(indices, i, &ei, 1); - u32_darray_push(geo_indices, ei); - } + // cgltf_accessor *indices = primitive.indices; + // if (primitive.indices > 0) { + // WARN("indices! %d", indices->count); + // has_indices = true; + + // // store indices + // for (cgltf_size i = 0; i < indices->count; ++i) { + // cgltf_uint ei; + // cgltf_accessor_read_uint(indices, i, &ei, 1); + // u32_darray_push(geo_indices, ei); + // } // fetch and store vertices for each index // for (cgltf_size i = 0; i < indices->count; ++i) { @@ -366,23 +366,23 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel // } // // for each vertex do the bone data // } - } else { - has_indices = false; - return false; // TODO: handle this - } - - geometry_data *geometry = malloc(sizeof(geometry_data)); - geometry->format = VERTEX_STATIC_3D; - geometry->colour = (rgba){ 1, 1, 1, 1 }; - geometry->vertices = geo_vertices; - geometry->indices = geo_indices; - geometry->has_indices = has_indices; - - mesh m = mesh_create(geometry, true); - m.material_index = (u32_opt){ .has_value = mat_idx == 9999, .value = mat_idx }; - - mesh_darray_push(out_model->meshes, m); - } + // } else { + // has_indices = false; + // return false; // TODO: handle this + // } + + // geometry_data *geometry = malloc(sizeof(geometry_data)); + // geometry->format = VERTEX_STATIC_3D; + // geometry->colour = (rgba){ 1, 1, 1, 1 }; + // geometry->vertices = geo_vertices; + // geometry->indices = geo_indices; + // geometry->has_indices = has_indices; + + // mesh m = mesh_create(geometry, true); + // m.material_index = (u32_opt){ .has_value = mat_idx == 9999, .value = mat_idx }; + + // mesh_darray_push(out_model->meshes, m); + // } // // clear data for each mesh // vec3_darray_clear(tmp_positions); diff --git a/src/resources/loaders.h b/src/resources/loaders.h index fe03ed9..d8437b9 100644 --- a/src/resources/loaders.h +++ b/src/resources/loaders.h @@ -2,8 +2,12 @@ #include "defines.h" #include "render_types.h" +#include "str.h" -struct core; +// --- Public API +ModelHandle Model_Load_obj(const char *path, bool invert_texture_y); +ModelHandle Model_Load_gltf(const char *path, bool invert_texture_y); -model_handle model_load_obj(const char *path, bool invert_texture_y); -model_handle model_load_gltf(const char *path, bool invert_texture_y); +// --- Internal +bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 relative_path, + Model *out_model, bool invert_textures_y); diff --git a/src/resources/obj.c b/src/resources/obj.c index 411ad82..87d3ed6 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -22,7 +22,7 @@ #include "render_types.h" #include "str.h" -extern core g_core; +extern Core g_core; struct face { u32 vertex_indices[3]; @@ -31,19 +31,19 @@ struct face { }; typedef struct face face; -KITC_DECL_TYPED_ARRAY(vec3) -KITC_DECL_TYPED_ARRAY(vec2) +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, 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); - -model_handle model_load_obj(core *core, const char *path, bool invert_textures_y) { +// 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, 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); + +ModelHandle model_load_obj(Core *core, const char *path, bool invert_textures_y) { size_t arena_size = 1024; arena scratch = arena_create(malloc(arena_size), arena_size); @@ -54,24 +54,24 @@ model_handle model_load_obj(core *core, const char *path, bool invert_textures_y } const char *file_string = string_from_file(path); - model_handle handle; - model *model = model_pool_alloc(&g_core.models, &handle); - model->name = str8_cstr_view(path); - model->meshes = mesh_darray_new(1); + ModelHandle handle; + // model *model = model_pool_alloc(&g_core.models, &handle); + // model->name = str8_cstr_view(path); + // model->meshes = mesh_darray_new(1); - bool success = model_load_obj_str(file_string, relative_path.path, &model, invert_textures_y); + // bool success = model_load_obj_str(file_string, relative_path.path, &model, invert_textures_y); - if (!success) { - FATAL("Couldnt load OBJ file at path %s", path); - ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); - } + // if (!success) { + // FATAL("Couldnt load OBJ file at path %s", path); + // ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); + // } - arena_free_all(&scratch); - arena_free_storage(&scratch); + // arena_free_all(&scratch); + // arena_free_storage(&scratch); return handle; } -bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_model, +bool model_load_obj_str(const char *file_string, Str8 relative_path, Model *out_model, bool invert_textures_y) { TRACE("Load OBJ from string"); @@ -232,166 +232,166 @@ bool model_load_obj_str(const char *file_string, str8 relative_path, model *out_ 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))) { - // 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, str8 relative_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_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; - // 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); - // 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; - // 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); - // } - - // 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); - - // INFO("Loaded %ld materials", material_darray_len(materials)); - TRACE("END load material lib"); - 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))) { +// // 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, str8 relative_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_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; +// // 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); +// // 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; +// // 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); +// // } + +// // 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); + +// // INFO("Loaded %ld materials", material_darray_len(materials)); +// TRACE("END load material lib"); +// return true; +// } diff --git a/src/scene.c b/src/scene.c index d9fea05..f6f5fb7 100644 --- a/src/scene.c +++ b/src/scene.c @@ -1,56 +1,57 @@ #include "scene.h" +#include "camera.h" #include "core.h" #include "log.h" #include "maths.h" #include "render_types.h" -extern core g_core; +extern Core g_core; -void scene_init(scene *s) { - memset(s, 0, sizeof(scene)); - s->renderables = render_entity_darray_new(10); - // default camera position - moved slightly along Z axis looking at 0,0,0 - vec3 cam_pos = vec3_create(0, 0, -5); - s->camera = camera_create(cam_pos, vec3_negate(cam_pos), VEC3_Y, deg_to_rad(45.0)); -} -void scene_free(scene *s) { render_entity_darray_free(s->renderables); } +// void scene_init(scene *s) { +// memset(s, 0, sizeof(scene)); +// s->renderables = render_entity_darray_new(10); +// // default camera position - moved slightly along Z axis looking at 0,0,0 +// Vec3 cam_pos = vec3_create(0, 0, -5); +// s->camera = Camera_Create(cam_pos, vec3_negate(cam_pos), VEC3_Y, deg_to_rad(45.0)); +// } +// void scene_free(scene *s) { render_entity_darray_free(s->renderables); } -void scene_set_dir_light(directional_light light) { g_core.default_scene.dir_light = light; } -void scene_add_point_light(point_light light) { - scene s = g_core.default_scene; - if (s.point_lights_count == 4) { - WARN("Already 4 point lights, we can't add more."); - } else { - s.point_lights[s.point_lights_count] = light; - s.point_lights_count++; - } -} -void scene_add_model(model_handle model, transform3d transform) { - render_entity renderable = { .model = model, .tf = transform }; - render_entity_darray_push(g_core.default_scene.renderables, renderable); -} +// void scene_set_dir_light(directional_light light) { g_core.default_scene.dir_light = light; } +// void scene_add_point_light(point_light light) { +// scene s = g_core.default_scene; +// if (s.point_lights_count == 4) { +// WARN("Already 4 point lights, we can't add more."); +// } else { +// s.point_lights[s.point_lights_count] = light; +// s.point_lights_count++; +// } +// } +// void scene_add_model(model_handle model, transform3d transform) { +// render_entity renderable = { .model = model, .tf = transform }; +// render_entity_darray_push(g_core.default_scene.renderables, renderable); +// } -bool scene_remove_model(model_handle model) { - scene s = g_core.default_scene; - for (u32 i = 0; i <= s.renderables->len; i++) { - if (s.renderables->data[i].model.raw == model.raw) { - // TODO: add remove function to darray - } - } - return true; -} +// bool scene_remove_model(model_handle model) { +// scene s = g_core.default_scene; +// for (u32 i = 0; i <= s.renderables->len; i++) { +// if (s.renderables->data[i].model.raw == model.raw) { +// // TODO: add remove function to darray +// } +// } +// return true; +// } -void scene_set_model_transform(model_handle model, transform3d new_transform) { - scene s = g_core.default_scene; - for (u32 i = 0; i <= s.renderables->len; i++) { - if (s.renderables->data[i].model.raw == model.raw) { - s.renderables->data[i].tf = new_transform; - } - } -} +// void scene_set_model_transform(model_handle model, transform3d new_transform) { +// scene s = g_core.default_scene; +// for (u32 i = 0; i <= s.renderables->len; i++) { +// if (s.renderables->data[i].model.raw == model.raw) { +// s.renderables->data[i].tf = new_transform; +// } +// } +// } -void scene_set_camera(vec3 pos, vec3 front) { - scene s = g_core.default_scene; - s.camera.position = pos; - s.camera.front = front; -} +// void scene_set_camera(vec3 pos, vec3 front) { +// scene s = g_core.default_scene; +// s.camera.position = pos; +// s.camera.front = front; +// } diff --git a/src/scene.h b/src/scene.h index 5ac7542..e414ea8 100644 --- a/src/scene.h +++ b/src/scene.h @@ -14,20 +14,20 @@ #include "maths_types.h" #include "render_types.h" -typedef struct scene { - // camera - camera camera; - // lights - directional_light dir_light; - point_light point_lights[4]; - size_t point_lights_count; - // geometry - render_entity_darray* renderables; - // TODO: tree - transform_hierarchy -} scene; - -void scene_init(scene* s); -void scene_free(scene* s); +// typedef struct scene { +// // camera +// Camera camera; +// // lights +// DirectionalLight dir_light; +// PointLight point_lights[4]; +// size_t point_lights_count; +// // geometry +// render_entity_darray* renderables; +// // TODO: tree - transform_hierarchy +// } scene; + +// void scene_init(scene* s); +// void scene_free(scene* s); // Simplified API - no scene pointer; gets and sets global scene @@ -36,16 +36,16 @@ void scene_free(scene* s); /* vec3 ambient; */ /* vec3 diffuse; */ /* vec3 specular; */ -void scene_set_dir_light(directional_light light); -void _scene_set_dir_light(vec3 ambient, vec3 diffuse, vec3 specular, vec3 direction); +// void scene_set_dir_light(directional_light light); +// void _scene_set_dir_light(vec3 ambient, vec3 diffuse, vec3 specular, vec3 direction); -void scene_add_point_light(point_light light); -void scene_add_model(model_handle model, transform3d transform); -bool scene_remove_model(model_handle model); +// void scene_add_point_light(point_light light); +// void scene_add_model(model_handle model, transform3d transform); +// bool scene_remove_model(model_handle model); -// Getter & Setters -void scene_set_model_transform(model_handle model, transform3d new_transform); -void scene_set_camera(vec3 pos, vec3 front); +// // Getter & Setters +// void scene_set_model_transform(model_handle model, transform3d new_transform); +// void scene_set_camera(vec3 pos, vec3 front); /* // There can only be one heightmap terrain at a time right now. */ /* bool scene_add_heightmap(scene* s /\* TODO *\/); */ diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index b15d269..b3dbd06 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -86,6 +86,7 @@ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ T *resized = Type##_darray_resize(d, new_capacity); \ + (void)resized; \ } \ \ d->data[d->len] = value; \ @@ -97,6 +98,7 @@ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ T *resized = Type##_darray_resize(d, new_capacity); \ + (void)resized; \ } \ \ T *place = d->data + d->len; \ @@ -116,6 +118,7 @@ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ T *resized = Type##_darray_resize(d, new_capacity); \ + (void)resized; \ } \ \ /* shift existing data after index */ \ @@ -136,14 +139,6 @@ \ PREFIX size_t Type##_darray_len(Type##_darray *d) { return d->len; } \ \ - PREFIX void Type##_darray_print(Type##_darray *d) { \ - printf("len: %zu ", d->len); \ - printf("capacity: %zu\n", d->capacity); \ - for (int i = 0; i < d->len; i++) { \ - printf("Index %d holds value %d\n", i, d->data[i]); \ - } \ - } \ - \ PREFIX Type##_darray_iter Type##_darray_iter_new(Type##_darray *d) { \ Type##_darray_iter iterator; \ iterator.array = d; \ diff --git a/src/std/mem.h b/src/std/mem.h index 8ab6f46..789cba3 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -80,12 +80,12 @@ void void_pool_dealloc(void_pool* pool, u32 raw_handle); void_pool p = void_pool_create(a, "\"" #Name "\"", cap, entry_size); \ return (Name##_pool){ .inner = p }; \ } \ - static inline T* Name##_pool_get(Name##_pool* pool, Name##_handle handle) { \ + static inline T* Name##_pool_get(Name##_pool* pool, Name##Handle handle) { \ return (T*)void_pool_get(&pool->inner, handle.raw); \ } \ - static inline T* Name##_pool_alloc(Name##_pool* pool, Name##_handle* out_handle) { \ + static inline T* Name##_pool_alloc(Name##_pool* pool, Name##Handle* out_handle) { \ return (T*)void_pool_alloc(&pool->inner, &out_handle->raw); \ } \ - static inline void Name##_pool_dealloc(Name##_pool* pool, Name##_handle handle) { \ + static inline void Name##_pool_dealloc(Name##_pool* pool, Name##Handle handle) { \ void_pool_dealloc(&pool->inner, handle.raw); \ }\ diff --git a/src/std/str.c b/src/std/str.c index 07a8e73..e15c38f 100644 --- a/src/std/str.c +++ b/src/std/str.c @@ -3,62 +3,62 @@ #include <string.h> #include "mem.h" -str8 str8_create(u8* buf, size_t len) { return (str8){ .buf = buf, .len = len }; } +// str8 str8_create(u8* buf, size_t len) { return (str8){ .buf = buf, .len = len }; } -str8 str8_cstr_view(char* string) { return str8_create((u8*)string, strlen(string)); } +// str8 str8_cstr_view(char* string) { return str8_create((u8*)string, strlen(string)); } -bool str8_equals(str8 a, str8 b) { - if (a.len != b.len) { - return false; - } +// bool str8_equals(str8 a, str8 b) { +// if (a.len != b.len) { +// return false; +// } - for (size_t i = 0; i < a.len; i++) { - if (a.buf[i] != b.buf[i]) { - return false; - } - } - return true; -} +// for (size_t i = 0; i < a.len; i++) { +// if (a.buf[i] != b.buf[i]) { +// return false; +// } +// } +// return true; +// } -char* str8_to_cstr(arena* a, str8 s) { - bool is_null_terminated = s.buf[s.len - 1] == 0; - size_t n_bytes = is_null_terminated ? s.len : s.len + 1; +// char* str8_to_cstr(arena* a, str8 s) { +// bool is_null_terminated = s.buf[s.len - 1] == 0; +// size_t n_bytes = is_null_terminated ? s.len : s.len + 1; - u8* dest = arena_alloc(a, n_bytes); +// u8* dest = arena_alloc(a, n_bytes); - memcpy(dest, s.buf, s.len); - if (is_null_terminated) { - dest[s.len] = '\0'; - } - return (char*)dest; -} +// memcpy(dest, s.buf, s.len); +// if (is_null_terminated) { +// dest[s.len] = '\0'; +// } +// return (char*)dest; +// } -str8 str8_concat(arena* a, str8 left, str8 right) { - size_t n_bytes = left.len + right.len + 1; +// str8 str8_concat(arena* a, str8 left, str8 right) { +// size_t n_bytes = left.len + right.len + 1; - u8* dest = arena_alloc(a, n_bytes); - memcpy(dest, left.buf, left.len); - memcpy(dest + right.len, right.buf, right.len); +// u8* dest = arena_alloc(a, n_bytes); +// memcpy(dest, left.buf, left.len); +// memcpy(dest + right.len, right.buf, right.len); - dest[n_bytes - 1] = '\0'; +// dest[n_bytes - 1] = '\0'; - return str8_create(dest, n_bytes); -} +// return str8_create(dest, n_bytes); +// } -str8 str8_substr(str8 s, u64 min, u64 max) { - assert(min >= 0); - assert(min < s.len); - assert(max >= 0); - assert(max <= s.len); - uint8_t* start = s.buf + (ptrdiff_t)min; - size_t new_len = max - min; - return (str8){ .buf = start, .len = new_len }; -} +// str8 str8_substr(str8 s, u64 min, u64 max) { +// assert(min >= 0); +// assert(min < s.len); +// assert(max >= 0); +// assert(max <= s.len); +// uint8_t* start = s.buf + (ptrdiff_t)min; +// size_t new_len = max - min; +// return (str8){ .buf = start, .len = new_len }; +// } -str8 str8_take(str8 s, u64 first_n) { return str8_substr(s, 0, first_n); } +// str8 str8_take(str8 s, u64 first_n) { return str8_substr(s, 0, first_n); } -str8 str8_drop(str8 s, u64 last_n) { return str8_substr(s, s.len - last_n, s.len); } +// str8 str8_drop(str8 s, u64 last_n) { return str8_substr(s, s.len - last_n, s.len); } -str8 str8_skip(str8 s, u64 n) { return str8_substr(s, n, s.len); } +// str8 str8_skip(str8 s, u64 n) { return str8_substr(s, n, s.len); } -str8 str8_chop(str8 s, u64 n) { return str8_substr(s, 0, s.len - n); } +// str8 str8_chop(str8 s, u64 n) { return str8_substr(s, 0, s.len - n); } diff --git a/src/std/str.h b/src/std/str.h index 1ebecac..e9c4098 100644 --- a/src/std/str.h +++ b/src/std/str.h @@ -23,30 +23,30 @@ typedef struct { u8* buf; size_t len; -} str8; +} Str8; // --- Constructors /** @brief Take a string literal and turn it into a `str8` */ -#define str8lit(s) \ - (str8) { (u8*)s, ((sizeof(s) / sizeof(*(s)) - 1)) } +#define str8(s) \ + (Str8) { (u8*)s, ((sizeof(s) / sizeof(*(s)) - 1)) } -str8 str8_create(u8* buf, size_t len); +Str8 str8_create(u8* buf, size_t len); /** @brief Return a null-terminated C string cloned onto an arena */ -char* str8_to_cstr(arena* a, str8 s); +char* Str8_to_cstr(arena* a, Str8 s); -#define cstr(a, s) (str8_to_cstr(a, s)) // Shorthand +#define cstr(a, s) (Str8_to_cstr(a, s)) // Shorthand -/** @brief Return a str8 that references a statically allocated string. +/** @brief Return a Str8 that references a statically allocated string. `string` therefore must already be null-terminated. @note The backing `string` cannot be modified. */ -str8 str8_cstr_view(char* string); +Str8 Str8_cstr_view(char* string); // --- Comparisons /** @brief Compare two strings for exact equality */ -bool str8_equals(str8 a, str8 b); +bool Str8_equals(Str8 a, Str8 b); /** * @brief Compare the first `first_nchars` of each string for equality @@ -55,27 +55,27 @@ bool str8_equals(str8 a, str8 b); * @returns 0 if they are fully equal up until `first_nchars`, i.e they never differed, else it returns the index at which the first string differed from the second string. */ -size_t str8_nequals(str8 a, str8 b, size_t first_nchars); +size_t Str8_nequals(Str8 a, Str8 b, size_t first_nchars); -bool str8_ends_with(str8 input_str, str8 suffix); +bool Str8_ends_with(Str8 input_str, Str8 suffix); /// --- Subviews -str8 str8_substr(str8 s, u64 min, u64 max); +Str8 Str8_substr(Str8 s, u64 min, u64 max); /** @brief Keeps only the `first_n` chars of `s` */ -str8 str8_take(str8 s, u64 first_n); +Str8 Str8_take(Str8 s, u64 first_n); /** @brief Keeps only the `last_n` chars of `s` */ -str8 str8_drop(str8 s, u64 last_n); +Str8 Str8_drop(Str8 s, u64 last_n); /** @brief Keeps everything after the first `n` chars of `s` */ -str8 str8_skip(str8 s, u64 n); +Str8 Str8_skip(Str8 s, u64 n); /** @brief Keeps everything before the last `n` chars of `s` */ -str8 str8_chop(str8 s, u64 n); +Str8 Str8_chop(Str8 s, u64 n); -str8 str8_concat(arena* a, str8 left, str8 right); +Str8 Str8_concat(arena* a, Str8 left, Str8 right); /// --- Misc -static inline bool str8_is_null_term(str8 a) { +static inline bool Str8_is_null_term(Str8 a) { return a.buf[a.len] == 0; // This doesn't seem safe. YOLO } diff --git a/src/systems/input.c b/src/systems/input.c index 0c8f768..a371ecd 100644 --- a/src/systems/input.c +++ b/src/systems/input.c @@ -6,11 +6,11 @@ #include "log.h" -static input_state *g_input; // Use a global to simplify caller code +static Input_State *g_input; // Use a global to simplify caller code -bool input_system_init(input_state *input, GLFWwindow *window) { +bool Input_Init(Input_State *input, GLFWwindow *window) { INFO("Input init"); - memset(input, 0, sizeof(input_state)); + memset(input, 0, sizeof(Input_State)); input->window = window; // Set everything to false. Could just set memory to zero but where's the fun in that @@ -29,9 +29,9 @@ bool input_system_init(input_state *input, GLFWwindow *window) { return true; } -void input_system_shutdown(input_state *input) {} +void Input_Shutdown(Input_State *input) {} -void input_update(input_state *input) { +void Input_Update(Input_State *input) { glfwPollEvents(); // --- update keyboard input @@ -95,4 +95,4 @@ bool key_is_pressed(keycode key) { return g_input->depressed_keys[key]; } bool key_just_pressed(keycode key) { return g_input->just_pressed_keys[key]; } -bool key_just_released(keycode key) { return g_input->just_released_keys[key]; }
\ No newline at end of file +bool key_just_released(keycode key) { return g_input->just_released_keys[key]; } diff --git a/src/systems/input.h b/src/systems/input.h index c119016..11c40ea 100644 --- a/src/systems/input.h +++ b/src/systems/input.h @@ -6,7 +6,6 @@ #include "defines.h" #include "keys.h" -struct core; struct GLFWWindow; typedef struct mouse_state { @@ -18,13 +17,13 @@ typedef struct mouse_state { bool left_btn_pressed; } mouse_state; -typedef struct input_state { +typedef struct Input_State { struct GLFWwindow *window; mouse_state mouse; bool depressed_keys[KEYCODE_MAX]; bool just_pressed_keys[KEYCODE_MAX]; bool just_released_keys[KEYCODE_MAX]; -} input_state; +} Input_State; /** @brief `key` is currently being held down */ bool key_is_pressed(keycode key); @@ -36,6 +35,8 @@ bool key_just_pressed(keycode key); bool key_just_released(keycode key); // --- Lifecycle -bool input_system_init(input_state *input, struct GLFWwindow *window); -void input_system_shutdown(input_state *input); -void input_update(input_state *state);
\ No newline at end of file + +bool Input_Init(Input_State *input, struct GLFWwindow *window); +void Input_Shutdown(Input_State *input); + +void Input_Update(Input_State *state); // must be run once per main loop diff --git a/src/systems/terrain.c b/src/systems/terrain.c index 6342d66..1d23cc3 100644 --- a/src/systems/terrain.c +++ b/src/systems/terrain.c @@ -1,24 +1,27 @@ /** - * @file terrain.c - * @author your name (you@domain.com) * @brief - * @version 0.1 - * @date 2024-06-22 - * - * @copyright Copyright (c) 2024 - * */ #include "terrain.h" #include "ral.h" -bool terrain_system_init(terrain_state* state) { - gpu_renderpass_desc rpass_desc = { - .default_framebuffer = true, - }; - struct graphics_pipeline_desc pipeline_desc = { +struct Terrain_Storage { + arena terrain_allocator; + Heightmap* heightmap; // NULL = no heightmap + GPU_Renderpass* hmap_renderpass; + GPU_Pipeline* hmap_pipeline; +}; - }; +PUB bool Terrain_Init(Terrain_Storage* storage) { return true; } +PUB void Terrain_Shutdown(Terrain_Storage* storage); - state->hmap_renderpass = gpu_renderpass_create(&rpass_desc); - state->hmap_pipeline = gpu_graphics_pipeline_create(pipeline_desc); -}
\ No newline at end of file +/* bool terrain_system_init(terrain_state* state) { */ +/* gpu_renderpass_desc rpass_desc = { */ +/* .default_framebuffer = true, */ +/* }; */ +/* struct graphics_pipeline_desc pipeline_desc = { */ + +/* }; */ + +/* state->hmap_renderpass = gpu_renderpass_create(&rpass_desc); */ +/* state->hmap_pipeline = gpu_graphics_pipeline_create(pipeline_desc); */ +/* } */ diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 888b6f4..890cb90 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -1,14 +1,10 @@ /** * @file terrain.h - * @author your name (you@domain.com) * @brief - * @version 0.1 - * @date 2024-04-27 - * - * @copyright Copyright (c) 2024 - * */ +#pragma once + /* Future: - Chunked terrain @@ -22,37 +18,37 @@ Future: #include "render.h" #include "str.h" -typedef struct heightmap { - str8 filepath; +typedef struct Heightmap { + Str8 filepath; u32x2 size; void* image_data; bool is_uploaded; -} heightmap; +} Heightmap; + +typedef struct Terrain_Storage Terrain_Storage; + +// --- Public API +PUB bool Terrain_Init(Terrain_Storage* storage); +PUB void Terrain_Shutdown(Terrain_Storage* storage); +PUB void Terrain_Run(Terrain_Storage* storage); // NOTE: For now it renders directly to main framebuffer -typedef struct terrain_state { - arena terrain_allocator; - heightmap* heightmap; // NULL = no heightmap - gpu_renderpass* hmap_renderpass; - gpu_pipeline* hmap_pipeline; -} terrain_state; +/** @brief Sets the active heightmap to be rendered and collided against. */ +PUB Heightmap Terrain_LoadHeightmap(Heightmap hmap, bool free_on_upload); +PUB Heightmap Heightmap_FromImage(Str8 filepath); +PUB Heightmap Heightmap_FromPerlin(/* TODO: perlin noise generation parameters */); -bool terrain_system_init(terrain_state* state); -void terrain_system_shutdown(terrain_state* state); -void terrain_system_render_hmap(renderer* rend, terrain_state* state); +PUB bool Terrain_IsActive(); // checks whether we have a loaded heightmap and it's being rendered -heightmap heightmap_from_image(str8 filepath); -heightmap heightmap_from_perlin(/* TODO: perlin noise generation parameters */); +// --- Internal + +// TODO: void terrain_system_render_hmap(renderer* rend, terrain_state* state); /** @brief Get the height (the Y component) for a vertex at a particular coordinate in the heightmap */ -f32 heightmap_height_at_xz(heightmap* hmap, f32 x, f32 z); +f32 Heightmap_HeightXZ(Heightmap* hmap, f32 x, f32 z); /** @brief Calculate the normal vector of a vertex at a particular coordinate in the heightmap */ -vec3 heightmap_normal_at_xz(heightmap* hmap, f32 x, f32 z); +Vec3 Heightmap_NormalXZ(Heightmap* hmap, f32 x, f32 z); /** @brief Generate the `geometry_data` for a heightmap ready to be uploaded to the GPU */ -geometry_data geo_heightmap(arena* a, heightmap heightmap); - -// somewhere there will be an easy way to add a heightmap - -// TODO: scene_add_heightmap +Geometry geo_heightmap(arena* a, Heightmap heightmap); diff --git a/src/systems/text.h b/src/systems/text.h index f40cfd6..983ffd6 100644 --- a/src/systems/text.h +++ b/src/systems/text.h @@ -10,44 +10,44 @@ #include "ral.h" #include "render_types.h" -struct core; - -/** @brief internal font struct */ -typedef struct font { - const char *name; - stbtt_fontinfo stbtt_font; - stbtt_bakedchar c_data[96]; - texture_handle bitmap_tex; -} font; - -typedef struct draw_text_packet { - char *contents; - f32 x; - f32 y; -} draw_text_packet; - -KITC_DECL_TYPED_ARRAY(draw_text_packet) - -typedef struct text_system_state { - font default_font; - shader_handle glyph_shader; - u32 glyph_vbo; - u32 glyph_vao; - draw_text_packet_darray *draw_cmd_buf; - // TODO: fonts array or hashtable -} text_system_state; - -void text_system_render(text_system_state *text); - -// --- Lifecycle functions -bool text_system_init(text_system_state *text); -void text_system_shutdown(text_system_state *text); - -// --- Drawing - -/** - * @brief immediate mode draw text. - * @note immediately emits draw calls causing a shader program switch if you weren't previously - drawing text in the current frame. -*/ -void draw_text(struct core *core, f32 x, f32 y, char *contents);
\ No newline at end of file +// struct core; + +// /** @brief internal font struct */ +// typedef struct font { +// const char *name; +// stbtt_fontinfo stbtt_font; +// stbtt_bakedchar c_data[96]; +// texture_handle bitmap_tex; +// } font; + +// typedef struct draw_text_packet { +// char *contents; +// f32 x; +// f32 y; +// } draw_text_packet; + +// KITC_DECL_TYPED_ARRAY(draw_text_packet) + +// typedef struct text_system_state { +// font default_font; +// shader_handle glyph_shader; +// u32 glyph_vbo; +// u32 glyph_vao; +// draw_text_packet_darray *draw_cmd_buf; +// // TODO: fonts array or hashtable +// } text_system_state; + +// void text_system_render(text_system_state *text); + +// // --- Lifecycle functions +// bool text_system_init(text_system_state *text); +// void text_system_shutdown(text_system_state *text); + +// // --- Drawing + +// /** +// * @brief immediate mode draw text. +// * @note immediately emits draw calls causing a shader program switch if you weren't previously +// drawing text in the current frame. +// */ +// void draw_text(struct core *core, f32 x, f32 y, char *contents); diff --git a/src/transform_hierarchy.c b/src/transform_hierarchy.c index b9795bc..a5f4d97 100644 --- a/src/transform_hierarchy.c +++ b/src/transform_hierarchy.c @@ -11,174 +11,175 @@ #include "log.h" #include "maths.h" #include "maths_types.h" - -struct transform_hierarchy { - transform_node root; -}; - -transform_hierarchy* transform_hierarchy_create() { - transform_hierarchy* tfh = malloc(sizeof(struct transform_hierarchy)); - - tfh->root = (transform_node){ .model = { ABSENT_MODEL_HANDLE }, - .tf = TRANSFORM_DEFAULT, - .local_matrix_tf = mat4_ident(), - .world_matrix_tf = mat4_ident(), - .parent = NULL, - .children = { 0 }, - .n_children = 0, - .tfh = tfh }; - return tfh; -} - -bool free_node(transform_node* node, void* _ctx_data) { - if (!node) return true; // leaf node - if (node == &node->tfh->root) { - WARN("You can't free the root node!"); - return false; - } - - printf("Freed node\n"); - free(node); - return true; -} - -void transform_hierarchy_free(transform_hierarchy* tfh) { - transform_hierarchy_dfs(&tfh->root, free_node, false, NULL); - free(tfh); -} - -transform_node* transform_hierarchy_root_node(transform_hierarchy* tfh) { return &tfh->root; } - -transform_node* transform_hierarchy_add_node(transform_node* parent, model_handle model, - transform tf) { - if (!parent) { - WARN("You tried to add a node to a bad parent (NULL?)"); - return NULL; - } - transform_node* node = malloc(sizeof(transform_node)); - node->model = model; - node->tf = tf; - node->local_matrix_tf = mat4_ident(); - node->world_matrix_tf = mat4_ident(); - node->parent = parent; - memset(node->children, 0, sizeof(node->children)); - node->n_children = 0; - node->tfh = parent->tfh; - - // push into parent's children array - u32 next_index = parent->n_children; - if (next_index == MAX_TF_NODE_CHILDREN) { - ERROR("This transform hierarchy node already has MAX children. Dropping."); - free(node); - } else { - parent->children[next_index] = node; - parent->n_children++; - } - - return node; -} - -void transform_hierarchy_delete_node(transform_node* node) { - // delete all children - for (u32 i = 0; i < node->n_children; i++) { - transform_node* child = node->children[i]; - transform_hierarchy_dfs(child, free_node, false, NULL); - } - - if (node->parent) { - for (u32 i = 0; i < node->parent->n_children; i++) { - transform_node* child = node->parent->children[i]; - if (child == node) { - node->parent->children[i] = NULL; // HACK: this will leave behind empty slots in the - // children array of the parent. oh well. - } - } - } - - free(node); -} - -void transform_hierarchy_dfs(transform_node* start_node, - bool (*visit_node)(transform_node* node, void* ctx_data), - bool is_pre_order, void* ctx_data) { - if (!start_node) return; - - bool continue_traversal = true; - if (is_pre_order) { - continue_traversal = visit_node(start_node, ctx_data); - } - - if (continue_traversal) { - for (u32 i = 0; i < start_node->n_children; i++) { - transform_node* child = start_node->children[i]; - transform_hierarchy_dfs(child, visit_node, is_pre_order, ctx_data); - } - } - - if (!is_pre_order) { - // post-order - visit_node(start_node, ctx_data); - } -} - -// Update matrix for the current node -bool update_matrix(transform_node* node, void* _ctx_data) { - if (!node) return true; // leaf node - - if (node->parent && node->parent->tf.is_dirty) { - node->tf.is_dirty = true; - } - - if (node->tf.is_dirty) { - // invalidates children - mat4 updated_local_transform = transform_to_mat(&node->tf); - node->local_matrix_tf = updated_local_transform; - if (node->parent) { - mat4 updated_world_transform = - mat4_mult(node->parent->world_matrix_tf, updated_local_transform); - node->world_matrix_tf = updated_world_transform; - } - } - - return true; -} - -void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh) { - // kickoff traversal - transform_hierarchy_dfs(&tfh->root, update_matrix, false, NULL); -} - -struct print_ctx { - core* core; - u32 indentation_lvl; -}; - -bool print_node(transform_node* node, void* ctx_data) { - struct print_ctx* ctx = (struct print_ctx*)ctx_data; - - if (!node) return true; - if (!node->parent) { - printf("Root Node\n"); - ctx->indentation_lvl++; - return true; - } - - // Grab the model - // FIXME - // model m = ctx->core->models->data[node->model.raw]; - for (int i = 0; i < ctx->indentation_lvl; i++) { - printf(" "); - } - // printf("Node %s\n", m.name.buf); - ctx->indentation_lvl++; - - return true; -} - -void transform_hierarchy_debug_print(transform_node* start_node, core* core) { - struct print_ctx* ctx = malloc(sizeof(struct print_ctx)); - ctx->core = core; - ctx->indentation_lvl = 0; - transform_hierarchy_dfs(start_node, print_node, true, (void*)ctx); - free(ctx); -}
\ No newline at end of file +#include "render_types.h" + +// struct transform_hierarchy { +// transform_node root; +// }; + +// transform_hierarchy* transform_hierarchy_create() { +// transform_hierarchy* tfh = malloc(sizeof(struct transform_hierarchy)); + +// tfh->root = (transform_node){ .model = { ABSENT_MODEL_HANDLE }, +// .tf = TRANSFORM_DEFAULT, +// .local_matrix_tf = mat4_ident(), +// .world_matrix_tf = mat4_ident(), +// .parent = NULL, +// .children = { 0 }, +// .n_children = 0, +// .tfh = tfh }; +// return tfh; +// } + +// bool free_node(transform_node* node, void* _ctx_data) { +// if (!node) return true; // leaf node +// if (node == &node->tfh->root) { +// WARN("You can't free the root node!"); +// return false; +// } + +// printf("Freed node\n"); +// free(node); +// return true; +// } + +// void transform_hierarchy_free(transform_hierarchy* tfh) { +// transform_hierarchy_dfs(&tfh->root, free_node, false, NULL); +// free(tfh); +// } + +// transform_node* transform_hierarchy_root_node(transform_hierarchy* tfh) { return &tfh->root; } + +// transform_node* transform_hierarchy_add_node(transform_node* parent, ModelHandle model, +// Transform tf) { +// if (!parent) { +// WARN("You tried to add a node to a bad parent (NULL?)"); +// return NULL; +// } +// transform_node* node = malloc(sizeof(transform_node)); +// node->model = model; +// node->tf = tf; +// node->local_matrix_tf = mat4_ident(); +// node->world_matrix_tf = mat4_ident(); +// node->parent = parent; +// memset(node->children, 0, sizeof(node->children)); +// node->n_children = 0; +// node->tfh = parent->tfh; + +// // push into parent's children array +// u32 next_index = parent->n_children; +// if (next_index == MAX_TF_NODE_CHILDREN) { +// ERROR("This transform hierarchy node already has MAX children. Dropping."); +// free(node); +// } else { +// parent->children[next_index] = node; +// parent->n_children++; +// } + +// return node; +// } + +// void transform_hierarchy_delete_node(transform_node* node) { +// // delete all children +// for (u32 i = 0; i < node->n_children; i++) { +// transform_node* child = node->children[i]; +// transform_hierarchy_dfs(child, free_node, false, NULL); +// } + +// if (node->parent) { +// for (u32 i = 0; i < node->parent->n_children; i++) { +// transform_node* child = node->parent->children[i]; +// if (child == node) { +// node->parent->children[i] = NULL; // HACK: this will leave behind empty slots in the +// // children array of the parent. oh well. +// } +// } +// } + +// free(node); +// } + +// void transform_hierarchy_dfs(transform_node* start_node, +// bool (*visit_node)(transform_node* node, void* ctx_data), +// bool is_pre_order, void* ctx_data) { +// if (!start_node) return; + +// bool continue_traversal = true; +// if (is_pre_order) { +// continue_traversal = visit_node(start_node, ctx_data); +// } + +// if (continue_traversal) { +// for (u32 i = 0; i < start_node->n_children; i++) { +// transform_node* child = start_node->children[i]; +// transform_hierarchy_dfs(child, visit_node, is_pre_order, ctx_data); +// } +// } + +// if (!is_pre_order) { +// // post-order +// visit_node(start_node, ctx_data); +// } +// } + +// // Update matrix for the current node +// bool update_matrix(transform_node* node, void* _ctx_data) { +// if (!node) return true; // leaf node + +// if (node->parent && node->parent->tf.is_dirty) { +// node->tf.is_dirty = true; +// } + +// if (node->tf.is_dirty) { +// // invalidates children +// Mat4 updated_local_transform = transform_to_mat(&node->tf); +// node->local_matrix_tf = updated_local_transform; +// if (node->parent) { +// Mat4 updated_world_transform = +// mat4_mult(node->parent->world_matrix_tf, updated_local_transform); +// node->world_matrix_tf = updated_world_transform; +// } +// } + +// return true; +// } + +// void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh) { +// // kickoff traversal +// transform_hierarchy_dfs(&tfh->root, update_matrix, false, NULL); +// } + +// struct print_ctx { +// Core* core; +// u32 indentation_lvl; +// }; + +// bool print_node(transform_node* node, void* ctx_data) { +// struct print_ctx* ctx = (struct print_ctx*)ctx_data; + +// if (!node) return true; +// if (!node->parent) { +// printf("Root Node\n"); +// ctx->indentation_lvl++; +// return true; +// } + +// // Grab the model +// // FIXME +// // model m = ctx->core->models->data[node->model.raw]; +// for (int i = 0; i < ctx->indentation_lvl; i++) { +// printf(" "); +// } +// // printf("Node %s\n", m.name.buf); +// ctx->indentation_lvl++; + +// return true; +// } + +// void transform_hierarchy_debug_print(transform_node* start_node, Core* core) { +// struct print_ctx* ctx = malloc(sizeof(struct print_ctx)); +// ctx->core = core; +// ctx->indentation_lvl = 0; +// transform_hierarchy_dfs(start_node, print_node, true, (void*)ctx); +// free(ctx); +// } diff --git a/src/transform_hierarchy.h b/src/transform_hierarchy.h index 0921c19..808baab 100644 --- a/src/transform_hierarchy.h +++ b/src/transform_hierarchy.h @@ -10,68 +10,69 @@ #define MAX_TF_NODE_CHILDREN \ 32 /** TEMP: Make it simpler to manage children in `transform_node`s */ -typedef struct transform_hierarchy transform_hierarchy; +typedef struct TransformHierarchy TransformHierarchy; -struct transform_node { - model_handle model; /** A handle back to what model this node represents */ - transform tf; - mat4 local_matrix_tf; /** cached local affine transform */ - mat4 world_matrix_tf; /** cached world-space affine transform */ +struct Transform_Node { + ModelHandle model; /** A handle back to what model this node represents */ + Transform tf; + Mat4 local_matrix_tf; /** cached local affine transform */ + Mat4 world_matrix_tf; /** cached world-space affine transform */ struct transform_node* parent; struct transform_node* children[MAX_TF_NODE_CHILDREN]; u32 n_children; struct transform_hierarchy* tfh; }; -typedef struct transform_node transform_node; +typedef struct Transform_Node Transform_Node; +typedef struct Transform_Node TF_Node; // --- Lifecycle /** @brief Allocates and returns an empty transform hierarchy with a root node */ -transform_hierarchy* transform_hierarchy_create(); - -/** - * @brief recursively frees all the children and then finally itself - * @note in the future we can use an object pool for the nodes - */ -void transform_hierarchy_free(transform_hierarchy* tfh); - -// --- Main usecase - -/** @brief Updates matrices of any invalidated nodes based on the `is_dirty` flag inside `transform` - */ -void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh); - -// --- Queries - -/** @brief Get a pointer to the root node */ -transform_node* transform_hierarchy_root_node(transform_hierarchy* tfh); - -// --- Mutations -transform_node* transform_hierarchy_add_node(transform_node* parent, model_handle model, - transform tf); -void transform_hierarchy_delete_node(transform_node* node); - -// --- Traversal - -/** - * @brief Perform a depth-first search traversal starting from `start_node`. - * @param start_node The starting node of the traversal. - * @param visit_node The function to call for each node visited. The callback should return false to - stop the traversal early. - * @param is_pre_order Indicates whether to do pre-order or post-order traversal i.e. when to call - the `visit_node` function. - * @param ctx_data An optional pointer to data that is be passed on each call to `visit_node`. Can - be used to carry additional information or context. - * - * @note The main use-cases are: - 1. traversing the whole tree to update cached 4x4 affine transform matrices (post-order) - 2. freeing child nodes after deleting a node in the tree (post-order) - 3. debug pretty printing the whole tree (post-order) - */ -void transform_hierarchy_dfs(transform_node* start_node, - bool (*visit_node)(transform_node* node, void* ctx_data), - bool is_pre_order, void* ctx_data); - -struct core; -void transform_hierarchy_debug_print(transform_node* start_node, struct core* core);
\ No newline at end of file +TransformHierarchy* TransformHierarchy_Create(); + +// /** +// * @brief recursively frees all the children and then finally itself +// * @note in the future we can use an object pool for the nodes +// */ +// void transform_hierarchy_free(transform_hierarchy* tfh); + +// // --- Main usecase + +// /** @brief Updates matrices of any invalidated nodes based on the `is_dirty` flag inside `transform` +// */ +// void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh); + +// // --- Queries + +// /** @brief Get a pointer to the root node */ +// Transform_Node* TransformHierarchy_RootNode(TransformHierarchy* tfh); + +// // --- Mutations +// Transform_Node* TransformHierarchy_AddNode(transform_node* parent, ModelHandle model, +// Transform tf); +// void transform_hierarchy_delete_node(transform_node* node); + +// // --- Traversal + +// /** +// * @brief Perform a depth-first search traversal starting from `start_node`. +// * @param start_node The starting node of the traversal. +// * @param visit_node The function to call for each node visited. The callback should return false to +// stop the traversal early. +// * @param is_pre_order Indicates whether to do pre-order or post-order traversal i.e. when to call +// the `visit_node` function. +// * @param ctx_data An optional pointer to data that is be passed on each call to `visit_node`. Can +// be used to carry additional information or context. +// * +// * @note The main use-cases are: +// 1. traversing the whole tree to update cached 4x4 affine transform matrices (post-order) +// 2. freeing child nodes after deleting a node in the tree (post-order) +// 3. debug pretty printing the whole tree (post-order) +// */ +// void transform_hierarchy_dfs(transform_node* start_node, +// bool (*visit_node)(transform_node* node, void* ctx_data), +// bool is_pre_order, void* ctx_data); + +// struct Core; +// void transform_hierarchy_debug_print(transform_node* start_node, struct Core* core); diff --git a/src/ui/ui.h b/src/ui/ui.h new file mode 100644 index 0000000..c5ace97 --- /dev/null +++ b/src/ui/ui.h @@ -0,0 +1,13 @@ +/** + * @brief + */ + +#pragma once +#include "defines.h" + +typedef struct UI_Storage UI_Storage; + +PUB bool UI_Init(UI_Storage* storage); +PUB void UI_Shutdown(UI_Storage* storage); + +// TODO: define immui api @@ -24,31 +24,31 @@ if is_plat("linux") then elseif is_plat("windows") then add_defines("CEL_PLATFORM_WINDOWS") add_syslinks("user32", "gdi32", "kernel32", "shell32") - add_requires("vulkansdk", {system=true}) + add_requires("vulkansdk", { system = true }) -- add_links("pthreadVC2-w64") elseif is_plat("macosx") then add_defines("CEL_PLATFORM_MAC") add_frameworks("Cocoa", "IOKit", "CoreVideo", "OpenGL") - add_frameworks( "Foundation", "Metal", "QuartzCore") + add_frameworks("Foundation", "Metal", "QuartzCore") set_runenv("MTL_DEBUG_LAYER", "1") -- add_syslinks("GL") end -- Compile GLFW from source package("local_glfw") - add_deps("cmake") - set_sourcedir(path.join(os.scriptdir(), "deps/glfw-3.3.8")) - on_install(function (package) - local configs = {} - -- NOTE(omni): Keeping these around as comments in case we need to modify glfw flags - -- table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) - -- table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF")) - import("package.tools.cmake").install(package, configs) - end) - on_test(function (package) - -- assert(package:has_cfuncs("add", {includes = "foo.h"})) - end) +add_deps("cmake") +set_sourcedir(path.join(os.scriptdir(), "deps/glfw-3.3.8")) +on_install(function(package) + local configs = {} + -- NOTE(omni): Keeping these around as comments in case we need to modify glfw flags + -- table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) + -- table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF")) + import("package.tools.cmake").install(package, configs) +end) +on_test(function(package) + -- assert(package:has_cfuncs("add", {includes = "foo.h"})) +end) package_end() add_requires("local_glfw") @@ -56,13 +56,17 @@ add_requires("local_glfw") local core_sources = { "deps/glad/src/glad.c", "src/*.c", + "src/core/*.c", -- "src/logos/*.c", "src/maths/*.c", "src/platform/*.c", "src/physics/*.c", - "src/renderer/*.c", - "src/renderer/backends/*.c", - "src/renderer/backends/opengl/*.c", + "src/ral/*.c", + -- "src/ral/backends/opengl/*.c", + "src/new_render/*.c", + -- "src/renderer/*.c", + -- "src/renderer/backends/*.c", + -- "src/renderer/backends/opengl/*.c", "src/resources/*.c", "src/std/*.c", "src/std/containers/*.c", @@ -76,88 +80,92 @@ local unity_sources = { } rule("compile_glsl_vert_shaders") - set_extensions(".vert") - on_buildcmd_file(function (target, batchcmds, sourcefile, opt) - local targetfile = path.join(target:targetdir(), path.basename(sourcefile) .. ".vert.spv") - - print("Compiling shader: %s to %s", sourcefile, targetfile) - batchcmds:vrunv('glslc', {sourcefile, "-o", targetfile}) - -- batchcmds:add_depfiles(sourcefile) +set_extensions(".vert") +on_buildcmd_file(function(target, batchcmds, sourcefile, opt) + local targetfile = path.join(target:targetdir(), path.basename(sourcefile) .. ".vert.spv") + + print("Compiling shader: %s to %s", sourcefile, targetfile) + batchcmds:vrunv('glslc', { sourcefile, "-o", targetfile }) + -- batchcmds:add_depfiles(sourcefile) end) rule("compile_glsl_frag_shaders") - set_extensions(".frag") - on_buildcmd_file(function (target, batchcmds, sourcefile, opt) - local targetfile = path.join(target:targetdir(), path.basename(sourcefile) .. ".frag.spv") - - print("Compiling shader: %s to %s", sourcefile, targetfile) - batchcmds:vrunv('glslc', {sourcefile, "-o", targetfile}) - -- batchcmds:add_depfiles(sourcefile) +set_extensions(".frag") +on_buildcmd_file(function(target, batchcmds, sourcefile, opt) + local targetfile = path.join(target:targetdir(), path.basename(sourcefile) .. ".frag.spv") + + print("Compiling shader: %s to %s", sourcefile, targetfile) + batchcmds:vrunv('glslc', { sourcefile, "-o", targetfile }) + -- batchcmds:add_depfiles(sourcefile) end) -- TODO: Metal shaders compilation -- common configuration for both static and shared libraries target("core_config") - set_kind("static") -- kind is required but you can ignore it since it's just for common settings - add_packages("local_glfw") - add_defines("CEL_REND_BACKEND_OPENGL") - add_includedirs("deps/cgltf", {public = true}) - add_includedirs("deps/glfw-3.3.8/include/GLFW", {public = true}) - add_includedirs("deps/glad/include", {public = true}) - add_includedirs("deps/stb_image", {public = true}) - add_includedirs("deps/stb_image_write", {public = true}) - add_includedirs("deps/stb_truetype", {public = true}) - add_includedirs("include/", {public = true}) - add_includedirs("src/", {public = true}) - -- add_includedirs("src/logos/", {public = true}) - add_includedirs("src/maths/", {public = true}) - add_includedirs("src/platform/", {public = true}) - add_includedirs("src/physics/", {public = true}) - add_includedirs("src/renderer/", {public = true}) - add_includedirs("src/renderer/backends/", {public = true}) - add_includedirs("src/renderer/backends/opengl", {public = true}) - add_includedirs("src/renderer/backends/metal", {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}) - add_files("src/empty.c") -- for some reason we need this on Mac so it doesnt call 'ar' with no files and error - -- add_rules("compile_glsl_vert_shaders") - -- add_rules("compile_glsl_frag_shaders") - -- add_files("assets/shaders/triangle.vert") - -- add_files("assets/shaders/triangle.frag") - -- add_files("assets/shaders/cube.vert") - -- add_files("assets/shaders/cube.frag") - -- add_files("assets/shaders/*.frag") - if is_plat("windows") then - add_includedirs("$(env VULKAN_SDK)/Include", {public = true}) - add_linkdirs("$(env VULKAN_SDK)/Lib", {public = true}) - add_links("vulkan-1") - end - if is_plat("macosx") then - add_files("src/renderer/backends/metal/*.m") - end - set_default(false) -- prevents standalone building of this target +set_kind("static") -- kind is required but you can ignore it since it's just for common settings +add_packages("local_glfw") +add_defines("CEL_REND_BACKEND_OPENGL") +add_includedirs("deps/cgltf", { public = true }) +add_includedirs("deps/glfw-3.3.8/include/GLFW", { public = true }) +add_includedirs("deps/glad/include", { public = true }) +add_includedirs("deps/stb_image", { public = true }) +add_includedirs("deps/stb_image_write", { public = true }) +add_includedirs("deps/stb_truetype", { public = true }) +add_includedirs("include/", { public = true }) +add_includedirs("src/", { public = true }) +add_includedirs("src/core", { public = true }) +-- add_includedirs("src/logos/", {public = true}) +add_includedirs("src/maths/", { public = true }) +add_includedirs("src/platform/", { public = true }) +add_includedirs("src/physics/", { public = true }) +add_includedirs("src/ral", { public = true }) +add_includedirs("src/ral/backends/opengl", { public = true }) +add_includedirs("src/new_render", { public = true }) +-- add_includedirs("src/renderer/", {public = true}) +-- add_includedirs("src/renderer/backends/", {public = true}) +-- add_includedirs("src/renderer/backends/opengl", {public = true}) +-- add_includedirs("src/renderer/backends/metal", {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 }) +add_files("src/empty.c") -- for some reason we need this on Mac so it doesnt call 'ar' with no files and error +-- add_rules("compile_glsl_vert_shaders") +-- add_rules("compile_glsl_frag_shaders") +-- add_files("assets/shaders/triangle.vert") +-- add_files("assets/shaders/triangle.frag") +-- add_files("assets/shaders/cube.vert") +-- add_files("assets/shaders/cube.frag") +-- add_files("assets/shaders/*.frag") +if is_plat("windows") then + add_includedirs("$(env VULKAN_SDK)/Include", { public = true }) + add_linkdirs("$(env VULKAN_SDK)/Lib", { public = true }) + add_links("vulkan-1") +end +if is_plat("macosx") then + add_files("src/renderer/backends/metal/*.m") +end +set_default(false) -- prevents standalone building of this target target("core_static") - set_kind("static") - add_deps("core_config") -- inherit common configurations - set_policy("build.merge_archive", true) - add_files(core_sources) - -- Link against static CRT - if is_plat("windows") then - add_links("libcmt", "legacy_stdio_definitions") -- for release builds - add_links("libcmtd", "legacy_stdio_definitions") -- for debug builds - end +set_kind("static") +add_deps("core_config") -- inherit common configurations +set_policy("build.merge_archive", true) +add_files(core_sources) +-- Link against static CRT +if is_plat("windows") then + add_links("libcmt", "legacy_stdio_definitions") -- for release builds + add_links("libcmtd", "legacy_stdio_definitions") -- for debug builds +end target("core_shared") - set_kind("shared") - add_deps("core_config") -- inherit common configurations - add_files(core_sources) - -- Link against dynamic CRT - if is_plat("windows") then - add_links("msvcrt", "legacy_stdio_definitions") -- for release builds - add_links("msvcrtd", "legacy_stdio_definitions") -- for debug builds - end +set_kind("shared") +add_deps("core_config") -- inherit common configurations +add_files(core_sources) +-- Link against dynamic CRT +if is_plat("windows") then + add_links("msvcrt", "legacy_stdio_definitions") -- for release builds + add_links("msvcrtd", "legacy_stdio_definitions") -- for debug builds +end -- target("main_loop") -- set_kind("binary") @@ -166,84 +174,84 @@ target("core_shared") -- add_files("examples/main_loop/ex_main_loop.c") -- set_rundir("$(projectdir)") -target("tri") - set_kind("binary") - set_group("examples") - add_deps("core_static") - add_files("examples/triangle/ex_triangle.c") - set_rundir("$(projectdir)") - if is_plat("macosx") then - before_build(function (target) - print("build metal shaders lib") - os.exec("mkdir -p build/shaders") - os.exec("xcrun -sdk macosx metal -c assets/shaders/triangle.metal -o build/shaders/gfx.air") - os.exec("xcrun -sdk macosx metallib build/shaders/gfx.air -o build/gfx.metallib") - end) - end - -target("cube") - set_kind("binary") - set_group("examples") - -- add_defines("CEL_REND_BACKEND_OPENGL") - add_deps("core_static") - add_files("examples/cube/ex_cube.c") - set_rundir("$(projectdir)") - -target("primitives") - set_kind("binary") - set_group("examples") - add_deps("core_static") - add_files("examples/primitives/ex_primitives.c") - set_rundir("$(projectdir)") - --- target("std") +-- target("tri") -- set_kind("binary") -- set_group("examples") -- add_deps("core_static") --- add_files("examples/standard_lib/ex_std.c") +-- add_files("examples/triangle/ex_triangle.c") -- set_rundir("$(projectdir)") +-- if is_plat("macosx") then +-- before_build(function (target) +-- print("build metal shaders lib") +-- os.exec("mkdir -p build/shaders") +-- os.exec("xcrun -sdk macosx metal -c assets/shaders/triangle.metal -o build/shaders/gfx.air") +-- os.exec("xcrun -sdk macosx metallib build/shaders/gfx.air -o build/gfx.metallib") +-- end) +-- end --- target("obj") +-- target("cube") -- set_kind("binary") -- set_group("examples") +-- -- add_defines("CEL_REND_BACKEND_OPENGL") -- add_deps("core_static") --- add_files("examples/obj_loading/ex_obj_loading.c") +-- add_files("examples/cube/ex_cube.c") -- set_rundir("$(projectdir)") --- target("input") +-- target("primitives") -- set_kind("binary") -- set_group("examples") -- add_deps("core_static") --- add_files("examples/input/ex_input.c") +-- add_files("examples/primitives/ex_primitives.c") -- set_rundir("$(projectdir)") -target("gltf") - set_kind("binary") - set_group("examples") - add_deps("core_static") - add_files("examples/gltf_loading/ex_gltf_loading.c") - set_rundir("$(projectdir)") - -target("pbr_params") - set_kind("binary") - set_group("examples") - add_deps("core_static") - add_files("examples/pbr_params/ex_pbr_params.c") - set_rundir("$(projectdir)") - -target("pbr_textured") - set_kind("binary") - set_group("examples") - add_deps("core_static") - add_files("examples/pbr_textured/ex_pbr_textured.c") - set_rundir("$(projectdir)") - -target("shadows") - set_kind("binary") - set_group("examples") - add_deps("core_static") - add_files("examples/shadow_maps/ex_shadow_maps.c") - set_rundir("$(projectdir)") +-- -- target("std") +-- -- set_kind("binary") +-- -- set_group("examples") +-- -- add_deps("core_static") +-- -- add_files("examples/standard_lib/ex_std.c") +-- -- set_rundir("$(projectdir)") + +-- -- target("obj") +-- -- set_kind("binary") +-- -- set_group("examples") +-- -- add_deps("core_static") +-- -- add_files("examples/obj_loading/ex_obj_loading.c") +-- -- set_rundir("$(projectdir)") + +-- -- target("input") +-- -- set_kind("binary") +-- -- set_group("examples") +-- -- add_deps("core_static") +-- -- add_files("examples/input/ex_input.c") +-- -- set_rundir("$(projectdir)") + +-- target("gltf") +-- set_kind("binary") +-- set_group("examples") +-- add_deps("core_static") +-- add_files("examples/gltf_loading/ex_gltf_loading.c") +-- set_rundir("$(projectdir)") + +-- target("pbr_params") +-- set_kind("binary") +-- set_group("examples") +-- add_deps("core_static") +-- add_files("examples/pbr_params/ex_pbr_params.c") +-- set_rundir("$(projectdir)") + +-- target("pbr_textured") +-- set_kind("binary") +-- set_group("examples") +-- add_deps("core_static") +-- add_files("examples/pbr_textured/ex_pbr_textured.c") +-- set_rundir("$(projectdir)") + +-- target("shadows") +-- set_kind("binary") +-- set_group("examples") +-- add_deps("core_static") +-- add_files("examples/shadow_maps/ex_shadow_maps.c") +-- set_rundir("$(projectdir)") -- target("transforms") -- set_kind("binary") @@ -280,13 +288,20 @@ target("shadows") -- add_files("examples/demo/demo.c") -- set_rundir("$(projectdir)") -target("pool_tests") - set_kind("binary") - set_group("tests") - add_deps("core_static") - add_files(unity_sources) - add_includedirs("deps/Unity/src", {public = true}) - add_includedirs("deps/Unity/extras/fixture/src", {public = true}) - add_includedirs("deps/Unity/extras/memory/src", {public = true}) - add_files("tests/pool_tests.c") - add_files("tests/pool_test_runner.c") +target("game") +set_kind("binary") +set_group("examples") +add_deps("core_static") +add_files("examples/game_demo/game_demo.c") +set_rundir("$(projectdir)") + +-- target("pool_tests") +-- set_kind("binary") +-- set_group("tests") +-- add_deps("core_static") +-- add_files(unity_sources) +-- add_includedirs("deps/Unity/src", {public = true}) +-- add_includedirs("deps/Unity/extras/fixture/src", {public = true}) +-- add_includedirs("deps/Unity/extras/memory/src", {public = true}) +-- add_files("tests/pool_tests.c") +-- add_files("tests/pool_test_runner.c") |