summaryrefslogtreecommitdiff
path: root/base/opengl.c
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-03-29 20:11:56 +0100
committerPeter Fors <peter.fors@mindkiller.com>2025-03-29 20:11:56 +0100
commitd5486a5af100fb37fac08b60d862ac14943853ce (patch)
treee2206f620745ba49c94f0f29d180587e03bc9fda /base/opengl.c
parentee4f15400998ca704c6ad8fc537f0d924930fabd (diff)
add base code for windowing and opengl crt-shader.
Diffstat (limited to 'base/opengl.c')
-rw-r--r--base/opengl.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/base/opengl.c b/base/opengl.c
new file mode 100644
index 0000000..641a2a0
--- /dev/null
+++ b/base/opengl.c
@@ -0,0 +1,133 @@
+
+#include "shader.c"
+#include "shader.h"
+#include "data/fragment_shader.h"
+#include "data/vertex_shader.h"
+
+/* [=]===^=[ setup_render_target ]================================================================^===[=] */
+static void setup_render_target(void) {
+ glDeleteTextures(1, &state.texture);
+
+ glGenTextures(1, &state.texture);
+ glBindTexture(GL_TEXTURE_2D, state.texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, state.render_width, state.render_height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buffer);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+/* [=]===^=[ compile_shader ]==============================================================^===[=] */
+static GLuint compile_shader(GLenum shader_type, const char *shader_source) {
+ GLuint shader = glCreateShader(shader_type);
+ glShaderSource(shader, 1, &shader_source, 0);
+ glCompileShader(shader);
+
+ GLint success;
+ GLchar info_log[512];
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+ if(!success) {
+ glGetShaderInfoLog(shader, sizeof(info_log), 0, info_log);
+ DEBUG_PRINT("%s shader compilation failed:\n%s\n", (shader_type == GL_VERTEX_SHADER) ? "Vertex" : "Fragment", info_log);
+ }
+ return shader;
+}
+
+/* [=]===^=[ setup_opengl ]================================================================^===[=] */
+static void opengl_setup(const char *vertex_shader_src, const char *fragment_shader_src) {
+ gl_loader();
+ glEnable(GL_FRAMEBUFFER_SRGB);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+
+ // Shader setup
+ GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_src);
+ GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_src);
+
+ state.shader_program = glCreateProgram();
+ glAttachShader(state.shader_program, vertex_shader);
+ glAttachShader(state.shader_program, fragment_shader);
+
+ glBindAttribLocation(state.shader_program, 0, "position");
+ glBindAttribLocation(state.shader_program, 1, "texture_coord");
+ glLinkProgram(state.shader_program);
+ GLint success;
+ glGetProgramiv(state.shader_program, GL_LINK_STATUS, &success);
+ if(!success) {
+ char log[512];
+ glGetProgramInfoLog(state.shader_program, sizeof(log), NULL, log);
+ DEBUG_PRINT("Shader Linking Failed: %s\n", log);
+ }
+
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+ glUseProgram(state.shader_program);
+
+ // Calculations for the shader.
+ state.contrast = 1.0f;
+ state.saturation = 0.3f;
+ state.brightness = 1.0f;
+ CrtsTone(state.tone_data, state.contrast, state.saturation, INPUT_THIN, INPUT_MASK); // NOTE(peter): Move this into the mainloop if change of contrast/saturation is added as an interactive thing.
+
+ // Retrieve shader uniforms
+ state.uniform_resolution = glGetUniformLocation(state.shader_program, "resolution");
+ state.uniform_src_image_size = glGetUniformLocation(state.shader_program, "src_image_size");
+ state.uniform_brightness = glGetUniformLocation(state.shader_program, "brightness");
+ state.uniform_tone = glGetUniformLocation(state.shader_program, "tone_data");
+ state.uniform_crt_emulation = glGetUniformLocation(state.shader_program, "crt_emulation");
+ state.uniform_sampler_location = glGetUniformLocation(state.shader_program, "iChannel0");
+
+ glGenVertexArrays(1, &state.vao);
+ glGenBuffers(1, &state.vbo);
+ glGenBuffers(1, &state.ebo);
+ glBindVertexArray(state.vao);
+
+ // Vertex data: Position (x, y) and Texture Coordinates (u, v)
+ const float vertices[] = {
+ -1.0f, -1.0f, 0.0f, 0.0f, // Bottom-left
+ 1.0f, -1.0f, 1.0f, 0.0f, // Bottom-right
+ 1.0f, 1.0f, 1.0f, 1.0f, // Top-right
+ -1.0f, 1.0f, 0.0f, 1.0f // Top-left
+ };
+
+ static const unsigned int indices[] = { 0, 1, 2, 2, 3, 0 };
+
+ glBindBuffer(GL_ARRAY_BUFFER, state.vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.ebo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); // Position
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); // Texture Coord
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+}
+
+/* [=]===^=[ render_frame ]=================================================================^===[=] */
+__attribute__((always_inline))
+static inline void render_frame(void) {
+ glClearColor(.0f, 0.f, 0.f, 1.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUseProgram(state.shader_program);
+ glBindVertexArray(state.vao);
+ glBindBuffer(GL_ARRAY_BUFFER, state.vbo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.ebo);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, state.texture);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, state.render_width, state.render_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, display_buffer);
+ glUniform2f(state.uniform_src_image_size, (float)state.render_width, (float)state.render_height);
+ glUniform2f(state.uniform_resolution, (float)state.viewport.w, (float)state.viewport.h);
+ glUniform1f(state.uniform_brightness, state.brightness);
+ glUniform4f(state.uniform_tone, state.tone_data[0], state.tone_data[1], state.tone_data[2], state.tone_data[3]);
+ glUniform1i(state.uniform_crt_emulation, state.toggle_crt_emulation);
+ glUniform1i(state.uniform_sampler_location, 0);
+ glViewport(state.viewport.x, state.viewport.y, state.viewport.w, state.viewport.h);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
+}