From 864df46d69e4aeb13480489b8d1f27e4233c4561 Mon Sep 17 00:00:00 2001 From: Rakarake Date: Sun, 14 Dec 2025 14:03:57 +0100 Subject: [PATCH] multiple files --- .gitignore | 1 + Makefile | 14 ++- glonkers.c | 128 +++++++++++++++++++++++ main.c | 293 ----------------------------------------------------- renderer.c | 171 +++++++++++++++++++++++++++++++ renderer.h | 13 +++ 6 files changed, 324 insertions(+), 296 deletions(-) create mode 100644 glonkers.c delete mode 100644 main.c create mode 100644 renderer.c create mode 100644 renderer.h diff --git a/.gitignore b/.gitignore index 1584e8b..e2946f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ glonkers +*.o .ccls-cache .direnv diff --git a/Makefile b/Makefile index f41bbb1..41bf9df 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,16 @@ LIBS=sdl3 opengl wayland-client CFLAGS=-g -Wall -Wextra $(shell pkg-config --cflags $(LIBS)) LDFLAGS=$(shell pkg-config --libs $(LIBS)) -all: - $(CC) $(CFLAGS) $(LDFLAGS) -o glonkers main.c +objects = renderer.o -run: all +glonkers: $(objects) glonkers.c + $(CC) $(CFLAGS) $(LDFLAGS) -o glonkers $^ + +$(objects): %.o: %.c + $(CC) $(CFLAGS) $(LDFLAGS) -c $^ -o $@ + +clean: + rm -f *.o glonkers + +run: glonkers SDL_VIDEODRIVER="wayland,x11" ./glonkers diff --git a/glonkers.c b/glonkers.c new file mode 100644 index 0000000..b075fb1 --- /dev/null +++ b/glonkers.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include "renderer.h" + +//int main() { +// struct wl_display *display = wl_display_connect(NULL); +// if (!display) { +// fprintf(stderr, "Failed to connect to Wayland display.\n"); +// return 1; +// } +// fprintf(stderr, "Connection established!\n"); +// +// while (wl_display_dispatch(display) != -1) { +// } +// +// wl_display_disconnect(display); +//} +//struct our_state { +// // ... +// struct wl_compositor *compositor; +// // ... +//}; +// +//static void +//registry_handle_global(void *data, struct wl_registry *registry, +// uint32_t name, const char *interface, uint32_t version) +//{ +// printf("interface: '%s', version: %d, name: %d\n", +// interface, version, name); +// +// struct our_state *state = data; +// +// if (strcmp(interface, wl_compositor_interface.name) == 0) { +// state->compositor = wl_registry_bind( +// registry, name, &wl_compositor_interface, 4); +// } +//} +// +//static void +//registry_handle_global_remove(void *data, struct wl_registry *registry, +// uint32_t name) +//{ +// // This space deliberately left blank +//} +// +//static const struct wl_registry_listener +//registry_listener = { +// .global = registry_handle_global, +// .global_remove = registry_handle_global_remove, +//}; +// +//int +//main(int argc, char *argv[]) +//{ +// struct our_state state = { 0 }; +// struct wl_display *display = wl_display_connect(NULL); +// struct wl_registry *registry = wl_display_get_registry(display); +// wl_registry_add_listener(registry, ®istry_listener, &state); +// wl_display_roundtrip(display); +// return 0; +//} + +struct timespec program_start; + +void init_timer() { + clock_gettime(CLOCK_MONOTONIC, &program_start); +} + +double time_since_start() { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + return (now.tv_sec - program_start.tv_sec) + + (now.tv_nsec - program_start.tv_nsec) / 1e9; +} + +int main() { + init_timer(); + + printf("Good Morning 🍵\n"); + SDL_Init(SDL_INIT_VIDEO); + SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1"); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, + SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_Window* window = SDL_CreateWindow("SDL3 OpenGL Cube", + 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + if (!window) { + printf("CreateWindow Error: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + + SDL_GLContext glContext = SDL_GL_CreateContext(window); + + if (!glContext) { + printf("GL Context Error: %s\n", SDL_GetError()); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + + Renderer renderer = new_renderer(); + + SDL_Event e; + int running = 1; + int w, h; + while (running) { + while (SDL_PollEvent(&e)) { + if (e.type == SDL_EVENT_QUIT) running = false; + if (e.type == SDL_EVENT_WINDOW_RESIZED) { + SDL_GetWindowSize(window, &w, &h); + } + } + + double time = time_since_start(); + render(&renderer, w, h, time); + + SDL_GL_SwapWindow(window); + } +} + diff --git a/main.c b/main.c deleted file mode 100644 index 4c7b516..0000000 --- a/main.c +++ /dev/null @@ -1,293 +0,0 @@ -#define GL_GLEXT_PROTOTYPES - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//int main() { -// struct wl_display *display = wl_display_connect(NULL); -// if (!display) { -// fprintf(stderr, "Failed to connect to Wayland display.\n"); -// return 1; -// } -// fprintf(stderr, "Connection established!\n"); -// -// while (wl_display_dispatch(display) != -1) { -// } -// -// wl_display_disconnect(display); -//} -//struct our_state { -// // ... -// struct wl_compositor *compositor; -// // ... -//}; -// -//static void -//registry_handle_global(void *data, struct wl_registry *registry, -// uint32_t name, const char *interface, uint32_t version) -//{ -// printf("interface: '%s', version: %d, name: %d\n", -// interface, version, name); -// -// struct our_state *state = data; -// -// if (strcmp(interface, wl_compositor_interface.name) == 0) { -// state->compositor = wl_registry_bind( -// registry, name, &wl_compositor_interface, 4); -// } -//} -// -//static void -//registry_handle_global_remove(void *data, struct wl_registry *registry, -// uint32_t name) -//{ -// // This space deliberately left blank -//} -// -//static const struct wl_registry_listener -//registry_listener = { -// .global = registry_handle_global, -// .global_remove = registry_handle_global_remove, -//}; -// -//int -//main(int argc, char *argv[]) -//{ -// struct our_state state = { 0 }; -// struct wl_display *display = wl_display_connect(NULL); -// struct wl_registry *registry = wl_display_get_registry(display); -// wl_registry_add_listener(registry, ®istry_listener, &state); -// wl_display_roundtrip(display); -// return 0; -//} - -void checkGlError() { - const char *err = SDL_GetError(); - if (*err != 0) { - printf("OpenGL error: %s", err); - } -} - -/// returns 0 if failed. -GLuint compile_shader(GLuint type, const char *src) { - GLuint id = glCreateShader(type); - glShaderSource(id, 1, &src, 0); - glCompileShader(id); - - int result; - glGetShaderiv(id, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) { - int length; - glGetShaderiv(id, GL_INFO_LOG_LENGTH, &result); - char *message = alloca(length * sizeof(char)); - glGetShaderInfoLog(id, length, &length, message); - printf("failed to compile %s shader\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment"); - printf("%s\n", message); - glDeleteShader(id); - return 0; - } - - return id; -} - -const char *vertex_shader_src = -//"attribute vec4 vPosition; \n" -//"void main() \n" -//"{ \n" -//" gl_Position = vPosition; \n" -//"} \n"; -"#version 320 es\n" -"\n" -"layout(location = 0) in vec2 aPos;\n" -"\n" -"void main() {\n" -" gl_Position = vec4(aPos, 0.0, 1.0);\n" -"}\n"; - -/// returns 0 if failed. -GLuint create_shader(const char *fragment_src) { - GLuint program = glCreateProgram(); - GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_src); - GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_src); - if (!((fragment_shader == 0) || (vertex_shader == 0))) { - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - glLinkProgram(program); - glValidateProgram(program); - glDeleteShader(vertex_shader); - glDeleteShader(fragment_shader); - return program; - } else { - return 0; - } -} - -GLuint load_shader(const char *path) { - FILE *handle = fopen(path, "r"); - fseek(handle, 0L, SEEK_END); - long length = ftell(handle); - fseek(handle, 0L, SEEK_SET); - char *string = malloc(length * sizeof(char)); - if (!fread(string, sizeof(char), length, handle)) { - printf("failed to read shader file"); - exit(1); - } - fclose(handle); - - GLuint shader = create_shader(string); - - //if (shader == 0) { - // // print file - // int line_count = 1; - // printf("%i\t", line_count); - // line_count++; - // for (int i = 0; i < length; i++) { - // printf("%c", string[i]); - // if (string[i] == '\n') { - // printf("%i\t", line_count); - // line_count++; - // } - // } - // printf("\n"); - //} - - free(string); - return shader; -} - -struct timespec program_start; - -void init_timer() { - clock_gettime(CLOCK_MONOTONIC, &program_start); -} - -double time_since_start() { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - return (now.tv_sec - program_start.tv_sec) + - (now.tv_nsec - program_start.tv_nsec) / 1e9; -} - -int main() { - init_timer(); - - printf("Good Morning 🍵\n"); - SDL_Init(SDL_INIT_VIDEO); - SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1"); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, - SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - SDL_Window* window = SDL_CreateWindow("SDL3 OpenGL Cube", - 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); - if (!window) { - printf("CreateWindow Error: %s\n", SDL_GetError()); - SDL_Quit(); - return 1; - } - - SDL_GLContext glContext = SDL_GL_CreateContext(window); -const char *version = (const char *)glGetString(GL_VERSION); -const char *renderer = (const char *)glGetString(GL_RENDERER); - -SDL_Log("GL_VERSION: %s", version); -SDL_Log("GL_RENDERER: %s", renderer); - - if (!glContext) { - printf("GL Context Error: %s\n", SDL_GetError()); - SDL_DestroyWindow(window); - SDL_Quit(); - return 1; - } - glEnable(GL_DEPTH_TEST); - - SDL_Event e; - int running = 1; - - GLuint shader = load_shader("fragment.glsl"); //create_shader(fragment_shader_source); - - - // buffers - // Load the vertex data - GLfloat vertices[] = { - -1.0, 1.0, - -1.0, -1.0, - 1.0, -1.0, - - 1.0, -1.0, - 1.0, 1.0, - -1.0, 1.0, - }; - GLuint vao, vbo; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, - sizeof(vertices), - vertices, - GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer( - 0, // location - 2, // vec2 - GL_FLOAT, - GL_FALSE, - 0, - (void *)0 - ); - - - - - int w, h; - double time; - while (running) { - while (SDL_PollEvent(&e)) { - if (e.type == SDL_EVENT_QUIT) running = false; - if (e.type == SDL_EVENT_WINDOW_RESIZED) { - SDL_GetWindowSize(window, &w, &h); - } - } - checkGlError(); - - // Rendorrrr - glViewport(0, 0, w, h); - - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Shader parameters. - glUseProgram(shader); - - int uniform_WindowSize = glGetUniformLocation(shader, "WindowSize"); - glUniform2f(uniform_WindowSize, w, h); - - time = time_since_start(); - int uniform_time = glGetUniformLocation(shader, "time"); - glUniform1f(uniform_time, (float)time); - - //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices); - //glEnableVertexAttribArray(0); - //glDrawArrays(GL_TRIANGLES, 0, 6); - - glBindVertexArray(vao); - glDrawArrays(GL_TRIANGLES, 0, 6); - - SDL_GL_SwapWindow(window); - checkGlError(); - } - - checkGlError(); -} - diff --git a/renderer.c b/renderer.c new file mode 100644 index 0000000..51996f4 --- /dev/null +++ b/renderer.c @@ -0,0 +1,171 @@ +#define GL_GLEXT_PROTOTYPES +#include +#include +#include +#include "renderer.h" + +void checkGlError() { + //const char *err = SDL_GetError(); + //if (*err != 0) { + // printf("OpenGL error: %s", err); + //} +} + +/// returns 0 if failed. +GLuint compile_shader(GLuint type, const char *src) { + GLuint id = glCreateShader(type); + glShaderSource(id, 1, &src, 0); + glCompileShader(id); + + int result; + glGetShaderiv(id, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) { + int length; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &result); + char *message = alloca(length * sizeof(char)); + glGetShaderInfoLog(id, length, &length, message); + printf("failed to compile %s shader\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment"); + printf("%s\n", message); + glDeleteShader(id); + return 0; + } + + return id; +} + +const char *vertex_shader_src = +//"attribute vec4 vPosition; \n" +//"void main() \n" +//"{ \n" +//" gl_Position = vPosition; \n" +//"} \n"; +"#version 320 es\n" +"\n" +"layout(location = 0) in vec2 aPos;\n" +"\n" +"void main() {\n" +" gl_Position = vec4(aPos, 0.0, 1.0);\n" +"}\n"; + +/// returns 0 if failed. +GLuint create_shader(const char *fragment_src) { + GLuint program = glCreateProgram(); + GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_src); + GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_src); + if (!((fragment_shader == 0) || (vertex_shader == 0))) { + glAttachShader(program, vertex_shader); + glAttachShader(program, fragment_shader); + glLinkProgram(program); + glValidateProgram(program); + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + return program; + } else { + return 0; + } +} + +GLuint load_shader(const char *path) { + FILE *handle = fopen(path, "r"); + fseek(handle, 0L, SEEK_END); + long length = ftell(handle); + fseek(handle, 0L, SEEK_SET); + char *string = malloc(length * sizeof(char)); + if (!fread(string, sizeof(char), length, handle)) { + printf("failed to read shader file"); + exit(1); + } + fclose(handle); + + GLuint shader = create_shader(string); + + //if (shader == 0) { + // // print file + // int line_count = 1; + // printf("%i\t", line_count); + // line_count++; + // for (int i = 0; i < length; i++) { + // printf("%c", string[i]); + // if (string[i] == '\n') { + // printf("%i\t", line_count); + // line_count++; + // } + // } + // printf("\n"); + //} + + free(string); + return shader; +} + +Renderer new_renderer() { + const char *version_str = (const char *)glGetString(GL_VERSION); + const char *renderer_str = (const char *)glGetString(GL_RENDERER); + printf("GL_VERSION: %s\n", version_str); + printf("GL_RENDERER: %s\n", renderer_str); + + glEnable(GL_DEPTH_TEST); + + GLuint shader = load_shader("fragment.glsl"); //create_shader(fragment_shader_source); + + // buffers + // Load the vertex data + GLfloat vertices[] = { + -1.0, 1.0, + -1.0, -1.0, + 1.0, -1.0, + + 1.0, -1.0, + 1.0, 1.0, + -1.0, 1.0, + }; + GLuint vao, vbo; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, + sizeof(vertices), + vertices, + GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, // location + 2, // vec2 + GL_FLOAT, + GL_FALSE, + 0, + (void *)0 + ); + + Renderer renderer = { shader, vao }; + return renderer; +} + +void render(Renderer *state, int w, int h, double time) { + checkGlError(); + + // Rendorrrr + glViewport(0, 0, w, h); + + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Shader parameters. + glUseProgram(state->shader); + + int uniform_WindowSize = glGetUniformLocation(state->shader, "WindowSize"); + glUniform2f(uniform_WindowSize, w, h); + + int uniform_time = glGetUniformLocation(state->shader, "time"); + glUniform1f(uniform_time, (float)time); + + //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices); + //glEnableVertexAttribArray(0); + //glDrawArrays(GL_TRIANGLES, 0, 6); + + glBindVertexArray(state->vao); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + diff --git a/renderer.h b/renderer.h new file mode 100644 index 0000000..91e175c --- /dev/null +++ b/renderer.h @@ -0,0 +1,13 @@ +#ifndef RENDERER_H +#define RENDERER_H + +typedef struct Renderer { + unsigned int shader; + unsigned int vao; +} Renderer; + +Renderer new_renderer(); +void render(Renderer *renderer, int w, int h, double time); + +#endif +