summaryrefslogtreecommitdiff
path: root/src/rendering
diff options
context:
space:
mode:
authoronelin <oscar@nelin.dk>2025-10-31 23:55:42 +0000
committeronelin <oscar@nelin.dk>2025-11-02 22:07:17 +0000
commitd38deeef3af2316a666f8fc0173940bd769b748e (patch)
tree6e30d4a9eea18daa5705c894f28cd99ff047e8f9 /src/rendering
parent6c077751982ea2c7bd2d9262b01b9f8602f80dc8 (diff)
Flatten project structure
This will make it easier to break up the code into smaller chunks again later. One would think doing this seems fun to me at this point.
Diffstat (limited to 'src/rendering')
-rw-r--r--src/rendering/CMakeLists.txt33
-rw-r--r--src/rendering/include/engine/rendering/platform.h57
-rw-r--r--src/rendering/include/engine/rendering/platform_glfw.h32
-rw-r--r--src/rendering/include/engine/rendering/rendering.h288
-rw-r--r--src/rendering/include/engine/rendering/window.h53
-rw-r--r--src/rendering/src/gl.c281
-rw-r--r--src/rendering/src/platform_glfw.c232
-rw-r--r--src/rendering/src/rendering.c696
-rw-r--r--src/rendering/src/window.c83
9 files changed, 0 insertions, 1755 deletions
diff --git a/src/rendering/CMakeLists.txt b/src/rendering/CMakeLists.txt
deleted file mode 100644
index f3f4710..0000000
--- a/src/rendering/CMakeLists.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-add_library(daw_rendering
- src/gl.c
- src/rendering.c
- src/window.c
- src/platform_glfw.c
- ${GLAD_HEADER}
- )
-
-add_custom_command(
- OUTPUT ${GLAD_HEADER}
- COMMAND
- glad
- --api gl:core=4.6
- --out-path ${CMAKE_BINARY_DIR}
- --reproducible
- c
- --header-only
- --mx
- )
-
-set_property(SOURCE src/window.c APPEND PROPERTY OBJECT_DEPENDS ${GLAD_HEADER})
-set_property(SOURCE src/rendering.c APPEND PROPERTY OBJECT_DEPENDS ${GLAD_HEADER})
-
-target_compile_options(daw_rendering PUBLIC ${BUILD_OPTS})
-target_include_directories(daw_rendering PRIVATE
- ${DAW_INCLUDE_DIRS}
- ${GLFW_INCLUDE_DIR}
-)
-target_link_libraries(daw_rendering PRIVATE
- OpenGL::GL
- cglm
- glfw
-)
diff --git a/src/rendering/include/engine/rendering/platform.h b/src/rendering/include/engine/rendering/platform.h
deleted file mode 100644
index ea51c47..0000000
--- a/src/rendering/include/engine/rendering/platform.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef PLATFORM_H
-#define PLATFORM_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <cglm/ivec2.h>
-
-#include <engine/core/types.h>
-// TODO: We only need the window once all the garbage in Instance is cleaned up.
-#include <engine/core/platform.h>
-#include <engine/rendering/window.h>
-
-#define DAW_WINDOW_VSYNC (1 << 0)
-#define DAW_WINDOW_FULLSCREEN (1 << 1)
-#define DAW_WINDOW_RESIZEABLE (1 << 2)
-
-// Whether or not it is clever to force API consistency using a struct like this
-// can be debated, at the time of writing it seemed like a smart idea.
-
-// Platform libraries must implement a struct Platform:
-struct Platform {
- /* Initialize a window for the given platform. The rendering backend should
- * also be initialized here.
- * Parameters:
- * const char* title: window title.
- * ivec2 windowsize: the size in pixels for the new window.
- * const u32 flags: window flags, such as static size and fullscreen.
- * The flags are platform agnostic and needs to be
- * converted to the specific library
- * Returns:
- * A pointer to a struct Window, NULL on error.
- */
- Window* (*window_init)(const char *restrict title, ivec2 windowsize, const u32 flags);
-
- /* Destroy, close, and free up resources related to the window and the
- * platform library specific resources.
- */
- void (*window_destroy)(Window *restrict w);
-
- /* Resize the given window. Resize callbacks are handled by the wrapper
- * implementation.
- */
- void (*window_resize)(Window *restrict window, int width, int height);
-
- /* Return true if the platform has ordered the window to exit. */
- bool (*window_should_close)(Window *restrict w);
-
- /* Poll events on the window from the operating system. */
- void (*window_poll)(void);
-};
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/rendering/include/engine/rendering/platform_glfw.h b/src/rendering/include/engine/rendering/platform_glfw.h
deleted file mode 100644
index 949968d..0000000
--- a/src/rendering/include/engine/rendering/platform_glfw.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef ENGINE_RENDERING_PLATFORM_GLFW_H
-#define ENGINE_RENDERING_PLATFORM_GLFW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <cglm/ivec2.h>
-
-#include <engine/core/types.h>
-#include <engine/rendering/platform.h>
-#include <engine/rendering/window.h>
-
-Window* window_init_glfw(const char *restrict windowtitle, ivec2 windowsize, const u32 flags);
-void window_destroy_glfw(Window *restrict w);
-void window_resize_glfw(Window *restrict window, int width, int height);
-bool window_should_close_glfw(Window *restrict window);
-void window_poll_glfw(void);
-
-const struct Platform Platform_GLFW = {
- .window_init = window_init_glfw,
- .window_destroy = window_destroy_glfw,
- .window_resize = window_resize_glfw,
- .window_should_close = window_should_close_glfw,
- .window_poll = window_poll_glfw,
-};
-
-#ifdef __cplusplus
-}
-#endif
-#endif
-
diff --git a/src/rendering/include/engine/rendering/rendering.h b/src/rendering/include/engine/rendering/rendering.h
deleted file mode 100644
index a996257..0000000
--- a/src/rendering/include/engine/rendering/rendering.h
+++ /dev/null
@@ -1,288 +0,0 @@
-#ifndef ENGINE_RENDERING_RENDERING_H
-#define ENGINE_RENDERING_RENDERING_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <engine/core/types.h>
-#include <engine/rendering/window.h>
-
-#include <cglm/ivec2.h>
-
-/* Definitions */
-#define RGBA(_r, _g, _b, _a) ((Engine_color){.r = _r, .g = _g, .b = _b, .a = _a})
-#define RGB(_r, _g, _b) RGBA(_r, _g, _b, 0xFF)
-
-/* Types */
-/* TODO: Cleanup these types. */
-typedef struct {
- u8 r;
- u8 g;
- u8 b;
- u8 a;
-} Engine_color;
-
-typedef struct {
- /* Maybe implement types, such as `atlas` (default), `standalone`, or
- * something idk. */
- u32 id;
- i32 width;
- i32 height;
-} Texture;
-
-typedef struct {
- u32 texture_id;
- ivec2 coord;
-} Sprite;
-
-typedef enum {
- Shader_Error,
-
- Shader_Program,
- Shader_Vertex,
- Shader_Tessellation,
- Shader_Geometry,
- Shader_Fragment,
- Shader_Compute,
-} ShaderType;
-
-typedef struct {
- /* Shader proram */
- ShaderType type;
- u32 program;
-} Shader;
-
-typedef struct {
- vec3 position;
- vec3 size;
- mat4 rotation;
-} Transform;
-
-typedef enum {
- ShaderBufferFlag_none = 0x00,
-
- // First 3 bytes describe the access frequency.
- ShaderBuffer_AccessFrequency_stream = 0b0000000000001, // 1
- ShaderBuffer_AccessFrequency_static = 0b0000000000010, // 2
- ShaderBuffer_AccessFrequency_dynamic = 0b0000000000011, // 3
-
- // Next 3 bytes describe the access type.
- ShaderBuffer_AccessType_draw = 0b0000000001000, // 8
- ShaderBuffer_AccessType_read = 0b0000000010000, // 16
- ShaderBuffer_AccessType_copy = 0b0000000011000, // 24
-
- // Next 3 bytes describe the buffer type
- ShaderBuffer_Type_vertexData = 0b0000001000000, // 64
- ShaderBuffer_Type_vertexPosition = 0b0000010000000, // 128
- ShaderBuffer_Type_vertexIndex = 0b0000011000000, // 192
-
- // Next 4 bytes are designated for the data type
- ShaderBuffer_DataType_nil = 0b0001000000000, // 512
-
- ShaderBuffer_DataType_f32 = 0b0010000000000, // 1024
- ShaderBuffer_DataType_f64 = 0b0011000000000, // 1536
-
- ShaderBuffer_DataType_i8 = 0b0100000000000, // 2048
- ShaderBuffer_DataType_i16 = 0b0101000000000, // 2560
- ShaderBuffer_DataType_i32 = 0b0110000000000, // 3072
- ShaderBuffer_DataType_i64 = 0b0111000000000, // 3584
-
- ShaderBuffer_DataType_u8 = 0b1000000000000, // 4096
- ShaderBuffer_DataType_u16 = 0b1001000000000, // 4608
- ShaderBuffer_DataType_u32 = 0b1010000000000, // 5120
- ShaderBuffer_DataType_u64 = 0b1011000000000, // 5632
-} ShaderBufferFlag;
-
-typedef struct {
- // The backend ID, ie. glGenBuffer(numBufferObjects, &this->buffername)
- u32 buffername;
- // Array, access, and data, type.
- u32 buffertype;
- // Buffer size of `data`. To get the size of the actual data, size_elem * count
- usize size;
- // Number of elements
- usize count;
- // components per generic vertex attribute (ie, 3 for RGB, 2 for UV)
- usize components;
- // size of each element
- usize size_elem;
- // Pointer to the data
- void* data;
-} ShaderBuffer;
-
-// SHADERBUFFER_NEW is a constructor that takes the
-// * type T, as one of f32, f64, i8, i16, i32, i64, u8, u16, u32, or u64.
-// * COUNT, number of elements in the buffer
-// * COMPONENTS, number of elements to be grouped together, ie. 3 for a vec3.
-// * DATA, the buffer (it is pointed to automatically)
-// * FLAGS, are low-level GL flags that hints the access frequency, the access
-// type, and what buffer type it is, such as "data" or an index buffer.
-#define SHADERBUFFER_NEW(T, COUNT, COMPONENTS, DATA, FLAGS) \
- (ShaderBuffer){ \
- .buffername = 0, \
- .buffertype = ShaderBuffer_DataType_##T | FLAGS, \
- .size = COUNT * sizeof(T), \
- .count = COUNT, \
- .components = COMPONENTS, \
- .size_elem = sizeof(T), \
- .data = DATA, \
- }
-
-typedef struct {
- /* Shader proram */
- Shader shader;
- /* Vertex Array Object */
- u32 vao;
-
- /* MVP (a uniform from the shader).
- * This could also probably be generalized */
- i32 mvp;
-
- // The texture ID, glBindTextures(target, &this->texture)
- u32 texture;
-
- // Number of buffers
- usize buffer_len;
-
- // The vertex buffer is also just a buffer
- ShaderBuffer* buffer;
-} RenderObject;
-
-typedef struct {
- // Index of the model in the RenderBatch models buffer
- usize model_idx;
- // The transformation of the model
- Transform transform;
-} BatchModelInstance;
-
-typedef struct {
- // Size of models buffer
- usize msize;
- // number of models in the `models` buffer
- usize mcount;
- // Pointers to original models in this batch
- RenderObject **models;
-
- // Size of instance buffer
- usize inst_size;
- // number of instances in the `instances` buffer
- usize inst_count;
- // Pointers to original models in this batch
- BatchModelInstance *instances;
-
- // The rendered destination object
- RenderObject renderobj;
-} RenderBatch;
-
-typedef enum {
- Camera_Perspective,
- Camera_Orthogonal,
-} CameraType;
-
-typedef struct {
- /* Position of the camera in world-space. */
- vec3 pos;
-
- /* The viewing direction of the camera, relative to the camera. */
- vec3 dir;
-
- /* Perspective matrix. Initialize with r_perspective_ortho or r_perspective. */
- /* Alternatively, use `glm_perspective` or `glm_ortho`. */
- mat4 per;
-
- /* Used to re-calculate the perspective matrix when resizing the window */
- CameraType type;
- /* Yes, could use a singular "f32 arg", but this is more extendable in the
- * future. */
- union {
- struct {f32 fov;} perspective;
- struct {f32 sz;} orthogonal;
- } parameters;
-
-} Camera;
-
-usize ShaderBufferDataType_size(u16 flags);
-
-ShaderBufferFlag ShaderBuffer_get_access_frequency(u64 flags);
-ShaderBufferFlag ShaderBuffer_get_access_type(u64 flags);
-ShaderBufferFlag ShaderBuffer_get_type(u64 flags);
-ShaderBufferFlag ShaderBuffer_get_data_type(u64 flags);
-
-/* Conversion to GL types */
-u32 ShaderBuffer_get_gl_type(u64 flags);
-u32 ShaderBuffer_get_gl_accesstype(u64 flags);
-u32 ShaderBuffer_get_gl_datatype(u64 flags);
-
-/* Rendering functions */
-void render_begin(Window* w);
-void render_present(Window* w);
-void drawcall_reset(void);
-void render(Window* w);
-
-/* Misc */
-void r_perspective(f32 fov, Camera *c);
-void r_perspective_ortho(f32 sz, Camera *c);
-
-void r_set_camera(Camera* c);
-void r_reset_camera(Camera* c);
-
-//void window_size_callback(GLFWwindow* window, i32 width, i32 height);
-
-void engine_draw_sprite(Sprite* s, ivec2* pos, f32 scale);
-void engine_draw_sprite_ex(Sprite* s, ivec2* pos, f32 scale,
- Engine_color colormod);
-void engine_draw_model(RenderObject* o, vec3 pos);
-
-Sprite sprite_new(u64 tid, u8 coord);
-
-typedef enum {
- RenderDrawCallType_Text,
- RenderDrawCallType_Sprite,
- RenderDrawCallType_Model,
-} RenderDrawCallType;
-
-typedef struct {
- RenderDrawCallType type;
- union {
- void* data;
- struct {
- Sprite* sprite;
- i32 x;
- i32 y;
- f32 scale;
- } sprite;
- struct {
- RenderObject* model;
- vec3 pos;
- f32 scale;
- } model;
- } data;
-} RenderDrawCall;
-
-// TODO make all the shader buffers a list
-
-RenderObject RenderObject_new(
- Shader* shader,
- u32 texture,
- ShaderBuffer *restrict buffers, usize num_buffers);
-
-int renderbatch_new(RenderBatch* renderbatch, usize count);
-i32 renderbatch_add(RenderBatch* renderbatch, RenderObject* obj, Transform* t);
-void renderbatch_transform(RenderBatch* renderbatch, usize obj_idx, Transform* t);
-int renderbatch_refresh(RenderBatch* renderbatch);
-
-Shader compile_shader(const char* file_path, const ShaderType shader_type);
-Shader compose_shader(Shader *shaders, usize shaders_len);
-void shaders_delete(Shader* shader, usize shader_len);
-
-u32 ComposeShader(u32 *shaders, usize shaders_len);
-
-ShaderType guess_shadertype_from_filename(const char *restrict fname);
-
-Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 height, u8 components);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/rendering/include/engine/rendering/window.h b/src/rendering/include/engine/rendering/window.h
deleted file mode 100644
index a964b38..0000000
--- a/src/rendering/include/engine/rendering/window.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef WINDOW_H
-#define WINDOW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <cglm/ivec2.h>
-
-#include <engine/core/types.h>
-#include <engine/ctrl/input.h>
-
-#ifndef ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS
-extern u64 (*get_time)(void);
-#endif
-
-typedef enum {
- WINDOW_FRAMEWORK_NONE = 0,
- WINDOW_FRAMEWORK_GLFW,
-} Window_framework;
-
-typedef enum {
- WINDOW_RENDERER_NONE = 0,
- WINDOW_RENDERER_OPENGL,
-} Window_renderer;
-
-typedef struct {
- // Specifies the framwork & renderer combo used.
- Window_framework framework;
- Window_renderer renderer;
-
- // Window *buffer* size, in pixels.
- ivec2 windowsize;
-
- // These are used differently depending on the framework / renderer combo.
- // Subject to change to a union of backend-dependent structs
- void* window;
- void* context;
-
- /* The ctrl is probably the only sensible thing in this struct. */
- usize bindings_sz;
- usize bindings_len;
- i_ctx** bindings;
-} Window;
-
-Window* Window_new(const char *restrict title, Window_framework framework, Window_renderer renderer, ivec2 size, u32 flags);
-
-void get_mousepos(double *x, double *y);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/rendering/src/gl.c b/src/rendering/src/gl.c
deleted file mode 100644
index 920518f..0000000
--- a/src/rendering/src/gl.c
+++ /dev/null
@@ -1,281 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <glad/gl.h>
-
-#include <engine/core/types.h>
-#include <engine/core/logging.h>
-
-#include <engine/rendering/rendering.h>
-#include <engine/core/platform.h>
-#include <engine/engine.h>
-
-extern Instance* GLOBAL_PLATFORM;
-
-const char* ShaderType_str[] = {
- [Shader_Error] = "Shader_Error",
- [Shader_Program] = "Shader_Program",
- [Shader_Vertex] = "Shader_Vertex",
- [Shader_Tessellation] = "Shader_Tessellation",
- [Shader_Geometry] = "Shader_Geometry",
- [Shader_Fragment] = "Shader_Fragment",
- [Shader_Compute] = "Shader_Compute",
-};
-
-Shader compile_shader(const char* file_path, const ShaderType shader_type) {
- u32 shaderID = 0;
- GLenum shadertype = GL_INVALID_ENUM;
-
- i32 Result = GL_FALSE;
- i32 infolog_len;
-
- char* source = NULL;
- FILE* file = NULL;
-
- const GladGLContext* gl = GLOBAL_PLATFORM->window->context;
-
- if (file_path == NULL) {
- WARN("Empty path to shader");
- return (Shader){.program = 0, .type = Shader_Error};
- }
-
- switch (shader_type) {
- case Shader_Vertex:
- shadertype = GL_VERTEX_SHADER;
- break;
- case Shader_Fragment:
- shadertype = GL_FRAGMENT_SHADER;
- break;
- default: break;
- }
-
- file = fopen(file_path, "r");
-
- shaderID = gl->CreateShader(shadertype);
- LOG("CREATED SHADER ID %d", shaderID);
-
- if(file != NULL) {
- const usize size = f_get_sz(file);
-
- source = calloc((usize)size + 1, sizeof(char));
-
- // Assume the whole file is successfully read
- fread(source, sizeof(char), (usize)size, file);
-
- fclose(file);
- } else {
- ERROR("Cannot open \"" TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET"\".", file_path);
- return (Shader){.program = 0, .type = Shader_Error};
- }
-
- // Compile shader
- INFO("Compiling shader \"" TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET"\".", file_path);
- char const* src_ptr = source;
- gl->ShaderSource(shaderID, 1, &src_ptr , NULL);
- gl->CompileShader(shaderID);
-
- // Check shader
- gl->GetShaderiv(shaderID, GL_COMPILE_STATUS, &Result);
- gl->GetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infolog_len);
- if ( infolog_len > 0 ) {
- char* msg = calloc((usize)infolog_len + 1, sizeof(char));
- gl->GetShaderInfoLog(shaderID, infolog_len, NULL, msg);
- ERROR("Failed to compile shader: " TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET, msg);
- free(msg);
- }
-
- free(source);
-
- return (Shader){.program = shaderID, .type = shader_type};
-}
-
-
-// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
-u32 load_shaders(
- const GladGLContext* gl,
- const char* vertex_file_path,
- const char* fragment_file_path) {
-
- i32 Result = GL_FALSE;
- i32 infolog_len;
-
- // Create the shaders
- const Shader vertexShader = compile_shader(vertex_file_path, Shader_Vertex);
- const Shader fragmentShader = compile_shader(fragment_file_path, Shader_Fragment);
-
- // Link the program
- INFO("Linking program");
- u32 ProgramID = gl->CreateProgram();
-
- if (vertex_file_path != NULL) gl->AttachShader(ProgramID, vertexShader.program);
- if (fragment_file_path != NULL) gl->AttachShader(ProgramID, fragmentShader.program);
-
- gl->LinkProgram(ProgramID);
-
- // Check the program
- gl->GetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
- gl->GetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &infolog_len);
- if ( infolog_len > 0 ){
- char* msg = calloc((usize)infolog_len + 1, sizeof(char));
- gl->GetShaderInfoLog(ProgramID, infolog_len, NULL, msg);
- ERROR("Compiling shader: " TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET, msg);
- free(msg);
- }
-
- gl->DetachShader(ProgramID, vertexShader.program);
- gl->DetachShader(ProgramID, fragmentShader.program);
-
- //gl->DeleteShader(vertexShader.program);
- //gl->DeleteShader(fragmentShader.program);
-
- return ProgramID;
-}
-
-/* Returns a shader program */
-Shader compose_shader(Shader *shaders, usize shaders_len) {
- const GladGLContext* gl = GLOBAL_PLATFORM->window->context;
- i32 Result = GL_FALSE;
-
- if (shaders_len == 0) {
- ERROR("No shaders provided!");
- return (Shader){.program = 0, .type = Shader_Error};
- }
-
- u32 prog = gl->CreateProgram();
-
- if (prog == 0) {
- ERROR("Failed to create program!");
- return (Shader){.program = 0, .type = Shader_Error};
- }
-
- for (usize i = 0; i < shaders_len; i++) {
- gl->AttachShader(prog, shaders[i].program);
- INFO("Attaching shader %d to %d", shaders[i].program, prog);
- }
-
- gl->LinkProgram(prog);
-
- // Check the program
- gl->GetProgramiv(prog, GL_LINK_STATUS, &Result);
- if (Result != GL_TRUE) {
- // Get the size of the log
- i32 log_len = 0;
- i32 msg_len = 0;
- gl->GetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_len);
- char* msg = calloc((usize)log_len + 1, sizeof(char));
-
- // Copy the log message(s)
- gl->GetProgramInfoLog(prog, log_len, &msg_len, msg);
-
- ERROR("(Compose) Compiling shader:\n" TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET "\n", msg);
- free(msg);
- }
-
- for (usize i = 0; i < shaders_len; i++) {
- gl->DetachShader(prog, shaders[i].program);
- }
-
- return (Shader){.program = prog, .type = Shader_Program};
-}
-
-/* Free up resources associated with `shader` */
-void shaders_delete(Shader* shader, usize shader_len) {
- const GladGLContext* gl = GLOBAL_PLATFORM->window->context;
-
- for (usize i = 0; i < shader_len; i++) {
- gl->DeleteShader(shader[i].program);
- }
-}
-
-GLenum ShaderBuffer_get_gl_access(u64 flags) {
- const ShaderBufferFlag access = ShaderBuffer_get_access_type(flags);
-
- switch(flags & 0b111) {
- case ShaderBuffer_AccessFrequency_stream:
- switch(access) {
- case ShaderBuffer_AccessType_draw: return GL_STREAM_DRAW;
- case ShaderBuffer_AccessType_read: return GL_STREAM_READ;
- case ShaderBuffer_AccessType_copy: return GL_STREAM_COPY;
- default: return GL_STREAM_DRAW;
- }
- case ShaderBuffer_AccessFrequency_static:
- switch(access) {
- case ShaderBuffer_AccessType_draw: return GL_STATIC_DRAW;
- case ShaderBuffer_AccessType_read: return GL_STATIC_READ;
- case ShaderBuffer_AccessType_copy: return GL_STATIC_COPY;
- default: return GL_STATIC_DRAW;
- }
- case ShaderBuffer_AccessFrequency_dynamic:
- switch(access) {
- case ShaderBuffer_AccessType_draw: return GL_DYNAMIC_DRAW;
- case ShaderBuffer_AccessType_read: return GL_DYNAMIC_READ;
- case ShaderBuffer_AccessType_copy: return GL_DYNAMIC_COPY;
- default: return GL_DYNAMIC_DRAW;
- }
- default: return GL_STATIC_DRAW;
- }
-}
-
-RenderObject RenderObject_new(
- Shader* shader,
- u32 texture,
- ShaderBuffer *restrict buffers, usize num_buffers) {
-
- GladGLContext *gl = GLOBAL_PLATFORM->window->context;
- RenderObject o;
-
- gl->GenVertexArrays(1, &(o.vao));
- gl->BindVertexArray(o.vao);
-
- /* For each buffer in the shader, */
- /* The shader should be generalied, */
- for (usize i = 0; i < num_buffers; i++) {
- const usize sz = buffers[i].size_elem * buffers[i].count;
- const u32 b_gl_type = ShaderBuffer_get_gl_type(buffers[i].buffertype);
-
- gl->GenBuffers(1, &(buffers[i].buffername));
- gl->BindBuffer(b_gl_type, buffers[i].buffername);
- gl->BufferData(b_gl_type, (isize)sz, buffers[i].data, ShaderBuffer_get_gl_accesstype(buffers[i].buffertype));
- }
-
- o.shader = *shader;
- o.texture = texture;
- o.buffer = buffers;
- o.buffer_len = num_buffers;
- o.mvp = gl->GetUniformLocation(o.shader.program, "MVP");
-
- // It is very much a non-issue if we don't find the model view projection in
- // the shader. In fact, it is removed from a shader program if it is not used.
- // TODO: Add common uniforms, should be a list of strings (uniform name) &
- // their locations (i32), such as
- // * mouse coords,
- // * time,
- // * delta time,
- // * modelviewprojection,
- // * window size.
- // These should be added to the RenderObject, if found.
-
- // if (o.mvp == -1) {
- // WARN("Unable to find \"MVP\" input in shader program");
- //}
-
- gl->BindVertexArray(0);
-
-
- return o;
-}
-
-ShaderType guess_shadertype_from_filename(const char *restrict fname) {
- const usize path_len = strlen(fname);
-
- if (path_len <= 4) {
- ERROR("Unable to determine shader type from suffix! (%s)", fname);
- return Shader_Error;
- }
-
- if (!strncmp(".vert", &fname[path_len - 5], 5)) { return Shader_Vertex; }
- if (!strncmp(".frag", &fname[path_len - 5], 5)) { return Shader_Fragment; }
-
- return Shader_Error;
-}
diff --git a/src/rendering/src/platform_glfw.c b/src/rendering/src/platform_glfw.c
deleted file mode 100644
index 47638e2..0000000
--- a/src/rendering/src/platform_glfw.c
+++ /dev/null
@@ -1,232 +0,0 @@
-// Required for OpenGL rendering backend
-#define GLAD_GL_IMPLEMENTATION
-#include <glad/gl.h>
-#undef GLAD_GL_IMPLEMENTATION
-
-// TODO: import vulkan thingymajig once I get around to it.
-// TODO: move OpenGL initialization code at some point
-
-#undef GLFW_INCLUDE_NONE
-#include <GLFW/glfw3.h>
-
-#include <engine/core/logging.h>
-
-#include <engine/rendering/platform.h>
-
-static void window_resize_callback(GLFWwindow *restrict window, int width, int height);
-static void framebuffer_resize_callback(GLFWwindow *restrict window, int width, int height);
-static void glfw_err_callback(int code, const char* description);
-static void render_init_opengl(Window *restrict w, const u32 flags);
-static void window_size(GLFWwindow *restrict w, ivec2 *restrict dst);
-
-
-Window* window_init_glfw(const char *restrict windowtitle, ivec2 windowsize, const u32 flags) {
- Window* ret = NULL;
- GLFWwindow* window = NULL;
-
- glfwSetErrorCallback(&glfw_err_callback);
-
- INFO_("initializing glfw...");
- if (glfwInit() == GLFW_FALSE) {
- const char *desc;
- int code = glfwGetError(&desc);
- ERROR("failed to initialize glfw [%d]: %s\n", code, *desc);
- exit(EXIT_FAILURE);
- } else
- printf("ok\n");
-
-
- INFO_("initializing window...");
- //glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
- if (!(flags & DAW_WINDOW_RESIZEABLE)) {
- glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
- }
-
- glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
- glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
-
- glfwWindowHint(GLFW_SAMPLES, 0); // Disable anti aliasing
-
- // Use a modern opengl version
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
-
- // Lean and mean
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
-#ifdef __APPLE__
- // To make MacOS happy; should not be needed
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-#endif
-
- /* "On Wayland specifically, you need to swap the buffers
- * once of a window for it to become visible." */
- {
- GLFWmonitor* mon = NULL;
- if (flags & DAW_WINDOW_FULLSCREEN) mon = glfwGetPrimaryMonitor();
-
- window = glfwCreateWindow(windowsize[0], windowsize[1], windowtitle, mon, NULL);
- }
-
- if (window == NULL) {
- ERROR("Failed to create GLFW window!\n");
- const char *desc;
- int code = glfwGetError(&desc);
- ERROR("failed to initialize glfw window [%d]: %s\n", code, desc);
- exit(EXIT_FAILURE);
- } else
- printf("ok\n");
-
- // Setup callbacks
- glfwSetFramebufferSizeCallback(window, framebuffer_resize_callback);
- glfwSetWindowSizeCallback(window, window_resize_callback);
- glfwSetKeyCallback(window, (GLFWkeyfun)key_callback);
-
- // Create the window datastructure
- ret = (Window*)calloc(1, sizeof(Window));
- ret->framework = WINDOW_FRAMEWORK_GLFW;
- ret->renderer = WINDOW_RENDERER_NONE;
- ret->window = window;
- /* Last parameter is used for the renderer */
- ret->context = NULL;
-
- {
- ivec2 wsize;
- vec2 wscaling;
- glfwGetWindowContentScale(window, &wscaling[0], &wscaling[1]);
- glfwGetWindowSize(window, &wsize[0], &wsize[1]);
-
- ret->windowsize[0] = (i32)((f32)wsize[0] * wscaling[0]);
- ret->windowsize[1] = (i32)((f32)wsize[1] * wscaling[1]);
-
- INFO("WINDOW CONTENT SCALING: %.2f x %.2f", wscaling[0], wscaling[1]);
- INFO("WINDOW SIZE: %d x %d -> %d x %d", wsize[0], wsize[1], ret->windowsize[0], ret->windowsize[1]);
- }
-
- // TODO: set this to `ret` once all the garbage is moved to `struct Window`
- glfwSetWindowUserPointer(window, (void*)ret);
-
- render_init_opengl(ret, flags);
-
- return ret;
-}
-
-void window_destroy_glfw(Window *restrict w) {
- glfwDestroyWindow(w->window);
- w->window = NULL;
-
- // If we ever do multi-window support, we need to make sure this is the last
- // window before terminating
- glfwTerminate();
-
- switch(w->renderer) {
- case WINDOW_RENDERER_OPENGL:
- // Missing unloader function in glad MX library
- free(w->context);
- w->context = NULL;
- break;
- default:
- ERROR("Destroying unknown renderer type.");
- }
-}
-
-void window_resize_glfw(Window *restrict window, int width, int height) {
- window_resize_callback(window->window, width, height);
- framebuffer_resize_callback(window->window, width, height);
-}
-
-bool window_should_close_glfw(Window *restrict window) {
- return glfwWindowShouldClose(window->window);
-}
-
-void window_poll_glfw(void) {
- glfwPollEvents();
-}
-
-// Helper function implementations
-static void window_resize_callback(GLFWwindow* window, int width, int height) {
- (void)width; (void)height;
- Window* w = glfwGetWindowUserPointer(window);
- glfwSwapBuffers(window);
- if (w != NULL) {
- const GladGLContext* gl = w->context;
- gl->Finish();
- }
-}
-
-static void framebuffer_resize_callback(GLFWwindow* window, int width, int height) {
- (void)width; (void)height;
- Window* w = glfwGetWindowUserPointer(window);
- if (w != NULL) {
- const GladGLContext* gl = w->context;
- //TODO: Move the camera to window->renderer
- //Camera* c = w->cam;
- gl->Viewport(0,0, width, height);
- w->windowsize[0] = width;
- w->windowsize[1] = height;
-
- //r_reset_camera(c);
- }
-}
-
-static void glfw_err_callback(int code, const char* description) {
- ERROR("glfw [%d]: %s\n", code, description);
- // Terminate?
- exit(EXIT_FAILURE);
-}
-
-static void render_init_opengl(Window *restrict w, const u32 flags) {
- if (w->renderer != WINDOW_RENDERER_NONE || w->context != NULL) {
- ERROR("Window already initialized with a renderer!");
- return;
- }
-
- // This is GLFW specific
- glfwMakeContextCurrent(w->window);
-
- GladGLContext* ctx = (GladGLContext*)malloc(sizeof(GladGLContext));
- if (!ctx) {
- ERROR("Failed to allocate memory for context");
- }
-
- int version = gladLoadGLContext(ctx, glfwGetProcAddress);
- INFO("Loaded OpenGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
-
- if (ctx == NULL) {
- ERROR("Failed to create glad context");
- exit(EXIT_FAILURE);
- }
-
- if (flags & DAW_WINDOW_VSYNC) {
- glfwSwapInterval(1);
- } else {
- glfwSwapInterval(0);
- }
-
-
- ctx->Viewport(0, 0, w->windowsize[0], w->windowsize[1]);
-
-#ifdef _DEBUG
- ctx->ClearColor((float)0x10 / 255.f, (float)0x0a / 255.f, (float)0x33 / 255.f, 0.f);
-#else
- ctx->ClearColor(0x0, 0x0, 0x0, 0.f);
-#endif
-
- // Make sure faces closest to the camera are drawn on-top of faces that are
- // further away
- ctx->Enable(GL_DEPTH_TEST);
- ctx->DepthFunc(GL_LESS);
-
- w->context = ctx;
- w->renderer = WINDOW_RENDERER_OPENGL;
-}
-
-static void window_size(GLFWwindow *restrict w, ivec2 *restrict dst) {
- ivec2 wsize;
- vec2 wscaling;
- glfwGetWindowContentScale(w, &wscaling[0], &wscaling[1]);
- glfwGetWindowSize(w, &wsize[0], &wsize[1]);
-
- *dst[0] = (i32)((f32)wsize[0] * wscaling[0]);
- *dst[1] = (i32)((f32)wsize[1] * wscaling[1]);
-}
diff --git a/src/rendering/src/rendering.c b/src/rendering/src/rendering.c
deleted file mode 100644
index 8932cfc..0000000
--- a/src/rendering/src/rendering.c
+++ /dev/null
@@ -1,696 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-
-#include <glad/gl.h>
-#include <GLFW/glfw3.h>
-#include <cglm/cam.h>
-#include <cglm/vec2.h>
-#include <cglm/mat4.h>
-
-
-#include <engine/engine.h>
-#include <engine/utils.h>
-#include <engine/rendering/rendering.h>
-
-
-/* Extern globals */
-extern Instance* GLOBAL_PLATFORM;
-
-/* Globals */
-#define drawcall_limit (64 * 1024)
-RenderDrawCall drawcalls[drawcall_limit];
-i32 drawcall_len = 0;
-
-usize
-ShaderBufferDataType_size(u16 flags) {
- const ShaderBufferFlag t = ShaderBuffer_get_data_type(flags);
- switch (t) {
- case ShaderBuffer_DataType_nil: return 0;
- case ShaderBuffer_DataType_f32: return sizeof(f32);
- case ShaderBuffer_DataType_f64: return sizeof(f64);
- case ShaderBuffer_DataType_i8: return sizeof(i8);
- case ShaderBuffer_DataType_i16: return sizeof(i16);
- case ShaderBuffer_DataType_i32: return sizeof(i32);
- case ShaderBuffer_DataType_i64: return sizeof(i64);
- case ShaderBuffer_DataType_u8: return sizeof(u8);
- case ShaderBuffer_DataType_u16: return sizeof(u16);
- case ShaderBuffer_DataType_u32: return sizeof(u32);
- case ShaderBuffer_DataType_u64: return sizeof(u64);
- default: return 0;
- }
-}
-
-ShaderBufferFlag ShaderBuffer_get_access_frequency(u64 flags) { return flags & (0b111 << 0); }
-ShaderBufferFlag ShaderBuffer_get_access_type(u64 flags) { return flags & (0b111 << 3); }
-ShaderBufferFlag ShaderBuffer_get_type(u64 flags) { return flags & (0b111 << 6); }
-ShaderBufferFlag ShaderBuffer_get_data_type(u64 flags) { return flags & (0b1111 << 9); }
-
-u32 ShaderBuffer_get_gl_type(u64 flags) {
- switch(ShaderBuffer_get_type(flags)) {
- case ShaderBuffer_Type_vertexData:
- return GL_ARRAY_BUFFER;
- case ShaderBuffer_Type_vertexPosition:
- return GL_ARRAY_BUFFER;
- case ShaderBuffer_Type_vertexIndex:
- return GL_ELEMENT_ARRAY_BUFFER;
- default:
- return GL_ARRAY_BUFFER;
- }
-}
-
-
-u32 ShaderBuffer_get_gl_accesstype(u64 flags) {
- switch (ShaderBuffer_get_access_frequency(flags)) {
- case ShaderBuffer_AccessFrequency_stream:
- switch (ShaderBuffer_get_access_type(flags)) {
- case ShaderBuffer_AccessType_draw: return GL_STREAM_DRAW;
- case ShaderBuffer_AccessType_read: return GL_STREAM_READ;
- case ShaderBuffer_AccessType_copy: return GL_STREAM_COPY;
- default: return 0;
- }
-
- case ShaderBuffer_AccessFrequency_static:
- switch (ShaderBuffer_get_access_type(flags)) {
- case ShaderBuffer_AccessType_draw: return GL_STATIC_DRAW;
- case ShaderBuffer_AccessType_read: return GL_STATIC_READ;
- case ShaderBuffer_AccessType_copy: return GL_STATIC_COPY;
- default: return 0;
- }
- case ShaderBuffer_AccessFrequency_dynamic:
- switch (ShaderBuffer_get_access_type(flags)) {
- case ShaderBuffer_AccessType_draw: return GL_DYNAMIC_DRAW;
- case ShaderBuffer_AccessType_read: return GL_DYNAMIC_READ;
- case ShaderBuffer_AccessType_copy: return GL_DYNAMIC_COPY;
- default: return 0;
- }
- default: return 0;
- }
-}
-
-ShaderBufferFlag ShaderBuffer_get_gl_datatype(u64 flags) {
- switch (ShaderBuffer_get_data_type(flags)) {
- case ShaderBuffer_DataType_nil: return GL_NONE;
-
- case ShaderBuffer_DataType_f32: return GL_FLOAT;
- case ShaderBuffer_DataType_f64: return GL_DOUBLE;
-
- case ShaderBuffer_DataType_i8: return GL_BYTE;
- case ShaderBuffer_DataType_i16: return GL_SHORT;
- case ShaderBuffer_DataType_i32: return GL_INT;
- case ShaderBuffer_DataType_i64: return GL_INT64_ARB;
-
- case ShaderBuffer_DataType_u8: return GL_UNSIGNED_BYTE;
- case ShaderBuffer_DataType_u16: return GL_UNSIGNED_SHORT;
- case ShaderBuffer_DataType_u32: return GL_UNSIGNED_INT;
- case ShaderBuffer_DataType_u64: return GL_UNSIGNED_INT64_ARB;
-
- default: return GL_NONE;
- }
-}
-
-// `RenderBatch` is used for batch rendering. The struct is used as a
-// "management" parent structure to keep track of multiple `RenderObject`s that
-// are put into a final `RenderObject` to render.
-// `RenderObject`s are copied to the internal `models` array, to which the
-// pointer to the copied RenderObject is returned, or NULL if an error occurred.
-// If changes are made to a render object the batch should be refreshed.
-// Renderbatches assumes that all buffer layouts are the same.
-
-// renderbatch_new: Create a new render batch with space for `count` models.
-int renderbatch_new(RenderBatch* renderbatch, usize count) {
- /* TODO: Make it such that you can add identical models with different
- * transforms, so you instead of relying on renderobject[n] to copy to the
- * renderobject we have something like
- *
- * model {
- * renderobj_idx // index in renderobj[n] that this model represents
- * transform {
- * size;
- * pos;
- * rotation;
- * };
- * };
- *
- * For this to work we will likely need to extend the shaderbuffer struct to
- * also hold what type of data the buffer contains, s.t. we can apply the
- * transformation to only geometry data.
- *
- * We'll therefore have both data type and buffer type stored somehow,
- * maybe like we did the ShaderBufferDataType.
- * TODO: Also use shaderbuffertype.
- * */
- if (renderbatch == NULL) {
- ERROR("renderbatch was null!");
- return -1;
- }
-
- usize numisnstances = count;
-
- if (count == 0) {
- // Just allocate enough for a couple hundred
- count = 256;
- numisnstances = count * 4;
- }
-
-
- renderbatch->msize = sizeof(RenderObject) * count;
- renderbatch->mcount = 0;
- renderbatch->inst_size = sizeof(BatchModelInstance) * numisnstances;
- renderbatch->inst_count = 0;
- renderbatch->models = (RenderObject**)calloc(count, sizeof(RenderObject*));
-
- if (renderbatch->models == NULL) {
- ERROR("Failed to allocate %lu size of bytes for models array!", sizeof(RenderObject*) * count);
- return -1;
- }
-
- renderbatch->instances = (BatchModelInstance*)calloc(numisnstances, sizeof(BatchModelInstance));
-
- if (renderbatch->instances == NULL) {
- ERROR("Failed to allocate %lu size of bytes for batch instances array!", sizeof(BatchModelInstance) * numisnstances);
- return -1;
- }
-
- memset(&(renderbatch->renderobj), 0, sizeof(RenderObject));
-
- return 0;
-}
-
-// Appends the data in src onto dst. More space for `data` is allocated if
-// necessary, in which case a pointer to the new ShaderBuffer is returned.
-ShaderBuffer* shaderbuffer_cat(ShaderBuffer* dst, ShaderBuffer *restrict src) {
- if (dst == NULL) {
- ERROR("dst is null");
- }
- else if (src == NULL) {
- ERROR("src is null");
- }
-
- if (ShaderBuffer_get_data_type(dst->buffertype) != ShaderBuffer_get_data_type(src->buffertype)) {
- ERROR("Failed to concatenate shader buffers, incompatible datatypes: %d != %d", dst->buffertype, src->buffertype);
- }
- if (dst->components != src->components) {
- ERROR("Failed to concatenate shader buffers, incompatible number of components: %d != %d", dst->components, src->components);
- }
-
- // Assume that we single-handedly control the pointer to the data, copy and
- // free the stuff.
-
- // Verify the size
- const usize sz_src = src->size_elem * src->count;
- const usize sz_dst = dst->size_elem * dst->count;
- if (dst->data == NULL || sz_dst + sz_src >= dst->size) {
- const usize sz_new = (1 + ((sz_src + sz_dst) / 4096)) * 4096;
- // Resize dst size
- dst->data = realloc(dst->data, sz_new);
- dst->size = sz_new;
- }
-
- memcpy(dst->data + sz_dst, src->data, sz_src);
-
- dst->count += src->count;
-
- return dst;
-}
-
-// Add a render object to the render batch.
-i32 renderbatch_add(RenderBatch* renderbatch, RenderObject* obj, Transform* t) {
- // Check if its a valid renderbatch
- if (renderbatch == NULL) {
- ERROR("renderbatch was null!");
- return -1;
- }
-
- // Check whether we have initialized models & instance memory
- if (renderbatch->models == NULL) {
- const usize sz = 8 * sizeof(RenderObject*);
- renderbatch->models = calloc(8, sizeof(RenderObject*));
- renderbatch->msize = sz;
- renderbatch->mcount = 0;
- }
-
- if (renderbatch->instances == NULL) {
- // Allocate enough for 4 times the models
- const usize modelbufsz = renderbatch->msize / sizeof(RenderObject*);
- const usize sz = 4 * modelbufsz * sizeof(BatchModelInstance);
- renderbatch->instances = calloc(4 * modelbufsz, sizeof(BatchModelInstance));
- renderbatch->inst_size = sz;
- renderbatch->inst_count = 0;
- }
-
- // The index of the model
- isize model_idx = -1;
-
- // Find the model, to check if it already exists
- for (usize i = 0; i < renderbatch->mcount; i++) {
- // Compare the model pointers
- if (obj == renderbatch->models[i]) {
- model_idx = (isize)i;
- break;
- }
- }
-
- // Model doesn't exist, add it
- if (-1 == model_idx) {
- // Check if there's room enough
- if ((1 + renderbatch->mcount) * sizeof(RenderObject*) > renderbatch->msize) {
- // Realloc if necessary
- const usize sz = renderbatch->msize * 2;
- renderbatch->models = realloc(renderbatch->models, sz);
- renderbatch->msize = sz;
- }
-
- // If this is the first model, we want to copy the renderobj, and
- // shaderbuffer parameters.
- if (renderbatch->mcount == 0) {
- // Shader, VAO, modelviewprojection, and texture, are set when the shaderobj
- // is actually created with RenderObject_new later.
- // The number of buffers should be the same.
- //renderbatch->renderobj.shader = obj->shader;
- //renderbatch->renderobj.texture = obj->texture;
-
- renderbatch->renderobj.buffer_len = obj->buffer_len;
- if (renderbatch->renderobj.buffer == NULL) {
- renderbatch->renderobj.buffer = calloc(obj->buffer_len, sizeof(ShaderBuffer));
- } else {
- ERROR("RenderObj buffer is already initialized!");
- return -1;
- }
-
- // Copy each buffers parameters
- for (usize i = 0; i < renderbatch->renderobj.buffer_len; i++) {
- renderbatch->renderobj.buffer[i].buffername = 0;
- renderbatch->renderobj.buffer[i].buffertype = obj->buffer[i].buffertype;
- // Size and count should be zero
-
- renderbatch->renderobj.buffer[i].components = obj->buffer[i].components;
- renderbatch->renderobj.buffer[i].size_elem = obj->buffer[i].size_elem;
- // Data should also be null
- }
- }
-
- //// Only concatenate the buffers once we refresh
- //for (usize i = 0; i < renderbatch->renderobj.buffer_len; i++) {
- // shaderbuffer_cat(&renderbatch->renderobj.buffer[i], &obj->buffer[i]);
- //}
-
- model_idx = (isize)renderbatch->mcount;
- renderbatch->models[renderbatch->mcount++] = obj;
- }
-
- // Create batch instance
- // Check if there's room enough
- if ((1 + renderbatch->inst_count) * sizeof(BatchModelInstance) > renderbatch->inst_size) {
- // Realloc if necessary
- const usize sz = renderbatch->inst_size * 2;
- renderbatch->instances = realloc(renderbatch->instances, sz);
- renderbatch->inst_size = sz;
- }
-
- BatchModelInstance inst = {
- .model_idx = (usize)model_idx,
- .transform = *t,
- };
-
- // Add it to the batch
- renderbatch->instances[renderbatch->inst_count++] = inst;
-
- // Return instance index
- return (i32)renderbatch->inst_count - 1;
-}
-
-void renderbatch_transform(RenderBatch* renderbatch, usize obj_idx, Transform* t) {
- // TODO: Combine transformation, ie. pos' += pos, etc.
- const usize m = renderbatch->instances[obj_idx].model_idx;
- const RenderObject* model = renderbatch->models[m];
- renderbatch->instances[obj_idx].transform = *t;
-
- if(renderbatch->inst_count < obj_idx) {
- ERROR("renderbatch_transform: object index is outside range!");
- return;
- }
- /* TODO: Update the model data, we might need to
- * 0. Iteratively go through each renderobj buffer, to find a vertexPosition
- * buffer,
- * 1. Calculate the models start index in the renderobj,
- * 2. Apply transformation to the model in the renderobj buffer.
- * */
- usize b;
- for (b = 0; b < renderbatch->renderobj.buffer_len; b++) {
- if (ShaderBuffer_Type_vertexPosition != ShaderBuffer_get_type(renderbatch->renderobj.buffer[b].buffertype)
- || ShaderBuffer_DataType_f32 != ShaderBuffer_get_data_type(renderbatch->renderobj.buffer[b].buffertype)) {
- continue;
- }
- }
-
- usize offset = 0;
- for (usize i = 0; i < obj_idx; i++) {
- const usize idx = renderbatch->instances[i].model_idx;
- offset += renderbatch->models[idx]->buffer->size_elem
- * renderbatch->models[idx]->buffer->count;
- }
-
- float *data = renderbatch->renderobj.buffer[b].data;
- data = &data[offset];
- const usize len = model->buffer[b].count;
-
- Transform tt = renderbatch->instances[obj_idx].transform;
- if (model->buffer[b].components == 2) {
- for (usize v = 0; v < len; v += 2) {
- // scale
- // rotate
- // offset
- glm_vec2_add(&data[v], tt.position, &data[v]);
- }
- }
- else if (model->buffer[b].components == 3) {
- for (usize v = 0; v < len; v += 3) {
- // scale
- // rotate
- // offset
- glm_vec3_add(&data[v], tt.position, &data[v]);
- }
- }
-}
-
-// renderbatch_refresh: Copy all instances/models in the renderbatch to the
-// batchs' model.
-int renderbatch_refresh(RenderBatch* renderbatch) {
- const usize bufs = renderbatch->renderobj.buffer_len;
- usize *offsets = calloc(bufs, sizeof(usize));
-
- // Reset renderobj buffers
- for (usize b = 0; b < renderbatch->renderobj.buffer_len; b++) {
- // Zero the old data
- renderbatch->renderobj.buffer[b].count = 0;
- memset(renderbatch->renderobj.buffer[b].data, 0, renderbatch->renderobj.buffer[b].size);
- }
-
- // Copy the instances models buffers, and vertex position buffers with translations applied
- for (usize i = 0; i < renderbatch->inst_count; i++) {
- const usize m = renderbatch->instances[i].model_idx;
- const RenderObject* model = renderbatch->models[m];
- Transform t = renderbatch->instances[i].transform;
-
- for (usize b = 0; b < renderbatch->renderobj.buffer_len; b++) {
- shaderbuffer_cat(&renderbatch->renderobj.buffer[b], &model->buffer[b]);
-
- if (ShaderBuffer_Type_vertexPosition == ShaderBuffer_get_type(renderbatch->renderobj.buffer[b].buffertype)) {
- if (ShaderBuffer_DataType_f32 != ShaderBuffer_get_data_type(renderbatch->renderobj.buffer[b].buffertype)) {
- WARN("Buffer data type is not f32, skipping transformation...");
- continue;
- }
- // Apply transformation in renderbatch buffer-memory
-
- float *data = renderbatch->renderobj.buffer[b].data;
- const usize len = model->buffer[b].count;
- // Data points to the start of the model in renderobj
- data = &data[renderbatch->renderobj.buffer[b].count - len];
-
- if (model->buffer[b].components == 2) {
- for (usize v = 0; v < len; v += 2) {
- // scale
- // rotate
- // offset
- glm_vec2_add(&data[v], t.position, &data[v]);
- }
- }
- else if (model->buffer[b].components == 3) {
- for (usize v = 0; v < len; v += 3) {
- // scale
- // rotate
- // offset
- glm_vec3_add(&data[v], t.position, &data[v]);
- }
- }
- }
- }
- }
-
- free(offsets);
- return 0;
-}
-
-
-/* Implementations */
-
-/* Clear the screen,
- * To be used inbetween draw calls */
-void render_begin(Window* w) {
- glfwMakeContextCurrent(w->window);
- ((GladGLContext*)(w->context))->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-void render_present(Window* w) {
- /* This is GL specific, TODO: move the GL-specific code elsewhere. Maybe make
- * this whole present GL specific? assign it as a fn ptr in the Window struct? */
- GladGLContext *restrict gl = w->context;
- Camera c = *GLOBAL_PLATFORM->cam;
-
- mat4 view; // view
- vec3 angle; // viewing angle / direction of the camera
- mat4 camera_matrix;
-
- glm_vec3_sub(c.pos, c.dir, angle);
- glm_lookat(c.pos, angle, GLM_YUP, view);
- glm_mat4_mul(c.per, view, camera_matrix);
-
- for (i32 drawcall_idx = 0; drawcall_idx < drawcall_len; drawcall_idx++) {
- RenderDrawCall dc = drawcalls[drawcall_idx];
- switch (dc.type) {
- case RenderDrawCallType_Sprite: {
- // TODO render a quad
- } break;
-
- case RenderDrawCallType_Model: {
-
- // bind shader program
- // - set uniforms
- // bind vertex array
- // bind index buffer
-
-
- RenderObject* o = dc.data.model.model;
- vec3 pos;
- glm_vec3_copy(dc.data.model.pos, pos);
-
- gl->UseProgram(o->shader.program);
- // TODO: Use texture atlas
- gl->ActiveTexture(GL_TEXTURE0);
- gl->BindTexture(GL_TEXTURE_2D, o->texture);
-
- {
- mat4 model = GLM_MAT4_IDENTITY_INIT;
- mat4 modelviewprojection;
-
- model[3][0] = pos[0];
- model[3][1] = pos[1];
- model[3][2] = pos[2];
-
- // modelviewprojection = p * view * model
- glm_mat4_mul(model, camera_matrix, modelviewprojection);
-
- // TODO: Do this only once during initialization
- gl->UniformMatrix4fv(o->mvp, 1, GL_FALSE, &modelviewprojection[0][0]);
- }
-
- // TODO the buffers need to be abstracted a bit more
- gl->BindVertexArray(o->vao);
-
- ShaderBuffer* ibo = NULL;
- for (usize i = 0; i < o->buffer_len; i++) {
- const u32 b_gl_type = ShaderBuffer_get_gl_type(o->buffer[i].buffertype);
- if (b_gl_type == GL_ELEMENT_ARRAY_BUFFER) {
- ibo = &o->buffer[i];
- }
-
- gl->EnableVertexAttribArray((u32)i);
- gl->BindBuffer(b_gl_type, o->buffer[i].buffername);
- gl->VertexAttribPointer(
- // index of the attribute
- (u32)i,
- // number of component
- (i32)o->buffer[i].components,
- // type
- ShaderBuffer_get_gl_datatype(o->buffer[i].buffertype),
- // normalized?
- GL_FALSE,
- // stride
- 0,
- // array buffer offset
- (void*)0
- );
- }
-
- // Draw the model !
- const i32 sz = (i32)(o->buffer->count * o->buffer->size_elem);
- if (ibo) {
- gl->DrawElements(
- GL_TRIANGLES,
- (i32)ibo->count,
- ShaderBuffer_get_gl_datatype(ibo->buffertype),
- (void*)0
- );
- } else {
- // Starting from vertex 0; 3 vertices total -> 1 triangle
- gl->DrawArrays(GL_TRIANGLES, 0, sz);
- }
-
- for (u32 i = 0; i < o->buffer_len; i++) {
- gl->DisableVertexAttribArray(i);
- }
-
- gl->BindVertexArray(0);
-
- //if (i == 8) {
- // printf("\r obj: %.3f", (double)(get_time() - t) * 1000.);
- //}
- } break;
- default:
- break;
- }
- }
-
- drawcall_len = 0;
-
- glfwSwapBuffers(w->window);
-}
-
-void drawcall_reset(void) {
- drawcall_len = 0;
- memset(drawcalls, 0, sizeof(RenderDrawCall) * drawcall_limit);
-}
-
-void r_perspective(f32 fov, Camera *c) {
- const f32 ratio = (f32)GLOBAL_PLATFORM->window->windowsize[0]
- / (f32)GLOBAL_PLATFORM->window->windowsize[1];
-
- c->type = Camera_Perspective;
- c->parameters.perspective.fov = fov;
-
- glm_perspective(glm_rad(fov), ratio, 0.1f, 100.0f, c->per);
-}
-
-void r_perspective_ortho(f32 sz, Camera *c) {
- const f32 ratio = (f32)GLOBAL_PLATFORM->window->windowsize[0]
- / (f32)GLOBAL_PLATFORM->window->windowsize[1];
-
- c->type = Camera_Orthogonal;
- c->parameters.orthogonal.sz = sz;
-
- glm_ortho(-sz * ratio, sz * ratio, -sz, sz, -sz * 10.f, sz * 10.f, c->per);
-}
-
-void r_set_camera(Camera* c) {
- GLOBAL_PLATFORM->cam = c;
-}
-
-
-void r_reset_camera(Camera* c) {
- if (c->type == Camera_Perspective) {
- r_perspective(c->parameters.perspective.fov, c);
- }
- else if (c->type == Camera_Orthogonal) {
- r_perspective_ortho(c->parameters.orthogonal.sz, c);
- }
-}
-
-void engine_draw_sprite(Sprite* s, ivec2* pos, f32 scale) {
- if (drawcall_len + 1 >= drawcall_limit) return;
-#ifdef _DEBUG
- if (s == NULL) __asm__("int3;");
-#endif
- drawcalls[drawcall_len++] =
- (RenderDrawCall){.type = RenderDrawCallType_Sprite,
- .data.sprite = {
- .sprite = s,
- .x = *pos[0],
- .y = *pos[1],
- .scale = scale,
- //.mod = {0xFF, 0xFF, 0xFF, 0xFF},
- }};
-}
-
-void engine_draw_sprite_ex(Sprite* s, ivec2* pos, f32 scale,
- Engine_color colormod) {
- if (drawcall_len + 1 >= drawcall_limit) return;
-#ifdef _DEBUG
- if (s == NULL) __asm__("int3;");
-#endif
- drawcalls[drawcall_len++] = (RenderDrawCall){
- .type = RenderDrawCallType_Sprite,
- .data.sprite = {
- .sprite = s,
- .x = *pos[0],
- .y = *pos[1],
- .scale = scale,
- //.mod = {colormod.r, colormod.g, colormod.b, colormod.a},
- }};
-}
-
-void engine_draw_model(RenderObject* o, vec3 pos) {
- if (drawcall_len + 1 >= drawcall_limit) return;
-#ifdef _DEBUG
- if (o == NULL) __asm__("int3;");
-#endif
- RenderDrawCall dc = {
- .type = RenderDrawCallType_Model,
- .data.model = {
- .model = o,
- .scale = 1.f,
- }};
-
-
- glm_vec3_copy(pos, dc.data.model.pos);
-
- drawcalls[drawcall_len++] = dc;
-}
-
-Sprite sprite_new(u64 tid, u8 coord) {
- const i32 ts = 16;
- // FIXME; used to be
- //((struct Resources*)GLOBAL_PLATFORM->data)->textures[tid]->tilesize;
- return (Sprite){
- .texture_id = (u32)tid,
- {
- ts * (coord & 0x0F),
- ts * ((coord & 0xF0) >> 4),
- }};
-}
-
-Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 height, u8 components) {
- Window* restrict w = GLOBAL_PLATFORM->window;
- Texture t;
- t.width = width;
- t.height = height;
-
- if (w->renderer != WINDOW_RENDERER_OPENGL) {
- ERROR("createTextureFromImageData not implemented for chosen renderer!");
- return (Texture){.id = 0, .width = 0, .height = 0};
- }
-
- const GladGLContext* gl = w->context;
-
- gl->GenTextures(1, &t.id);
- gl->BindTexture(GL_TEXTURE_2D, t.id);
- u32 err = gl->GetError();
- if (err) {
- ERROR("Failed to bind texture from image data!");
- }
-
- /* TODO: Support more formats than rgb and rgba, such as gray, gray/alpha, etc.*/
- u32 format = GL_RGB;
- if (components == 4) format = GL_RGBA;
-
- /* TODO: Don't force internal format to RGB */
-
- gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format,
- GL_UNSIGNED_BYTE, image_data);
-
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- gl->BindTexture(GL_TEXTURE_2D, 0);
-
- return t;
-}
diff --git a/src/rendering/src/window.c b/src/rendering/src/window.c
deleted file mode 100644
index d761543..0000000
--- a/src/rendering/src/window.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <time.h>
-
-/* TODO: REMOVE THIS INCLUSION */
-#include <engine/engine.h>
-
-#include <engine/core/types.h>
-#include <engine/core/logging.h>
-
-#define ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS
-#include <engine/rendering/window.h>
-#undef ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS
-
-#include <engine/rendering/platform_glfw.h>
-
-#include <glad/gl.h>
-
-#undef GLFW_INCLUDE_NONE
-#include <GLFW/glfw3.h>
-
-#include <cglm/ivec2.h>
-
-extern Instance* GLOBAL_PLATFORM;
-
-static inline u64 platform_get_time_usec(void) {
- struct timespec t;
- int res = clock_gettime(CLOCK_MONOTONIC, &t);
- if (res != 0) {
- // TODO: Check errno
- WARN("Failed to get system time");
- }
- return (u64)(t.tv_sec * 1000000 + t.tv_nsec / 1000);
-}
-
-/* wrapper to get time in ms */
-u64 (*get_time)(void) = platform_get_time_usec;
-
-
-#define DAW_WINDOW_VSYNC (1 << 0)
-#define DAW_WINDOW_FULLSCREEN (1 << 1)
-#define DAW_WINDOW_RESIZEABLE (1 << 2)
-
-// Wrapper to get a specific window and set up related structures.
-Window* Window_new(const char *restrict title, Window_framework framework, Window_renderer renderer, ivec2 size, u32 flags) {
- Window* w = NULL;
-
- switch (framework) {
- case WINDOW_FRAMEWORK_GLFW:
- switch (renderer) {
- case WINDOW_RENDERER_OPENGL:
- /* For now, pass instance as NULL, fix it once all the necessary bs is
- * out of struct Instance */
- w = Platform_GLFW.window_init(title, size, flags);
-
- w->bindings = NULL;
- w->bindings_sz = 0;
- w->bindings_len = 0;
-
- /// TODO
- //w->cam = &default_camera;
- return w;
- break;
- default:
- ERROR("Unsupported renderer.");
- }
- break;
- default:
- ERROR("Unsupported framework.");
- }
- return NULL;
-}
-
-void get_mousepos(double *x, double *y) {
- Window* w = GLOBAL_PLATFORM->window;
-
- switch(w->framework) {
- case WINDOW_FRAMEWORK_GLFW:
- glfwGetCursorPos(GLOBAL_PLATFORM->window->window, x, y);
- break;
- default:
- ERROR("get_mouse_pos not implemented for chosen framework.");
- }
-
-}