summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-18 00:18:50 +1100
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-18 00:18:50 +1100
commitdf81a840a5276c35df5f35d55610f1bf31487153 (patch)
tree51b4fe8d90911e83ea3248481dc40b47a3b95083
parenta9b750f003c711eb08cbc4b6b383de0ddab6ddcc (diff)
port a few more math functions
-rw-r--r--assets/shaders/cube.metal29
-rw-r--r--examples/cube.c21
-rw-r--r--include/celeritas.h91
-rw-r--r--src/maths.c36
4 files changed, 141 insertions, 36 deletions
diff --git a/assets/shaders/cube.metal b/assets/shaders/cube.metal
index e69de29..dc7ace1 100644
--- a/assets/shaders/cube.metal
+++ b/assets/shaders/cube.metal
@@ -0,0 +1,29 @@
+#include <metal_stdlib>
+using namespace metal;
+
+struct VertexData {
+ float4 position;
+ float4 normal;
+ float2 texCoords;
+};
+
+struct VertexOut {
+ float4 position [[position]];
+ float2 textureCoordinate;
+};
+
+struct TransformationData {
+ float4x4 modelMatrix;
+ float4x4 viewMatrix;
+ float4x4 perspectiveMatrix;
+};
+
+vertex VertexOut cubeVertexShader(uint vertexID [[vertex_id]],
+ constant VertexData* vertexData,
+ constant TransformationData* transformationData)
+{
+ VertexOut out;
+ out.position = transformationData->perspectiveMatrix * transformationData->viewMatrix * transformationData->modelMatrix * vertexData[vertexID].position;
+ out.textureCoordinate = vertexData[vertexID].texCoords;
+ return out;
+} \ No newline at end of file
diff --git a/examples/cube.c b/examples/cube.c
index 6642e2a..629a570 100644
--- a/examples/cube.c
+++ b/examples/cube.c
@@ -1,12 +1,25 @@
#include <celeritas.h>
-
-// vertices
+#include "glfw3.h"
pipeline_handle draw_pipeline;
buf_handle cube_vbuf;
tex_handle texture;
+// transformation data
+typedef struct MVPData {
+ mat4 model;
+ mat4 view;
+ mat4 projection;
+} MVPData;
+
void draw() {
+ // prepare data
+ mat4 translation_matrix = mat4_translation(vec3(0, 0, -1));
+
+ f32 angle_degrees = glfwGetTime() / 2.0 * 45.0;
+ f32 angle = angle_degrees * PI / 180.0;
+ mat4 rotation_matrix = mat4_rotation(quat_from_axis_angle(VEC3_Y, angle, true));
+
render_pass_desc d = {};
gpu_encoder* enc = ral_render_encoder(d);
ral_encode_bind_pipeline(enc, draw_pipeline);
@@ -32,7 +45,7 @@ int main() {
.fragment = {
.source = NULL,
.is_spirv = false,
- .entry_point = "cubeFragmentShader",
+ .entry_point = "fragmentShader",
.stage = STAGE_FRAGMENT,
},
};
@@ -54,4 +67,4 @@ int main() {
}
return 0;
-} \ No newline at end of file
+}
diff --git a/include/celeritas.h b/include/celeritas.h
index 77b7a9b..51a9a3d 100644
--- a/include/celeritas.h
+++ b/include/celeritas.h
@@ -1,13 +1,14 @@
#pragma once
// Standard library includes
+#include <assert.h>
+#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
#include <string.h>
// Third party dependency includes
@@ -107,7 +108,7 @@ void _cel_push_error(int error_code);
// TODO: Arenas
// Pool
-typedef struct void_pool_header void_pool_header; // TODO: change name of this
+typedef struct void_pool_header void_pool_header; // TODO: change name of this
struct void_pool_header {
void_pool_header* next;
};
@@ -130,26 +131,26 @@ void* void_pool_alloc(void_pool* pool, u32* out_raw_handle);
void void_pool_dealloc(void_pool* pool, u32 raw_handle);
u32 void_pool_insert(void_pool* pool, void* item);
-#define TYPED_POOL(T, Name) \
- typedef struct Name##_pool { \
- void_pool inner; \
- } Name##_pool; \
- \
- static Name##_pool Name##_pool_create(void* storage, u64 cap, u64 entry_size) { \
- void_pool p = void_pool_create(storage, "\"" #Name "\"", cap, entry_size); \
- return (Name##_pool){ .inner = p }; \
- } \
+#define TYPED_POOL(T, Name) \
+ typedef struct Name##_pool { \
+ void_pool inner; \
+ } Name##_pool; \
+ \
+ static Name##_pool Name##_pool_create(void* storage, u64 cap, u64 entry_size) { \
+ void_pool p = void_pool_create(storage, "\"" #Name "\"", cap, entry_size); \
+ return (Name##_pool){ .inner = p }; \
+ } \
static inline T* Name##_pool_get(Name##_pool* pool, Name##_handle handle) { \
- return (T*)void_pool_get(&pool->inner, handle.raw); \
- } \
+ return (T*)void_pool_get(&pool->inner, handle.raw); \
+ } \
static inline T* Name##_pool_alloc(Name##_pool* pool, Name##_handle* out_handle) { \
- return (T*)void_pool_alloc(&pool->inner, &out_handle->raw); \
- } \
+ return (T*)void_pool_alloc(&pool->inner, &out_handle->raw); \
+ } \
static inline void Name##_pool_dealloc(Name##_pool* pool, Name##_handle handle) { \
- void_pool_dealloc(&pool->inner, handle.raw); \
- } \
+ void_pool_dealloc(&pool->inner, handle.raw); \
+ } \
static Name##_handle Name##_pool_insert(Name##_pool* pool, T* item) { \
- u32 raw_handle = void_pool_insert(pool, item); \
+ u32 raw_handle = void_pool_insert(pool, item); \
return (Name##_handle){ .raw = raw_handle }; \
}
@@ -185,13 +186,13 @@ void log_output(char* module, loglevel level, const char* msg, ...);
static inline void WARN(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_WARN, msg, args); \
+ log_output(#module, LOG_LEVEL_WARN, msg, args); \
va_end(args); \
} \
static inline void INFO(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_INFO, msg, args); \
+ log_output(#module, LOG_LEVEL_INFO, msg, args); \
va_end(args); \
} \
static inline void DEBUG(const char* msg, ...) { \
@@ -236,7 +237,6 @@ typedef vec4 quat;
typedef struct mat4 {
// TODO: use this format for more readable code: vec4 x_axis, y_axis, z_axis, w_axis;
f32 data[16];
-
} mat4;
/** @brief 3D affine transformation */
@@ -247,19 +247,49 @@ typedef struct transform {
bool is_dirty;
} transform;
+_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");
+
inlined vec3 vec3_create(f32 x, f32 y, f32 z);
inlined vec3 vec3_add(vec3 u, vec3 v);
inlined vec3 vec3_sub(vec3 u, vec3 v);
inlined vec3 vec3_mult(vec3 u, f32 s);
inlined vec3 vec3_div(vec3 u, f32 s);
+inlined vec3 vec3_len_squared(vec3 a);
+inlined f32 vec3_len(vec3 a);
+inlined vec3 vec3_negate(vec3 a);
+inlined vec3 vec3_normalise(vec3 a);
+inlined f32 vec3_dot(vec3 a, vec3 b);
+inlined vec3 vec3_cross(vec3 a, vec3 b);
inlined vec4 vec4_create(f32 x, f32 y, f32 z, f32 w);
+// quaternion functions
+inlined quat quat_ident();
+quat quat_from_axis_angle(vec3 axis, f32 angle, bool normalise);
+quat quat_slerp(quat a, quat b, f32 percentage);
+
+// matrix functions
+inlined mat4 mat4_ident();
+mat4 mat4_translation(vec3 position);
+mat4 mat4_scale(vec3 scale);
+mat4 mat4_rotation(quat rotation);
+mat4 mat4_mult(mat4 lhs, mat4 rhs);
+mat4 mat4_transposed(mat4 m);
+mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, f32 far_clip);
+mat4 mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 near_clip, f32 far_clip);
+mat4 mat4_look_at(vec3 position, vec3 target, vec3 up);
+
+// transform functions
+inlined transform transform_create(vec3 pos, quat rot, vec3 scale);
+mat4 transform_to_mat(transform* tf);
+
// helpers
-#define vec3(x,y,z) ((vec3){ x, y, z })
-#define vec4(x,y,z,w) ((vec4){ x, y, z, w })
-inlined vec4 v3tov4(vec3 v3) { return vec4_create(v3.x, v3.y, v3.z, 0.0); }
+#define vec3(x, y, z) ((vec3){ x, y, z })
+#define vec4(x, y, z, w) ((vec4){ x, y, z, w })
+inlined vec4 v3tov4(vec3 v3) { return vec4_create(v3.x, v3.y, v3.z, 1.0); }
static const vec3 VEC3_X = vec3(1.0, 0.0, 0.0);
static const vec3 VEC3_NEG_X = vec3(-1.0, 0.0, 0.0);
@@ -270,8 +300,6 @@ static const vec3 VEC3_NEG_Z = vec3(0.0, 0.0, -1.0);
static const vec3 VEC3_ZERO = vec3(0.0, 0.0, 0.0);
static const vec3 VEC3_ONES = vec3(1.0, 1.0, 1.0);
-
-
// --- RAL
DEFINE_HANDLE(buf_handle);
@@ -284,7 +312,7 @@ DEFINE_HANDLE(compute_pipeline_handle);
// Backend-specific structs
typedef struct gpu_swapchain gpu_swapchain;
-typedef struct gpu_encoder gpu_encoder; // Render command encoder
+typedef struct gpu_encoder gpu_encoder; // Render command encoder
typedef struct gpu_compute_encoder gpu_compute_encoder;
typedef struct gpu_buffer gpu_buffer;
typedef struct gpu_texture gpu_texture;
@@ -390,10 +418,10 @@ typedef struct gfx_pipeline_desc {
// u32 data_layouts_count;
} gfx_pipeline_desc;
-typedef struct compute_pipeline_desc { /* TODO */ } compute_pipeline_desc;
+typedef struct compute_pipeline_desc { /* TODO */
+} compute_pipeline_desc;
typedef struct render_pass_desc {
-
} render_pass_desc;
// --- RAL Functions
@@ -436,7 +464,7 @@ void ral_backend_resize_framebuffer(int width, int height);
// Frame lifecycle
-typedef void (*scoped_draw_commands)(); // callback that we run our draw commands within.
+typedef void (*scoped_draw_commands)(); // callback that we run our draw commands within.
// allows us to wrap some api-specific behaviour
void ral_frame_start();
@@ -493,6 +521,8 @@ typedef struct camera {
f32 fov;
} camera;
+mat4 camera_view_proj(camera);
+
// --- Reference Renderer
// TODO: Filament PBR model
@@ -502,7 +532,6 @@ typedef struct camera {
DEFINE_HANDLE(model_handle);
typedef struct model {
-
} model;
model_handle model_load_from_gltf(const char* path);
diff --git a/src/maths.c b/src/maths.c
index 95283e6..40223c6 100644
--- a/src/maths.c
+++ b/src/maths.c
@@ -2,4 +2,38 @@
vec3 vec3_create(f32 x, f32 y, f32 z) { return (vec3){ x, y, z }; }
-vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z , w }; } \ No newline at end of file
+vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z, w }; }
+
+mat4 mat4_ident() {
+ return (mat4){ .data = { 1.0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.0 } };
+}
+
+mat4 mat4_mult(mat4 lhs, mat4 rhs) {
+ mat4 out_matrix = mat4_ident();
+
+ const f32* m1_ptr = lhs.data;
+ const f32* m2_ptr = rhs.data;
+ f32* dst_ptr = out_matrix.data;
+
+ for (i32 i = 0; i < 4; ++i) {
+ for (i32 j = 0; j < 4; ++j) {
+ *dst_ptr = m1_ptr[0] * m2_ptr[0 + j] + m1_ptr[1] * m2_ptr[4 + j] + m1_ptr[2] * m2_ptr[8 + j] +
+ m1_ptr[3] * m2_ptr[12 + j];
+ dst_ptr++;
+ }
+ m1_ptr += 4;
+ }
+
+ return out_matrix;
+}
+
+mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_z, f32 far_z) {
+ f32 half_tan_fov = tanf(fov_radians * 0.5f);
+ 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_z + near_z) / (far_z - near_z));
+ out_matrix.data[11] = -1.0f;
+ out_matrix.data[14] = -((2.0f * far_z * near_z) / (far_z - near_z));
+ return out_matrix;
+}