read fragment shader from file

This commit is contained in:
2025-09-12 19:19:45 +02:00
parent fda0de78c7
commit f90e842bd8
10 changed files with 121 additions and 51 deletions
+1 -1
View File
@@ -2,4 +2,4 @@ AUTOMAKE_OPTIONS = foreign subdir-objects -Wall
bin_PROGRAMS = forge
forge_SOURCES = src/main.c src/args.c src/forge.c src/file.c
forge_CFLAGS = -Ofast -march=native -flto -funroll-loops -fprefetch-loop-arrays -fno-exceptions -fopenmp
include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h include/linmath.h include/glad/gl.h
include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h src/constants.h include/linmath.h include/glad/gl.h
+4 -3
View File
@@ -86,10 +86,11 @@ make -f Makefile.dev release-arch
- [x] Create GLSL Window
- [x] Load static fragment shader into GLSL
- [x] Add default uniforms
- [ ] Read fragment shader from file
- [x] Read fragment shader from file
- [ ] Handle compilation errors
- [ ] Minimal working fragment sample
- [ ] Hot-reload fragment shader
- [x] Minimal working fragment sample
- [x] Hot-reload fragment shader
- [ ] Specify fragment shader path
- [x] Force fullscreen
- [x] Select screen as argument / config
- [ ] Midi
+15
View File
@@ -0,0 +1,15 @@
#version 330
uniform float iTime;
uniform vec2 iResolution;
in vec2 vUV;
out vec4 fragColor;
void main() {
vec2 uv0 = vUV.st;
float ratio = iResolution.x / iResolution.y;
vec2 uv1 = (uv0 - .5) * vec2(ratio, 1);
vec3 color = vec3(vUV, sin(iTime * 0.5) * 0.5 + 0.5);
color *= 1 - step(cos(iTime) * 0.1 + 0.5,length(uv1));
fragColor = vec4(color, 1.0);
}
+3 -2
View File
@@ -1,10 +1,11 @@
#include "args.h"
#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "args.h"
#include "config.h"
void print_help(int status_code) {
puts(PACKAGE
" " VERSION "\n\n"
+16
View File
@@ -0,0 +1,16 @@
#include "types.h"
static const char *vertex_shader_text =
"#version 330\n"
"uniform mat4 mvp;\n"
"in vec2 vPos;\n"
"out vec2 vUV;\n"
"void main()\n"
"{\n"
" gl_Position = mvp * vec4(vPos, 0.0, 1.0);\n"
" vUV = vPos;\n"
"}\n";
static const Vertex vertices[6] = {{{0.0f, 0.0f}}, {{0.0f, 1.0f}},
{{1.0f, 1.0f}}, {{0.0f, 0.0f}},
{{1.0f, 1.0f}}, {{1.0f, 0.0f}}};
+7 -3
View File
@@ -23,7 +23,9 @@ bool should_update_file(File *file) {
void update_file(File *file) {
// free remaining data
free(file->content);
if (file->content != 0) {
free(file->content);
}
// init empty file
file->content = 0;
file->error = false;
@@ -56,7 +58,9 @@ void update_file(File *file) {
}
File read_file(char *path) {
File file = {path, 0, 0, 0};
File file = {path, 0, false, 0};
update_file(&file);
return file;
}
}
void free_file(File *file) { free(file->content); }
+2
View File
@@ -9,4 +9,6 @@ bool should_update_file(File *file);
void update_file(File *file);
void free_file(File *file);
#endif
+64 -37
View File
@@ -1,47 +1,18 @@
#include "config.h"
#include "types.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <linmath.h>
#include "config.h"
#include "constants.h"
#include "file.h"
#include "types.h"
#include <linmath.h>
#define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
static const Vertex vertices[6] = {{{0.0f, 0.0f}}, {{0.0f, 1.0f}},
{{1.0f, 1.0f}}, {{0.0f, 0.0f}},
{{1.0f, 1.0f}}, {{1.0f, 0.0f}}};
static const char *vertex_shader_text =
"#version 330\n"
"uniform mat4 mvp;\n"
"in vec2 vPos;\n"
"out vec2 vUV;\n"
"void main()\n"
"{\n"
" gl_Position = mvp * vec4(vPos, 0.0, 1.0);\n"
" vUV = vPos;\n"
"}\n";
static const char *fragment_shader_text =
"#version 330\n"
"uniform float iTime;\n"
"uniform vec2 iResolution;\n"
"in vec2 vUV;\n"
"out vec4 fragColor;\n"
"void main()\n"
"{\n"
" vec2 uv0 = vUV.st;\n"
" float ratio = iResolution.x / iResolution.y;\n"
" vec2 uv1 = (uv0 - .5) * vec2(ratio, 1);\n"
" vec3 color = vec3(vUV, sin(iTime * 0.5) * 0.5 + 0.5);\n"
" color *= 1 - step(cos(iTime) * 0.5 + 0.5,length(uv1));\n"
" fragColor = vec4(color, 1.0);\n"
"}\n";
void error_callback(int error, const char *description) {
fprintf(stderr, "Error %d: %s\n", error, description);
glfwTerminate();
@@ -56,6 +27,8 @@ static void key_callback(GLFWwindow *window, int key, int scancode, int action,
}
}
// TODO extract to window file
// TODO split into smaller functions
void *init_window(GLFWwindow **window, Parameters params) {
// set errors handler
glfwSetErrorCallback(error_callback);
@@ -112,8 +85,11 @@ void *init_window(GLFWwindow **window, Parameters params) {
return window;
}
ShaderProgram init_program() {
// TODO extract to "shaders" file
// TODO split into smaller functions
ShaderProgram init_program(File fragment_shader) {
ShaderProgram program = {};
GLint status_params;
glGenBuffers(1, &program.vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, program.vertex_buffer);
@@ -123,10 +99,27 @@ ShaderProgram init_program() {
glShaderSource(program.vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(program.vertex_shader);
glGetShaderiv(program.vertex_shader, GL_COMPILE_STATUS, &status_params);
if (status_params == GL_FALSE) {
program.error = true;
// TODO use glGetShaderInfoLog( GLuint shader, GLsizei
// maxLength, GLsizei *length, GLchar *infoLog);
}
program.fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(program.fragment_shader, 1, &fragment_shader_text, NULL);
glShaderSource(program.fragment_shader, 1,
(const GLchar *const *)&fragment_shader.content, NULL);
glCompileShader(program.fragment_shader);
glGetShaderiv(program.fragment_shader, GL_COMPILE_STATUS, &status_params);
if (status_params == GL_FALSE) {
program.error = true;
}
if (program.error) {
return program;
}
program.program = glCreateProgram();
glAttachShader(program.program, program.vertex_shader);
glAttachShader(program.program, program.fragment_shader);
@@ -146,6 +139,21 @@ ShaderProgram init_program() {
return program;
}
// TODO extract to "shaders" file
void update_program(ShaderProgram program, File fragment_shader) {
GLint status_params;
glShaderSource(program.fragment_shader, 1,
(const GLchar *const *)&fragment_shader.content, NULL);
glCompileShader(program.fragment_shader);
glGetShaderiv(program.fragment_shader, GL_COMPILE_STATUS, &status_params);
if (status_params == GL_FALSE) {
fprintf(stderr, "Failed to compile shaders\n"); // TODO add info
return;
}
glLinkProgram(program.program);
}
void loop(GLFWwindow *window, ShaderProgram program) {
int width, height;
glfwGetFramebufferSize(window, &width, &height);
@@ -173,13 +181,32 @@ void loop(GLFWwindow *window, ShaderProgram program) {
void forge_run(Parameters params) {
GLFWwindow *window;
File fragment_shader = read_file("shaders/tmp.glsl");
if (fragment_shader.error) {
fprintf(stderr, "Cannot read file\n");
exit(EXIT_FAILURE);
}
init_window(&window, params);
ShaderProgram program = init_program();
ShaderProgram program = init_program(fragment_shader);
if (program.error) {
fprintf(stderr, "Failed to compile shaders\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
while (!glfwWindowShouldClose(window)) {
if (should_update_file(&fragment_shader)) {
update_file(&fragment_shader);
update_program(program, fragment_shader);
}
loop(window, program);
}
glfwTerminate();
free_file(&fragment_shader);
}
+4 -3
View File
@@ -1,10 +1,11 @@
#include "args.h"
#include "config.h"
#include "forge.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "args.h"
#include "config.h"
#include "forge.h"
int main(int argc, char **argv) {
Parameters params;
params = parse_args(argc, argv);
+5 -2
View File
@@ -1,8 +1,9 @@
#include <glad/gl.h>
#include <linmath.h>
#include <stdbool.h>
#include <time.h>
#include <glad/gl.h>
#include <linmath.h>
#ifndef TYPES_H
#define TYPES_H
@@ -35,6 +36,8 @@ typedef struct ShaderProgram {
GLuint ires_location;
GLuint vertex_array;
bool error;
} ShaderProgram;
#endif