diff options
Diffstat (limited to 'src/rendering')
| -rw-r--r-- | src/rendering/include/engine/rendering/rendering.h | 62 | ||||
| -rw-r--r-- | src/rendering/include/engine/rendering/window.h | 43 | ||||
| -rw-r--r-- | src/rendering/src/gl.c | 119 | ||||
| -rw-r--r-- | src/rendering/src/rendering.c | 30 | ||||
| -rw-r--r-- | src/rendering/src/window.c | 185 |
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."); + } +} |
