summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-26 20:26:40 +1100
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-26 20:26:40 +1100
commitd900e713c8aebcc0a56eb594007de62584d470ea (patch)
tree048d619dc84d12fcc4fabd40af0cffcea5b92223
parent6182860f1b1aba4128b4f66eda7977600e60d1a0 (diff)
spin cube in place
-rw-r--r--assets/shaders/cube.metal2
-rw-r--r--examples/cube.c88
-rw-r--r--examples/triangle.c6
-rw-r--r--include/celeritas.h20
-rw-r--r--src/backend_mtl.m15
-rw-r--r--src/geometry.c39
-rw-r--r--src/maths.c142
7 files changed, 267 insertions, 45 deletions
diff --git a/assets/shaders/cube.metal b/assets/shaders/cube.metal
index dc7ace1..93fa727 100644
--- a/assets/shaders/cube.metal
+++ b/assets/shaders/cube.metal
@@ -24,6 +24,8 @@ vertex VertexOut cubeVertexShader(uint vertexID [[vertex_id]],
{
VertexOut out;
out.position = transformationData->perspectiveMatrix * transformationData->viewMatrix * transformationData->modelMatrix * vertexData[vertexID].position;
+ // out.position = transformationData->modelMatrix * vertexData[vertexID].position;
+ // out.position = 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 629a570..8fd85de 100644
--- a/examples/cube.c
+++ b/examples/cube.c
@@ -1,8 +1,10 @@
#include <celeritas.h>
#include "glfw3.h"
+camera cam;
pipeline_handle draw_pipeline;
buf_handle cube_vbuf;
+buf_handle transform_buf;
tex_handle texture;
// transformation data
@@ -12,24 +14,83 @@ typedef struct MVPData {
mat4 projection;
} MVPData;
+// draw calls for a single frame
void draw() {
- // prepare data
- mat4 translation_matrix = mat4_translation(vec3(0, 0, -1));
-
- f32 angle_degrees = glfwGetTime() / 2.0 * 45.0;
+ // prepare model data
+ f32 angle_degrees = glfwGetTime() * 45.0;
f32 angle = angle_degrees * PI / 180.0;
- mat4 rotation_matrix = mat4_rotation(quat_from_axis_angle(VEC3_Y, angle, true));
+
+ // Move origin to cube center
+ vec3 center_offset = vec3(0.5, 0.5, 0.5);
+ mat4 to_center = mat4_translation(vec3_negate(center_offset));
+ mat4 from_center = mat4_translation(center_offset);
+
+ // Create rotation around Y axis
+ mat4 rotation = mat4_rotation(quat_from_axis_angle(VEC3_Y, angle, true));
+
+ // Print debug info for one frame
+ static bool printed = false;
+ if (!printed) {
+ printf("\nTo Center:\n");
+ for (int i = 0; i < 16; i += 4) {
+ printf("%f %f %f %f\n", to_center.data[i], to_center.data[i + 1], to_center.data[i + 2], to_center.data[i + 3]);
+ }
+ printed = true;
+ }
+
+ // Order: first move to center, then rotate, then move back
+ mat4 cube_transform = mat4_mult(from_center, mat4_mult(rotation, to_center));
+
+ mat4 move = mat4_translation(vec3(-0.5, -0.5, 0));
+ cube_transform = mat4_mult(move, cube_transform);
+
+ // prepare camera data
+ mat4 view, proj;
+ camera_view_proj(cam, 800, 600, &view, &proj);
render_pass_desc d = {};
gpu_encoder* enc = ral_render_encoder(d);
ral_encode_bind_pipeline(enc, draw_pipeline);
+ ral_set_default_settings(enc);
+
+ MVPData mvp = { .model = cube_transform, .view = view, .projection = proj };
+
+ ral_buffer_upload_data(transform_buf, sizeof(MVPData), &mvp);
+ ral_bind_buffer(enc, transform_buf, 1); // bind the transform data buffer to binding 1
ral_encode_set_vertex_buf(enc, cube_vbuf);
ral_encode_set_texture(enc, texture, 0);
ral_encode_draw_tris(enc, 0, 36);
ral_encoder_finish_and_submit(enc);
}
+void test_matrix_mult() {
+ // Create a simple translation matrix (1 unit in x)
+ mat4 trans1 = mat4_translation(vec3(1, 0, 0));
+ // Create another translation matrix (1 unit in y)
+ mat4 trans2 = mat4_translation(vec3(0, 1, 0));
+
+ printf("Matrix 1 (translate x+1):\n");
+ for (int i = 0; i < 16; i += 4) {
+ printf("%f %f %f %f\n", trans1.data[i], trans1.data[i + 1], trans1.data[i + 2], trans1.data[i + 3]);
+ }
+
+ printf("\nMatrix 2 (translate y+1):\n");
+ for (int i = 0; i < 16; i += 4) {
+ printf("%f %f %f %f\n", trans2.data[i], trans2.data[i + 1], trans2.data[i + 2], trans2.data[i + 3]);
+ }
+
+ mat4 result = mat4_mult(trans1, trans2);
+
+ printf("\nResult matrix:\n");
+ for (int i = 0; i < 16; i += 4) {
+ printf("%f %f %f %f\n", result.data[i], result.data[i + 1], result.data[i + 2], result.data[i + 3]);
+ }
+}
+
int main() {
+ test_matrix_mult();
+ // exit(1);
+
core_bringup("Celeritas Example: Triangle", NULL);
// create rendering pipeline
@@ -52,12 +113,29 @@ int main() {
draw_pipeline = ral_gfx_pipeline_create(pipeline_desc);
+ // load texture from file
+ texture = ral_texture_load_from_file("assets/textures/mc_grass.jpeg");
+
+ cam = (camera){ .position = vec3(0, 3, 5), .forwards = vec3(0, -3, -5), .fov = 45.0, .up = VEC3_Y };
+
// create the cube geometry
geometry cube = geo_cuboid(1.0, 1.0, 1.0);
+ // (debug) print out each vertex
+ size_t vertex_stride = cube.data_length / cube.n_vertices;
+ printf("Vertex stride %ld\n", vertex_stride);
+ for (int i = 0; i < cube.n_vertices; i++) {
+ static_3d_vert* vertex = (static_3d_vert*)(cube.vertex_data + vertex_stride * i);
+ print_static_3d_vert(vertex);
+ }
+
// upload vertex data to the gpu
cube_vbuf = ral_buffer_create(64 * 36, cube.vertex_data);
+ // create a buffer to hold the MVP transforms
+ MVPData d = {};
+ transform_buf = ral_buffer_create(sizeof(MVPData), &d);
+
while (!app_should_exit()) {
glfwPollEvents();
diff --git a/examples/triangle.c b/examples/triangle.c
index 7770fd1..8cf8dd2 100644
--- a/examples/triangle.c
+++ b/examples/triangle.c
@@ -2,12 +2,6 @@
#include <celeritas.h>
-// static vec4 vertices[] = {
-// {-0.5f, -0.5f, 0.0f, 1.0},
-// { 0.5f, -0.5f, 0.0f, 1.0},
-// { 0.0f, 0.5f, 0.0f, 1.0}
-// };
-
typedef struct VertexData {
vec4 position;
vec2 texCoords;
diff --git a/include/celeritas.h b/include/celeritas.h
index 0b56bf5..979e8c4 100644
--- a/include/celeritas.h
+++ b/include/celeritas.h
@@ -264,7 +264,7 @@ 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_squared(vec3 a);
inlined f32 vec3_len(vec3 a);
inlined vec3 vec3_negate(vec3 a);
inlined vec3 vec3_normalise(vec3 a);
@@ -275,11 +275,13 @@ inlined vec4 vec4_create(f32 x, f32 y, f32 z, f32 w);
// quaternion functions
inlined quat quat_ident();
+quat quat_normalise(quat a);
+f32 quat_dot(quat a, quat b);
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_ident();
mat4 mat4_translation(vec3 position);
mat4 mat4_scale(vec3 scale);
mat4 mat4_rotation(quat rotation);
@@ -366,9 +368,18 @@ typedef struct vertex_desc {
u32 padding;
} vertex_desc;
+typedef struct static_3d_vert {
+ vec4 pos;
+ vec4 norm;
+ vec2 uv;
+ vec2 pad;
+} static_3d_vert;
+
// Some default formats
vertex_desc static_3d_vertex_format();
+void print_static_3d_vert(static_3d_vert* vertex_data);
+
typedef enum shader_binding_type {
BINDING_BYTES,
BINDING_BUFFER,
@@ -437,6 +448,7 @@ typedef struct render_pass_desc {
// Resources
buf_handle ral_buffer_create(u64 size, const void* data);
void ral_buffer_destroy(buf_handle handle);
+void ral_buffer_upload_data(buf_handle, u64 size, const void* data);
tex_handle ral_texture_create(texture_desc desc, bool create_view, const void* data);
tex_handle ral_texture_load_from_file(const char* filepath);
@@ -460,9 +472,11 @@ void ral_compute_pipeline_destroy(compute_pipeline_handle handle);
// Encoding
void ral_encode_bind_pipeline(gpu_encoder* enc, pipeline_handle pipeline);
+void ral_set_default_settings(gpu_encoder* enc);
void ral_encode_set_vertex_buf(gpu_encoder* enc, buf_handle vbuf);
void ral_encode_set_index_buf(gpu_encoder* enc, buf_handle ibuf);
void ral_encode_set_texture(gpu_encoder* enc, tex_handle texture, u32 slot);
+void ral_bind_buffer(gpu_encoder* enc, buf_handle, u32 index);
void ral_encode_draw_tris(gpu_encoder* enc, size_t start, size_t count);
// Backend lifecycle
@@ -491,6 +505,8 @@ DEFINE_HANDLE(model_handle);
typedef struct geometry {
vertex_desc vertex_format;
void* vertex_data;
+ size_t data_length;
+ size_t n_vertices;
bool has_indices; // When this is false indexed drawing is not used
u32_darray* indices;
} geometry;
diff --git a/src/backend_mtl.m b/src/backend_mtl.m
index 48e0ab0..2564ff0 100644
--- a/src/backend_mtl.m
+++ b/src/backend_mtl.m
@@ -128,6 +128,11 @@ buf_handle ral_buffer_create(u64 size, const void *data) {
return handle;
}
+void ral_buffer_upload_data(buf_handle buf, u64 size, const void *data) {
+ metal_buffer* b = buf_pool_get(&ctx.bufpool, buf);
+ memcpy(b->id.contents, data, size);
+}
+
tex_handle ral_texture_create(texture_desc desc, bool create_view, const void *data) {
tex_handle handle;
metal_texture* texture = tex_pool_alloc(&ctx.texpool, &handle);
@@ -229,11 +234,21 @@ void ral_encode_bind_pipeline(gpu_encoder *enc, pipeline_handle pipeline) {
[enc->cmd_encoder setRenderPipelineState:p->pso];
}
+void ral_set_default_settings(gpu_encoder* enc) {
+ [enc->cmd_encoder setFrontFacingWinding:MTLWindingCounterClockwise];
+ [enc->cmd_encoder setCullMode:MTLCullModeBack];
+}
+
void ral_encode_set_vertex_buf(gpu_encoder *enc, buf_handle vbuf) {
metal_buffer* b = buf_pool_get(&ctx.bufpool, vbuf);
[enc->cmd_encoder setVertexBuffer:b->id offset:0 atIndex:0 ];
}
+void ral_bind_buffer(gpu_encoder *enc, buf_handle buf, u32 index) {
+ metal_buffer* b = buf_pool_get(&ctx.bufpool, buf);
+ [enc->cmd_encoder setVertexBuffer:b->id offset:0 atIndex:index ];
+}
+
void ral_encode_set_texture(gpu_encoder* enc, tex_handle texture, u32 slot) {
metal_texture* t = tex_pool_get(&ctx.texpool, texture);
[enc->cmd_encoder setFragmentTexture:t->id atIndex:slot];
diff --git a/src/geometry.c b/src/geometry.c
index 05414d3..46bb058 100644
--- a/src/geometry.c
+++ b/src/geometry.c
@@ -1,12 +1,5 @@
#include <celeritas.h>
-typedef struct static_3d_vert {
- vec4 pos;
- vec4 norm;
- vec2 uv;
- vec2 pad;
-} static_3d_vert;
-
vertex_desc static_3d_vertex_format() {
vertex_desc desc;
desc.label = "Static 3D Vertex";
@@ -19,18 +12,23 @@ vertex_desc static_3d_vertex_format() {
return desc;
}
+void print_static_3d_vert(static_3d_vert* vertex_data) {
+ printf("Pos (%.2f, %.2f %.2f)\n", vertex_data->pos.x, vertex_data->pos.y, vertex_data->pos.z);
+}
+
geometry geo_cuboid(f32 x_scale, f32 y_scale, f32 z_scale) {
- vec4 BACK_BOT_LEFT = (vec4){ 0, 0, 0, 0 };
- vec4 BACK_BOT_RIGHT = (vec4){ 1, 0, 0, 0 };
- vec4 BACK_TOP_LEFT = (vec4){ 0, 1, 0, 0 };
- vec4 BACK_TOP_RIGHT = (vec4){ 1, 1, 0, 0 };
- vec4 FRONT_BOT_LEFT = (vec4){ 0, 0, 1, 0 };
- vec4 FRONT_BOT_RIGHT = (vec4){ 1, 0, 1, 0 };
- vec4 FRONT_TOP_LEFT = (vec4){ 0, 1, 1, 0 };
- vec4 FRONT_TOP_RIGHT = (vec4){ 1, 1, 1, 0 };
+ vec4 BACK_BOT_LEFT = (vec4){ 0, 0, 0, 1 };
+ vec4 BACK_BOT_RIGHT = (vec4){ 1, 0, 0, 1 };
+ vec4 BACK_TOP_LEFT = (vec4){ 0, 1, 0, 1 };
+ vec4 BACK_TOP_RIGHT = (vec4){ 1, 1, 0, 1 };
+ vec4 FRONT_BOT_LEFT = (vec4){ 0, 0, 1, 1 };
+ vec4 FRONT_BOT_RIGHT = (vec4){ 1, 0, 1, 1 };
+ vec4 FRONT_TOP_LEFT = (vec4){ 0, 1, 1, 1 };
+ vec4 FRONT_TOP_RIGHT = (vec4){ 1, 1, 1, 1 };
// allocate the data
- static_3d_vert* vertices = malloc(36 * 64);
+ size_t buffer_length = 36 * 64;
+ static_3d_vert* vertices = malloc(buffer_length);
vertices[0] = (static_3d_vert){ .pos = BACK_TOP_RIGHT, .norm = (v3tov4(VEC3_NEG_Z)), .uv = { 0, 0 } };
vertices[1] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_Z), .uv = { 0, 1 } };
@@ -79,7 +77,10 @@ geometry geo_cuboid(f32 x_scale, f32 y_scale, f32 z_scale) {
vertices[34] = (static_3d_vert){ .pos = FRONT_BOT_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
vertices[35] = (static_3d_vert){ .pos = FRONT_TOP_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
- return (geometry){
- .vertex_format = static_3d_vertex_format(), .vertex_data = vertices, .has_indices = false, .indices = NULL
- };
+ return (geometry){ .vertex_format = static_3d_vertex_format(),
+ .vertex_data = vertices,
+ .data_length = buffer_length,
+ .n_vertices = 36,
+ .has_indices = false,
+ .indices = NULL };
} \ No newline at end of file
diff --git a/src/maths.c b/src/maths.c
index c1fab2a..3a7ecf1 100644
--- a/src/maths.c
+++ b/src/maths.c
@@ -1,27 +1,116 @@
#include <celeritas.h>
vec3 vec3_create(f32 x, f32 y, f32 z) { return (vec3){ x, y, z }; }
-
vec3 vec3_add(vec3 u, vec3 v) { return (vec3){ .x = u.x + v.x, .y = u.y + v.y, .z = u.z + v.z }; }
+vec3 vec3_sub(vec3 a, vec3 b) { return (vec3){ a.x - b.x, a.y - b.y, a.z - b.z }; }
+vec3 vec3_mult(vec3 a, f32 s) { return (vec3){ a.x * s, a.y * s, a.z * s }; }
+vec3 vec3_div(vec3 a, f32 s) { return (vec3){ a.x / s, a.y / s, a.z / s }; }
+
+f32 vec3_len_squared(vec3 a) { return (a.x * a.x) + (a.y * a.y) + (a.z * a.z); }
+f32 vec3_len(vec3 a) { return sqrtf(vec3_len_squared(a)); }
+vec3 vec3_negate(vec3 a) { return (vec3){ -a.x, -a.y, -a.z }; }
+
+vec3 vec3_normalise(vec3 a) {
+ f32 length = vec3_len(a);
+ return vec3_div(a, length);
+}
+
+f32 vec3_dot(vec3 a, vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
+
+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 };
+}
vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z, w }; }
+f32 quat_dot(quat a, quat b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; }
+
+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 };
+}
+
+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 };
+ if (normalize) {
+ return quat_normalise(q);
+ }
+ return q;
+}
+
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 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;
+}
+
+mat4 mat4_scale(vec3 scale) {
mat4 out_matrix = mat4_ident();
+ out_matrix.data[0] = scale.x;
+ out_matrix.data[5] = scale.y;
+ out_matrix.data[10] = scale.z;
+ return out_matrix;
+}
+
+// TODO: double check this
+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;
+ out_matrix.data[2] = 2.0f * n.x * n.z + 2.0f * n.y * n.w;
+
+ out_matrix.data[4] = 2.0f * n.x * n.y + 2.0f * n.z * n.w;
+ out_matrix.data[5] = 1.0f - 2.0f * n.x * n.x - 2.0f * n.z * n.z;
+ out_matrix.data[6] = 2.0f * n.y * n.z - 2.0f * n.x * n.w;
+
+ out_matrix.data[8] = 2.0f * n.x * n.z - 2.0f * n.y * n.w;
+ out_matrix.data[9] = 2.0f * n.y * n.z + 2.0f * n.x * n.w;
+ out_matrix.data[10] = 1.0f - 2.0f * n.x * n.x - 2.0f * n.y * n.y;
+
+ return out_matrix;
+}
- const f32* m1_ptr = lhs.data;
- const f32* m2_ptr = rhs.data;
- f32* dst_ptr = out_matrix.data;
+// mat4 mat4_mult(mat4 lhs, mat4 rhs) {
+// mat4 out_matrix = mat4_ident();
- 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++;
+// 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_mult(mat4 lhs, mat4 rhs) {
+ mat4 out_matrix = mat4_ident();
+
+ for (i32 row = 0; row < 4; row++) {
+ for (i32 col = 0; col < 4; col++) {
+ f32 sum = 0;
+ for (i32 i = 0; i < 4; i++) {
+ // column-major: first matrix columns × second matrix rows
+ sum += lhs.data[row + i * 4] * rhs.data[i + col * 4];
+ }
+ out_matrix.data[row + col * 4] = sum;
}
- m1_ptr += 4;
}
return out_matrix;
@@ -39,5 +128,32 @@ mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_z, f32 far_z)
}
mat4 mat4_look_at(vec3 position, vec3 target, vec3 up) {
- // TODO
-} \ No newline at end of file
+ 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);
+
+ out_matrix.data[0] = x_axis.x;
+ out_matrix.data[1] = y_axis.x;
+ out_matrix.data[2] = -z_axis.x;
+ out_matrix.data[3] = 0;
+ out_matrix.data[4] = x_axis.y;
+ out_matrix.data[5] = y_axis.y;
+ out_matrix.data[6] = -z_axis.y;
+ out_matrix.data[7] = 0;
+ out_matrix.data[8] = x_axis.z;
+ out_matrix.data[9] = y_axis.z;
+ out_matrix.data[10] = -z_axis.z;
+ out_matrix.data[11] = 0;
+ out_matrix.data[12] = -vec3_dot(x_axis, position);
+ out_matrix.data[13] = -vec3_dot(y_axis, position);
+ out_matrix.data[14] = vec3_dot(z_axis, position);
+ out_matrix.data[15] = 1.0f;
+
+ return out_matrix;
+}