summaryrefslogtreecommitdiff
path: root/src/rendering
diff options
context:
space:
mode:
author0scar <qgt268@alumni.ku.dk>2024-02-06 11:52:32 +0000
committer0scar <qgt268@alumni.ku.dk>2024-02-06 11:52:32 +0000
commitc7a3dcdc8a26eb5bf98ce2079abd66fd64534459 (patch)
treeff5c572f94c3bf3e11e7f9e75e617d4454cc263a /src/rendering
parent3705b14a4b2ac0d6baa418f08991424cfad89891 (diff)
Fixup window handling & rendering
Diffstat (limited to 'src/rendering')
-rw-r--r--src/rendering/include/engine/rendering/rendering.h62
-rw-r--r--src/rendering/include/engine/rendering/window.h43
-rw-r--r--src/rendering/src/gl.c119
-rw-r--r--src/rendering/src/rendering.c30
-rw-r--r--src/rendering/src/window.c185
5 files changed, 384 insertions, 55 deletions
diff --git a/src/rendering/include/engine/rendering/rendering.h b/src/rendering/include/engine/rendering/rendering.h
index 6ae6535..4bfbf16 100644
--- a/src/rendering/include/engine/rendering/rendering.h
+++ b/src/rendering/include/engine/rendering/rendering.h
@@ -30,43 +30,42 @@ typedef struct {
#include <engine/ui.h>
/* Rendering functions */
-void render_begin(Window* w);
-void render_present(Window* w);
+void render_begin(Window w);
+void render_present(Window w);
void drawcall_reset(void);
-void render(Window* w);
+void render(Window w);
/* Misc */
-void window_size_callback(GLFWwindow* window, i32 width, i32 height);
-void engine_window_resize_pointers(i32* w, i32* h);
-void engine_window_resize_pointers_reset(void);
+//void window_size_callback(GLFWwindow* window, i32 width, i32 height);
+//void engine_window_resize_pointers(i32* w, i32* h);
+//void engine_window_resize_pointers_reset(void);
/* UI rendering */
/* See rendering_ui.c for implementation */
i64 engine_render_text(i32 font_id, Engine_color fg, char* text,
v2_i32* size_out, bool wrapped);
-void engine_draw_uitree(UITree* t);
void engine_draw_sprite(Sprite* s, v2_i32* pos, f32 scale);
void engine_draw_sprite_ex(Sprite* s, v2_i32* pos, f32 scale,
Engine_color colormod);
Sprite sprite_new(u64 tid, u8 coord);
-#ifdef ENGINE_INTERNALS
-#include <engine/engine.h>
-
-//#include <glad/gl.h>
-//#define GLFW_INCLUDE_NONE
-//#include <GLFW/glfw3.h>
-
-#define TEXTURES_INCREMENT 512
-
+//#ifdef ENGINE_INTERNALS
+//#include <engine/engine.h>
+//
+////#include <glad/gl.h>
+////#define GLFW_INCLUDE_NONE
+////#include <GLFW/glfw3.h>
+//
+//#define TEXTURES_INCREMENT 512
+//
typedef enum {
RenderDrawCallType_UITree,
/*RenderDrawCallType_UIButton,*/
RenderDrawCallType_Text,
RenderDrawCallType_Sprite,
} RenderDrawCallType;
-
+//
typedef struct {
RenderDrawCallType type;
union {
@@ -79,23 +78,16 @@ typedef struct {
} sprite;
} data;
} RenderDrawCall;
-
-struct RenderObject {
- u32 vao;
- u32 vbo;
- u32 col;
- u32 shaderprogram;
- f32 g_vertex_buffer_data[9];
-};
-
-void render_uitree(Window* w, UITree* t);
-
-void render_container(Window* w, UITree_container* t);
-void render_button(Window* w, UITree_button* t);
-void render_title(Window* w, UITree_title* t);
-void render_text(Window* w, UITree_text* t);
-v2_i32 elem_size(UITree* root);
-
-#endif
+//
+//struct RenderObject {
+// u32 vao;
+// u32 vbo;
+// u32 col;
+// u32 shaderprogram;
+// f32 g_vertex_buffer_data[9];
+//};
+//
+//
+//#endif
#endif
diff --git a/src/rendering/include/engine/rendering/window.h b/src/rendering/include/engine/rendering/window.h
new file mode 100644
index 0000000..16a0336
--- /dev/null
+++ b/src/rendering/include/engine/rendering/window.h
@@ -0,0 +1,43 @@
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <engine/core/types.h>
+#include <cglm/cglm.h>
+
+enum Window_framework {
+ WINDOW_FRAMEWORK_NONE = 0,
+ WINDOW_FRAMEWORK_GLFW,
+};
+
+typedef enum Window_framework Window_framework;
+
+enum Window_renderer {
+ WINDOW_RENDERER_NONE = 0,
+ WINDOW_RENDERER_OPENGL,
+};
+
+typedef enum Window_renderer Window_renderer;
+
+struct Window {
+ // 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;
+};
+
+typedef struct Window* Window;
+
+// Window function
+Window init_window_glfw(const char* windowtitle, ivec2 windowsize, const u32 flags);
+void destroy_window(Window w);
+
+// Renderer intializer(s)
+void init_render_opengl(Window w);
+
+#endif
diff --git a/src/rendering/src/gl.c b/src/rendering/src/gl.c
index e69de29..2958d49 100644
--- a/src/rendering/src/gl.c
+++ b/src/rendering/src/gl.c
@@ -0,0 +1,119 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glad/gl.h>
+
+#include <engine/core/types.h>
+#include <engine/core/logging.h>
+
+// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
+GLuint LoadShaders(
+ const GladGLContext* gl,
+ const char * vertex_file_path,
+ const char * fragment_file_path) {
+
+ // Create the shaders
+ GLuint VertexShaderID = gl->CreateShader(GL_VERTEX_SHADER);
+ GLuint FragmentShaderID = gl->CreateShader(GL_FRAGMENT_SHADER);
+
+ // Read the Vertex Shader code from the file
+ char* VertexShaderCode;
+ FILE* VertexShaderStream = fopen(vertex_file_path, "r");
+ if(VertexShaderStream != NULL){
+ fseek(VertexShaderStream, 0, SEEK_END);
+ const i64 size = ftell(VertexShaderStream);
+ rewind(VertexShaderStream);
+ VertexShaderCode = calloc(size + 1, sizeof(char));
+
+ // Assume the whole file is successfully read
+ fread(VertexShaderCode, sizeof(char), size, VertexShaderStream);
+
+ fclose(VertexShaderStream);
+ } else {
+ ERROR("Impossible to open %s. Are you in the right directory?\n", vertex_file_path);
+ getchar();
+ return 0;
+ }
+
+ // Read the Fragment Shader code from the file
+ char* FragmentShaderCode;
+ FILE* FragmentShaderStream = fopen(fragment_file_path, "r");
+ if(FragmentShaderStream != NULL){
+ fseek(FragmentShaderStream, 0, SEEK_END);
+ const i64 size = ftell(FragmentShaderStream);
+ rewind(FragmentShaderStream);
+ FragmentShaderCode = calloc(size + 1, sizeof(char));
+
+ // Assume the whole file is successfully read
+ fread(FragmentShaderCode, sizeof(char), size, FragmentShaderStream);
+ LOG("fragment source is %d bytes", size);
+
+ fclose(FragmentShaderStream);
+ } else {
+ ERROR("Impossible to open %s. Are you in the right directory?\n", fragment_file_path);
+ getchar();
+ return 0;
+ }
+
+ GLint Result = GL_FALSE;
+ int InfoLogLength;
+
+ // Compile Vertex Shader
+ INFO("Compiling shader: %s\n", vertex_file_path);
+ char const * VertexSourcePointer = VertexShaderCode;
+ gl->ShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
+ gl->CompileShader(VertexShaderID);
+
+ // Check Vertex Shader
+ gl->GetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
+ gl->GetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+ if ( InfoLogLength > 0 ) {
+ char* msg = calloc(InfoLogLength + 1, sizeof(char));
+ gl->GetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, msg);
+ ERROR("Compiling shader: %s\n", msg);
+ free(msg);
+ }
+
+ // Compile Fragment Shader
+ INFO("Compiling shader: %s\n", fragment_file_path);
+ char const * FragmentSourcePointer = FragmentShaderCode;
+ gl->ShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
+ gl->CompileShader(FragmentShaderID);
+
+ // Check Fragment Shader
+ gl->GetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
+ gl->GetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+ if ( InfoLogLength > 0 ){
+ char* msg = calloc(InfoLogLength + 1, sizeof(char));
+ gl->GetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, msg);
+ ERROR("Compiling shader: %s\n", msg);
+ free(msg);
+ }
+
+ // Link the program
+ INFO("Linking program\n");
+ GLuint ProgramID = gl->CreateProgram();
+ gl->AttachShader(ProgramID, VertexShaderID);
+ gl->AttachShader(ProgramID, FragmentShaderID);
+ gl->LinkProgram(ProgramID);
+
+ // Check the program
+ gl->GetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
+ gl->GetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+ if ( InfoLogLength > 0 ){
+ char* msg = calloc(InfoLogLength + 1, sizeof(char));
+ gl->GetShaderInfoLog(ProgramID, InfoLogLength, NULL, msg);
+ ERROR("Compiling shader: %s\n", msg);
+ free(msg);
+ }
+
+ gl->DetachShader(ProgramID, VertexShaderID);
+ gl->DetachShader(ProgramID, FragmentShaderID);
+
+ gl->DeleteShader(VertexShaderID);
+ gl->DeleteShader(FragmentShaderID);
+
+ free(VertexShaderCode);
+ free(FragmentShaderCode);
+ return ProgramID;
+}
diff --git a/src/rendering/src/rendering.c b/src/rendering/src/rendering.c
index 808897c..740e3a9 100644
--- a/src/rendering/src/rendering.c
+++ b/src/rendering/src/rendering.c
@@ -1,9 +1,7 @@
#include <stdio.h>
#include <string.h>
-//#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
-//#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
@@ -25,13 +23,12 @@ i32 drawcall_len = 0;
/* Clear the screen,
* To be used inbetween draw calls */
-void render_begin(Window* w) {
- //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+void render_begin(Window w) {
glfwMakeContextCurrent(w->window);
- w->context->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ ((GladGLContext*)(w->context))->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
-void render_present(Window* w) {
+void render_present(Window w) {
// for (i32 i = 0; i < drawcall_len; i++) {
// RenderDrawCall dc = drawcalls[i];
// switch (dc.type) {
@@ -69,22 +66,14 @@ void render_present(Window* w) {
void drawcall_reset(void) { drawcall_len = 0; }
-void window_size_callback(GLFWwindow* window, int width, int height) {
- GLOBAL_PLATFORM->window->context->Viewport(0,0, width, height);
- //*GLOBAL_PLATFORM->window->game_w = width;
- //*GLOBAL_PLATFORM->window->game_h = height;
- GLOBAL_PLATFORM->window->windowsize.x = width;
- GLOBAL_PLATFORM->window->windowsize.y = height;
-}
-
void engine_window_resize_pointers(i32* w, i32* h) {
- GLOBAL_PLATFORM->window->game_w = w;
- GLOBAL_PLATFORM->window->game_h = h;
+ //GLOBAL_PLATFORM->window->game_w = w;
+ //GLOBAL_PLATFORM->window->game_h = h;
}
void engine_window_resize_pointers_reset(void) {
- GLOBAL_PLATFORM->window->game_w = NULL;
- GLOBAL_PLATFORM->window->game_h = NULL;
+ //GLOBAL_PLATFORM->window->game_w = NULL;
+ //GLOBAL_PLATFORM->window->game_h = NULL;
}
void engine_draw_uitree(UITree* t) {
@@ -127,8 +116,9 @@ void engine_draw_sprite_ex(Sprite* s, v2_i32* pos, f32 scale,
}
Sprite sprite_new(u64 tid, u8 coord) {
- const i32 ts =
- ((struct Resources*)GLOBAL_PLATFORM->data)->textures[tid]->tilesize;
+ const i32 ts = 16;
+ // FIXME; used to be
+ //((struct Resources*)GLOBAL_PLATFORM->data)->textures[tid]->tilesize;
return (Sprite){.texture_id = tid,
(v2_i32){
.x = ts * (coord & 0x0F),
diff --git a/src/rendering/src/window.c b/src/rendering/src/window.c
index e69de29..ce5544a 100644
--- a/src/rendering/src/window.c
+++ b/src/rendering/src/window.c
@@ -0,0 +1,185 @@
+#include <stdio.h>
+
+/* TODO: REMOVE THIS INCLUSION */
+#include <engine/engine.h>
+
+#include <engine/core/types.h>
+#include <engine/core/logging.h>
+
+#include <engine/rendering/window.h>
+
+#define GLAD_GL_IMPLEMENTATION
+#include <glad/gl.h>
+#undef GLAD_GL_IMPLEMENTATION
+
+#undef GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+
+#include <cglm/cglm.h>
+
+extern Platform* GLOBAL_PLATFORM;
+
+/* GLFW And vulkan spaghetti boiler */
+void glfw_err_callback(int code, const char* description) {
+ ERROR("glfw [%d]: %s\n", code, description);
+ // Terminate?
+ exit(EXIT_FAILURE);
+}
+
+void window_size_callback(GLFWwindow* window, int width, int height) {
+ GladGLContext* gl = GLOBAL_PLATFORM->window->context;
+ gl->Viewport(0,0, width, height);
+ GLOBAL_PLATFORM->window->windowsize[0] = width;
+ GLOBAL_PLATFORM->window->windowsize[1] = height;
+}
+
+GladGLContext* create_context(GLFWwindow *window) {
+ glfwMakeContextCurrent(window);
+
+ GladGLContext* context = (GladGLContext*) calloc(1, sizeof(GladGLContext));
+ if (!context) return NULL;
+
+ int version = gladLoadGLContext(context, glfwGetProcAddress);
+ INFO("Loaded OpenGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
+
+ return context;
+}
+
+Window init_window_glfw(
+ const char* 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);
+ glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
+
+ 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
+ * of a window for it to become visible." */
+ window = glfwCreateWindow(windowsize[0], windowsize[1], windowtitle, NULL, 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
+ // TODO: input handler callback
+ glfwSetFramebufferSizeCallback(window, window_size_callback);
+
+ // Minor tweaks
+ glfwSwapInterval(0);
+
+ // Create the window datastructure
+ ret = (Window)calloc(1, sizeof(Window));
+ ret->framework = WINDOW_FRAMEWORK_GLFW;
+ ret->renderer = WINDOW_RENDERER_NONE;
+ ret->windowsize[0] = windowsize[0];
+ ret->windowsize[1] = windowsize[1];
+ ret->window = window;
+ // Last parameter is used for the renderer
+ ret->context = NULL;
+
+ return ret;
+}
+
+// Initializes opengl using the window
+void init_render_opengl(Window w) {
+ if (w == NULL || w->window == NULL) {
+ ERROR("Window is not initialized");
+ return;
+ }
+
+ if (w->renderer != WINDOW_RENDERER_NONE || w->context != NULL) {
+ ERROR("Window already initialized with a renderer!");
+ return;
+ }
+
+ if (w->framework != WINDOW_FRAMEWORK_GLFW) {
+ ERROR("Trying to initialize OpenGL with incompatible window");
+ return;
+ }
+
+ // This is GLFW specific
+ GladGLContext *ctx = create_context((GLFWwindow*)w->window);
+
+ ctx->Viewport(0, 0, w->windowsize[0], w->windowsize[1]);
+
+ if (ctx == NULL) {
+ ERROR("Failed to create glad context");
+ exit(EXIT_FAILURE);
+ }
+
+#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;
+}
+
+void destroy_window_glfw(GLFWwindow* w) {
+ glfwDestroyWindow(w);
+
+ // If we ever do multi-window support, we need to make sure this is the last
+ // window before terminating
+ glfwTerminate();
+}
+
+void destroy_window(Window w) {
+ switch(w->framework) {
+ case WINDOW_FRAMEWORK_GLFW:
+ destroy_window_glfw(w->window);
+ w->window = NULL;
+ break;
+ default:
+ ERROR("Destroying unknown window type.");
+ }
+
+ switch(w->renderer) {
+ case WINDOW_RENDERER_OPENGL:
+ // Missing unloader function in glad MX library
+ w->context = NULL;
+ break;
+ default:
+ ERROR("Destroying unknown renderer type.");
+ }
+}