diff options
author | omnisci3nce <omniscient.oce@gmail.com> | 2024-07-12 12:47:07 +1000 |
---|---|---|
committer | omnisci3nce <omniscient.oce@gmail.com> | 2024-07-12 12:47:07 +1000 |
commit | f74cf52946f4e569a26bc81105537b40be95c2c7 (patch) | |
tree | 1d000367350d0e28eb7cfbc800286a0ed30a4e6c | |
parent | fedba7ff68924ff50022405fc9103a5acf7013fe (diff) |
wip: big makeover
42 files changed, 1130 insertions, 943 deletions
diff --git a/examples/game_demo/game_demo.c b/examples/game_demo/game_demo.c new file mode 100644 index 0000000..5e76ced --- /dev/null +++ b/examples/game_demo/game_demo.c @@ -0,0 +1,70 @@ +// 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 }; + while (!ShouldExit()) { + Frame_Begin(); + + // BEGIN Draw calls + + // draw the player model with shadows + + Render_DrawTerrain(); + Skybox_Draw(&skybox); + + // END Draw calls + Frame_Draw(); + Frame_End(); + } + + Core_Shutdown(); + return 0; +} 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/core/camera.c b/src/core/camera.c index 50c4054..428a50d 100644 --- a/src/core/camera.c +++ b/src/core/camera.c @@ -2,16 +2,15 @@ #include "maths.h" -Camera Camera_Create(vec3 pos, vec3 front, vec3 up, f32 fov) { +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); +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; } diff --git a/src/core/camera.h b/src/core/camera.h index 233f5f3..bacbca9 100644 --- a/src/core/camera.h +++ b/src/core/camera.h @@ -8,14 +8,14 @@ #include "maths_types.h" typedef struct Camera { - vec3 position; - vec3 front; - vec3 up; + Vec3 position; + Vec3 front; + Vec3 up; f32 fov; } Camera; /** @brief create a camera */ -Camera Camera_Create(vec3 pos, vec3 front, vec3 up, f32 fov); +Camera Camera_Create(Vec3 pos, Vec3 front, Vec3 up, f32 fov); /** * @brief Get 3D camera transform matrix @@ -23,10 +23,10 @@ Camera Camera_Create(vec3 pos, vec3 front, vec3 up, f32 fov); * @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); +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 +PUB Mat4 Camera_View2D(Camera* c); // TODO: 2D cameras // TODO: Basic reusable camera controls diff --git a/src/core/core.c b/src/core/core.c index a022366..602d35c 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -11,37 +11,35 @@ #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; - Renderer renderer; - input_state input; - model_pool models; + GLFWwindow* window; + Renderer* renderer; + Input_State input; }; /** @brief Gets the global `Core` singleton */ inline Core* GetCore() { return &g_core; } -void core_bringup() { +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 } }; - - g_core.renderer.backend_context = NULL; + .scr_width = SCR_WIDTH, + .scr_height = SCR_HEIGHT, + .clear_colour = (Vec3){ .08, .08, .1 } }; // initialise all subsystems - if (!Renderer_Init(conf, &g_core.renderer)) { + 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.renderer.window)) { + 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"); @@ -50,34 +48,28 @@ void core_bringup() { 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"); + // 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); + // 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); +void Core_Shutdown() { + Input_Shutdown(&g_core.input); + Renderer_Shutdown(g_core.renderer); } -bool should_exit() { - return key_just_released(KEYCODE_ESCAPE) || glfwWindowShouldClose(g_core.renderer.window); +bool ShouldExit() { + return key_just_released(KEYCODE_ESCAPE) || glfwWindowShouldClose(g_core.window); } -void frame_begin() { +void Frame_Begin() { glfwPollEvents(); - render_frame_begin(&g_core.renderer); + Render_FrameBegin(g_core.renderer); } -void frame_draw() {} -void frame_end() { render_frame_end(&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 index 469f8d1..7916143 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -9,18 +9,13 @@ typedef struct Core Core; - -core* get_global_core(); - -// --- Lifecycle +Core* get_global_core(); /** @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_Bringup(); +void Core_Shutdown(); +bool ShouldExit(); -void core_input_update(); +void Frame_Begin(); +void Frame_Draw(); +void Frame_End(); diff --git a/src/defines.h b/src/defines.h index e0a7782..1f0eae7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -53,21 +53,6 @@ CORE_DEFINE_HANDLE(Handle); // Untyped handle that can be casted to a strongly t #define PUB // For collecting public APIs to expose in an amalgamation header file -/* -Possible platform defines: -#define CEL_PLATFORM_LINUX 1 -#define CEL_PLATFORM_WINDOWS 1 -#define CEL_PLATFORM_MAC 1 -#define CEL_PLATFORM_HEADLESS 1 -*/ - -/* -Renderer backend defines: -#define CEL_REND_BACKEND_OPENGL 1 -#define CEL_REND_BACKEND_VULKAN 1 -#define CEL_REND_BACKEND_METAL 1 -*/ - // NOTE: The below is now handled in xmake.lua // Platform will inform renderer backend (unless user overrides) #if defined(CEL_PLATFORM_LINUX) @@ -76,8 +61,9 @@ 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) 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 5bfc43c..f256a9b 100644 --- a/src/maths/maths_types.h +++ b/src/maths/maths_types.h @@ -40,10 +40,9 @@ typedef struct Vec4 { typedef Vec4 Quat; /** @brief 4x4 Matrix */ -typedef union Mat4 { +typedef struct Mat4 { // TODO: use this format for more readable code: vec4 x_axis, y_axis, z_axis, w_axis; f32 data[16]; - Vec4 cols[4]; } Mat4; /** @brief Three dimensional bounding box */ 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/pbr.h b/src/new_render/pbr.h index dd29301..7573563 100644 --- a/src/new_render/pbr.h +++ b/src/new_render/pbr.h @@ -44,6 +44,8 @@ typedef struct PBR_Textures { // --- Internal +typedef struct MaterialMap MaterialMap; +typedef struct RenderEnt RenderEnt; GPU_Renderpass* PBR_RPassCreate(); GPU_Pipeline* PBR_PipelineCreate(GPU_Renderpass* rpass); diff --git a/src/new_render/render.c b/src/new_render/render.c index 455b730..f5547d5 100644 --- a/src/new_render/render.c +++ b/src/new_render/render.c @@ -4,34 +4,31 @@ #include "render.h" #include "maths_types.h" -#include "shadow.h" - -struct RendererConfig { - char window_name[256]; - u32 scr_width, scr_height; - Vec3 clear_colour; -}; +#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; - ResourcePools* resource_pools; + 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 + // set the RAL backend up - // create our renderpasses - Shadow_Init(&renderer->shadows); + // create our renderpasses + Shadow_Init(renderer->shadows); - return true; + return true; } diff --git a/src/new_render/render.h b/src/new_render/render.h index 93b2366..7c6a4a5 100644 --- a/src/new_render/render.h +++ b/src/new_render/render.h @@ -4,9 +4,47 @@ #pragma once #include "defines.h" +#include "maths_types.h" +#include "ral_types.h" +#include "render_types.h" typedef struct Renderer Renderer; -typedef struct RendererConfig RendererConfig; +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); +PUB void Render_FrameDraw(Renderer* renderer); + +// --- 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_types.h b/src/new_render/render_types.h index 63c472e..384a18f 100644 --- a/src/new_render/render_types.h +++ b/src/new_render/render_types.h @@ -7,6 +7,11 @@ #include "defines.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; @@ -27,6 +32,11 @@ typedef struct Mesh { 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, @@ -46,6 +56,8 @@ typedef struct Model { // materials } Model; +// TODO: function to create a model from a single mesh (like when using primitives) + // --- Lights typedef struct PointLight { Vec3 position; @@ -61,3 +73,12 @@ typedef struct DirectionalLight { Vec3 diffuse; Vec3 specular; } DirectionalLight; + +// --- + +// A renderable 'thing' +typedef struct RenderEnt { + ModelHandle model; + Mat4 affine; + bool casts_shadows; +} RenderEnt; diff --git a/src/new_render/shadows.h b/src/new_render/shadows.h index fd1c45d..82ded5c 100644 --- a/src/new_render/shadows.h +++ b/src/new_render/shadows.h @@ -5,11 +5,11 @@ #pragma once #include "defines.h" -#include "ral/ral_types.h" +#include "ral.h" +#include "render_types.h" typedef struct Shadow_Storage Shadow_Storage; -typedef struct RenderEnt RenderEnt; typedef struct Camera Camera; typedef struct Mat4 Mat4; diff --git a/src/new_render/skybox.h b/src/new_render/skybox.h index 10ec4f9..9bdc2ec 100644 --- a/src/new_render/skybox.h +++ b/src/new_render/skybox.h @@ -3,4 +3,30 @@ */ #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/ral/backends/opengl/backend_opengl.h b/src/ral/backends/opengl/backend_opengl.h index e69de29..22162f3 100644 --- a/src/ral/backends/opengl/backend_opengl.h +++ 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/ral_common.c b/src/ral/ral_common.c index 755b489..89d475b 100644 --- a/src/ral/ral_common.c +++ b/src/ral/ral_common.c @@ -1,19 +1,19 @@ #include "ral_common.h" #include "ral_impl.h" -void backend_pools_init(arena* a, gpu_backend_pools* backend_pools) { - pipeline_layout_pool pipeline_layout_pool = - pipeline_layout_pool_create(a, MAX_PIPELINES, sizeof(gpu_pipeline_layout)); +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)); + 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)); + 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 resource_pools* res_pools) { - buffer_pool buf_pool = buffer_pool_create(a, MAX_BUFFERS, sizeof(gpu_buffer)); +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)); + Texture_pool tex_pool = Texture_pool_create(a, MAX_TEXTURES, sizeof(GPU_Texture)); res_pools->textures = tex_pool; -}
\ No newline at end of file +} diff --git a/src/ral/ral_common.h b/src/ral/ral_common.h index fabf264..1088404 100644 --- a/src/ral/ral_common.h +++ b/src/ral/ral_common.h @@ -1,46 +1,39 @@ #pragma once #include "defines.h" +#include "buf.h" #include "mem.h" #include "ral_types.h" #include "ral_impl.h" -CORE_DEFINE_HANDLE(BufferHandle); -CORE_DEFINE_HANDLE(TextureHandle); -CORE_DEFINE_HANDLE(SamplerHandle); -CORE_DEFINE_HANDLE(ShaderHandle); - -CORE_DEFINE_HANDLE(pipeline_layout_handle); -CORE_DEFINE_HANDLE(pipeline_handle); -CORE_DEFINE_HANDLE(renderpass_handle); - -#define MAX_SHADER_DATA_LAYOUTS 8 -#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_pipeline_layout, pipeline_layout); -TYPED_POOL(gpu_pipeline, pipeline); -TYPED_POOL(gpu_renderpass, renderpass); +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_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; +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 resource_pools* res_pools); +void resource_pools_init(arena* a, struct ResourcePools* res_pools); + + +// --- Vertex formats +bytebuffer vertices_as_bytebuffer(arena* a, VertexFormat format, Vertex_darray* vertices); -// vertex_description static_3d_vertex_description(); +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 index 8edf211..4d1c17a 100644 --- a/src/ral/ral_impl.h +++ b/src/ral/ral_impl.h @@ -1,22 +1,38 @@ +/** + * @brief +*/ #pragma once #include "defines.h" #include "ral_types.h" struct GLFWwindow; -bool gpu_backend_init(const char* window_name, struct GLFWwindow* window); -void gpu_backend_shutdown(); +// 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_device_create(gpu_device* out_device); -void gpu_device_destroy(gpu_device* device); +bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window); +void GPU_Backend_Shutdown(); -gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description); -void gpu_pipeline_destroy(gpu_pipeline* pipeline); +bool GPU_Device_Create(GPU_Device* out_device); +void GPU_Device_Destroy(GPU_Device* device); -// --- Renderpass -gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description); -void gpu_renderpass_destroy(gpu_renderpass* pass); +bool GPU_Swapchain_Create(GPU_Swapchain* out_swapchain); +void GPU_Swapchain_Destroy(GPU_Swapchain* swapchain); -// --- Swapchain -bool gpu_swapchain_create(gpu_swapchain* out_swapchain); -void gpu_swapchain_destroy(gpu_swapchain* swapchain);
\ No newline at end of file +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 index 5987fbf..0ba7f87 100644 --- a/src/ral/ral_types.h +++ b/src/ral/ral_types.h @@ -1,45 +1,124 @@ #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 -// 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_pipeline_layout gpu_pipeline_layout; -typedef struct gpu_pipeline gpu_pipeline; -typedef struct gpu_renderpass gpu_renderpass; -typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording -typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission -typedef struct gpu_buffer gpu_buffer; -typedef struct gpu_texture gpu_texture; - -typedef struct GPU_Renderpass GPU_Renderpass; -typedef struct GPU_Pipeline GPU_Pipeline; - -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 -} gpu_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; - -// Vertex attributes /// @strip_prefix(ATTR_) -typedef enum vertex_attrib_type { +typedef enum VertexAttribType { ATTR_F32, ATTR_F32x2, ATTR_F32x3, @@ -52,35 +131,93 @@ typedef enum vertex_attrib_type { ATTR_I32x2, ATTR_I32x3, ATTR_I32x4, -} vertex_attrib_type; +} 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 vertex_description {} vertex_description; -typedef struct shader_desc {} shader_desc; +typedef struct ShaderDataLayout { + ShaderBinding* bindings; + size_t binding_count; +} ShaderDataLayout; -typedef struct graphics_pipeline_desc { +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; - vertex_description vertex_desc; - shader_desc vs; /** @brief Vertex shader stage */ - shader_desc fs; /** @brief Fragment shader stage */ + 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 - shader_data data_layouts[MAX_SHADER_DATA_LAYOUTS]; + ShaderData data_layouts[MAX_SHADER_DATA_LAYOUTS]; u32 data_layouts_count; - // gpu_pipeline_layout* layout; - gpu_renderpass* renderpass; - bool wireframe; bool depth_test; -} graphics_pipeline_desc; +} GraphicsPipelineDesc; -typedef struct gpu_renderpass_desc { +typedef struct GPU_RenderpassDesc { bool default_framebuffer; bool has_color_target; - texture_handle color_target; // for now only support one + TextureHandle color_target; // for now only support one bool has_depth_stencil; - texture_handle depth_stencil; -} gpu_renderpass_desc; + TextureHandle depth_stencil; +} GPU_RenderpassDesc; diff --git a/src/render/ral_types.h b/src/render/ral_types.h index 5f21846..be95902 100644 --- a/src/render/ral_types.h +++ b/src/render/ral_types.h @@ -26,139 +26,6 @@ CORE_DEFINE_HANDLE(pipeline_handle); CORE_DEFINE_HANDLE(renderpass_handle); #define ABSENT_MODEL_HANDLE 999999999 -// 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 @@ -218,32 +85,12 @@ typedef struct shader_binding { } 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 diff --git a/src/render/render.h b/src/render/render.h index 19a8d1a..f0e9a64 100644 --- a/src/render/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/resources/gltf.c b/src/resources/gltf.c index c51e30d..5947bad 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); + 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; } @@ -86,30 +86,30 @@ typedef struct model { } 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 }; - 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_load_buffers(&options, data, filepath); - DEBUG("loaded buffers"); + 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_load_buffers(&options, data, filepath); + // DEBUG("loaded buffers"); // // --- Skin // size_t num_skins = data->skins_count; @@ -204,7 +204,7 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel // DEBUG("Number of this primitive %d", primitive.) for (cgltf_size a = 0; a < data->meshes[m].primitives[0].attributes_count; a++) { - cgltf_attribute attribute = data->meshes[m].primitives[0].attributes[a]; + // cgltf_attribute attribute = data->meshes[m].primitives[0].attributes[a]; if (attribute.type == cgltf_attribute_type_position) { TRACE("Load positions from accessor"); @@ -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) { 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..bf2f353 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, +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 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) { +model_handle 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); 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.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 1ef7940..11c40ea 100644 --- a/src/systems/input.h +++ b/src/systems/input.h @@ -36,7 +36,7 @@ bool key_just_released(keycode key); // --- Lifecycle -bool Input_Init(Input_state *input, struct GLFWwindow *window); -void Input_Shutdown(Input_state *input); +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 +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 a8e8b48..1d23cc3 100644 --- a/src/systems/terrain.c +++ b/src/systems/terrain.c @@ -1,30 +1,19 @@ /** - * @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" struct Terrain_Storage { arena terrain_allocator; - heightmap* heightmap; // NULL = no heightmap + Heightmap* heightmap; // NULL = no heightmap GPU_Renderpass* hmap_renderpass; GPU_Pipeline* hmap_pipeline; }; -PUB bool Terrain_Init(Terrain_Storage* storage) { - - return true; -} +PUB bool Terrain_Init(Terrain_Storage* storage) { return true; } PUB void Terrain_Shutdown(Terrain_Storage* storage); - /* bool terrain_system_init(terrain_state* state) { */ /* gpu_renderpass_desc rpass_desc = { */ /* .default_framebuffer = true, */ diff --git a/src/systems/terrain.h b/src/systems/terrain.h index a65ecec..890cb90 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -19,7 +19,7 @@ Future: #include "str.h" typedef struct Heightmap { - str8 filepath; + Str8 filepath; u32x2 size; void* image_data; bool is_uploaded; @@ -32,9 +32,13 @@ 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 -PUB Heightmap Heightmap_FromImage(str8 filepath); +/** @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 */); +PUB bool Terrain_IsActive(); // checks whether we have a loaded heightmap and it's being rendered + // --- Internal // TODO: void terrain_system_render_hmap(renderer* rend, terrain_state* state); 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..b08e545 100644 --- a/src/transform_hierarchy.c +++ b/src/transform_hierarchy.c @@ -11,6 +11,7 @@ #include "log.h" #include "maths.h" #include "maths_types.h" +#include "render_types.h" struct transform_hierarchy { transform_node root; @@ -49,8 +50,8 @@ void transform_hierarchy_free(transform_hierarchy* 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) { +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; @@ -131,10 +132,10 @@ bool update_matrix(transform_node* node, void* _ctx_data) { if (node->tf.is_dirty) { // invalidates children - mat4 updated_local_transform = transform_to_mat(&node->tf); + Mat4 updated_local_transform = transform_to_mat(&node->tf); node->local_matrix_tf = updated_local_transform; if (node->parent) { - mat4 updated_world_transform = + Mat4 updated_world_transform = mat4_mult(node->parent->world_matrix_tf, updated_local_transform); node->world_matrix_tf = updated_world_transform; } @@ -149,7 +150,7 @@ void transform_hierarchy_propagate_transforms(transform_hierarchy* tfh) { } struct print_ctx { - core* core; + Core* core; u32 indentation_lvl; }; @@ -175,10 +176,10 @@ bool print_node(transform_node* node, void* ctx_data) { return true; } -void transform_hierarchy_debug_print(transform_node* start_node, core* core) { +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 +} diff --git a/src/transform_hierarchy.h b/src/transform_hierarchy.h index 0921c19..0a506de 100644 --- a/src/transform_hierarchy.h +++ b/src/transform_hierarchy.h @@ -10,25 +10,26 @@ #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(); +TransformHierarchy* TransformHierarchy_Create(); /** * @brief recursively frees all the children and then finally itself @@ -45,11 +46,11 @@ 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); +Transform_Node* TransformHierarchy_RootNode(TransformHierarchy* tfh); // --- Mutations -transform_node* transform_hierarchy_add_node(transform_node* parent, model_handle model, - transform tf); +Transform_Node* TransformHierarchy_AddNode(transform_node* parent, ModelHandle model, + Transform tf); void transform_hierarchy_delete_node(transform_node* node); // --- Traversal @@ -73,5 +74,5 @@ 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 +struct Core; +void transform_hierarchy_debug_print(transform_node* start_node, struct Core* core); @@ -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,6 +56,7 @@ 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", @@ -79,91 +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/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 +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") @@ -286,6 +288,13 @@ target("core_shared") -- add_files("examples/demo/demo.c") -- set_rundir("$(projectdir)") +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") |