From d5486a5af100fb37fac08b60d862ac14943853ce Mon Sep 17 00:00:00 2001 From: Peter Fors Date: Sat, 29 Mar 2025 20:11:56 +0100 Subject: add base code for windowing and opengl crt-shader. --- base/opengl.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 base/opengl.c (limited to 'base/opengl.c') 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); +} -- cgit v1.2.3