feat: working include directive
This commit is contained in:
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: install libs
|
||||
run: sudo apt install -y libglfw3-dev libgl-dev libv4l-dev libasound2-dev
|
||||
- name: gcc
|
||||
run: mkdir -p build && gcc -v -Wall -Wextra -Werror src/*.c src/*.h -lglfw -lGL -lm -lasound -Iinclude hashmap.c/hashmap.c log.c/src/log.c -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE
|
||||
run: mkdir -p build && gcc -v -Wall -Wextra -Werror -Wno-format-truncation src/*.c src/*.h -lglfw -lGL -lm -lasound -Iinclude hashmap.c/hashmap.c log.c/src/log.c -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE
|
||||
|
||||
build-release:
|
||||
needs: lint
|
||||
|
||||
+4
-1
@@ -85,6 +85,7 @@ make -f Makefile.dev release-arch
|
||||
- [x] Clean code and fix things
|
||||
- [x] Share openGL state between monitor and screen
|
||||
- [ ] Default project
|
||||
- [ ] split with includes
|
||||
- [ ] src 9: game of life
|
||||
- [ ] src 10 : ?
|
||||
- [ ] src 11 : ?
|
||||
@@ -97,7 +98,9 @@ make -f Makefile.dev release-arch
|
||||
- [ ] Other
|
||||
- [x] `forge_project.cfg`
|
||||
- [x] Define frag prefix in config
|
||||
- [ ] Use custom `#include xxx.glsl` preprocessor
|
||||
- [x] Use custom `#include xxx.glsl` preprocessor
|
||||
- [ ] Use snprintf isntead of sprintf (and strlcpy instand of strncpy)
|
||||
- [ ] Pass "heavy" struct as pointer to avoid stack overload
|
||||
- [x] Clean and sort args
|
||||
- [x] `--auto-random` / `--no-auto-random`
|
||||
- [ ] Update readme with usage documentation
|
||||
|
||||
@@ -16,6 +16,7 @@ build:
|
||||
log.c/src/log.c \
|
||||
-lm -lGL -lglfw -lasound \
|
||||
-Wall -Wextra \
|
||||
-Wno-format-truncation \
|
||||
-DGLFW_INCLUDE_NONE \
|
||||
-DGLFW_EXPOSE_NATIVE_EGL \
|
||||
-DGLFW_NATIVE_INCLUDE_NONE \
|
||||
@@ -31,6 +32,10 @@ run: build
|
||||
demo: build
|
||||
./build/$(TARGET) $(TEST_ARGS) --demo
|
||||
|
||||
.PHONY: sample
|
||||
sample: build
|
||||
./build/$(TARGET) --project=sample
|
||||
|
||||
.PHONY: valgrind
|
||||
valgrind: build
|
||||
valgrind \
|
||||
|
||||
@@ -31,7 +31,8 @@ b
|
||||
- [NanoKontrol2 Controller mapping](#nanokontrol2-controller-mapping)
|
||||
- [Making your own FORGE project](#making-your-own-forge-project)
|
||||
- [`forge_project.cfg`](#forge_projectcfg)
|
||||
- [Working with `frag0.glsl`](#working-with-frag0glsl)
|
||||
- [Writing your fragment shaders](#writing-your-fragment-shaders)
|
||||
- [Working with `#include`](#working-with-include)
|
||||
- [Frequently Asked Questions](#frequently-asked-questions)
|
||||
- [Why "steel"?](#why-steel)
|
||||
- [How do I report a bug?](#how-do-i-report-a-bug)
|
||||
@@ -178,7 +179,11 @@ TODO
|
||||
|
||||
TODO
|
||||
|
||||
### Working with `frag0.glsl`
|
||||
### Writing your fragment shaders
|
||||
|
||||
TODO
|
||||
|
||||
### Working with `#include`
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// VIDEO 1
|
||||
// -----------
|
||||
// IN: 1 (RAW IN A)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// MONITOR
|
||||
// ---
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// VIDEO 2
|
||||
// -----------
|
||||
// IN: 2 (RAW IN B)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// SRC A
|
||||
// -----------
|
||||
// OUT: 5 (FX A)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// SRC B
|
||||
// -----------
|
||||
// OUT: 6 (FX B)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// FX A
|
||||
// -------------
|
||||
// IN: 5 (SRC A)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// FX B
|
||||
// -------------
|
||||
// IN: 6 (SRC B)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// A+B
|
||||
// ------------
|
||||
// IN: 7 (FX A)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// MFX
|
||||
// ------------
|
||||
// IN: 9 (A+B)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include frag0.glsl
|
||||
|
||||
// OUT
|
||||
// ---
|
||||
|
||||
|
||||
+5
-1
@@ -31,6 +31,10 @@
|
||||
#define MAX_FRAG 64
|
||||
#endif
|
||||
|
||||
#ifndef MAX_SUB_FILE
|
||||
#define MAX_SUB_FILE 32
|
||||
#endif
|
||||
|
||||
/* MIDI */
|
||||
|
||||
#ifndef UNSET_MIDI_CODE
|
||||
@@ -44,7 +48,7 @@
|
||||
/* ARRAY */
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE 1024
|
||||
#define ARRAY_SIZE 512
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_NOT_FOUND
|
||||
|
||||
+20
-12
@@ -2,6 +2,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -22,7 +23,7 @@ bool file_should_update(File file) {
|
||||
return file.last_write != get_file_time(file);
|
||||
}
|
||||
|
||||
void file_update(File *file) {
|
||||
bool file_update(File *file) {
|
||||
long length;
|
||||
FILE *file_pointer;
|
||||
|
||||
@@ -40,19 +41,19 @@ void file_update(File *file) {
|
||||
if (file_pointer == NULL) {
|
||||
file->error = true;
|
||||
log_error("Cannot open file '%s'", file->path);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// read file length
|
||||
fseek(file_pointer, 0, SEEK_END);
|
||||
length = ftell(file_pointer);
|
||||
// init buffer
|
||||
fseek(file_pointer, 0, SEEK_SET);
|
||||
file->content = (char *)malloc((length + 1) * sizeof(char));
|
||||
file->content = malloc(length + 1);
|
||||
if (file->content == NULL) {
|
||||
file->error = true;
|
||||
fclose(file_pointer);
|
||||
log_error("Cannot read file '%s'", file->path);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
// read file
|
||||
fread(file->content, sizeof(char), length, file_pointer);
|
||||
@@ -62,12 +63,14 @@ void file_update(File *file) {
|
||||
file->content[length] = '\0';
|
||||
// read last update time
|
||||
file->last_write = get_file_time(*file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
File file_read(char *path) {
|
||||
File file;
|
||||
|
||||
sprintf(file.path, path, STR_LEN);
|
||||
strncpy(file.path, path, STR_LEN);
|
||||
file.content = NULL;
|
||||
file.error = false;
|
||||
file.last_write = 0;
|
||||
@@ -98,12 +101,17 @@ void file_write(char *path, StringArray lines) {
|
||||
fclose(file_pointer);
|
||||
}
|
||||
|
||||
void file_prepend(File *src, File extra) {
|
||||
char *old_src_content;
|
||||
|
||||
old_src_content = src->content;
|
||||
src->content = string_concat(extra.content, src->content);
|
||||
free(old_src_content);
|
||||
void file_free(File *file) {
|
||||
if (!file->error) {
|
||||
free(file->content);
|
||||
file->error = true;
|
||||
}
|
||||
}
|
||||
|
||||
void file_free(File *file) { free(file->content); }
|
||||
void file_free_array(FileArray *files) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < files->length; i++) {
|
||||
file_free(&files->values[i]);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -7,12 +7,12 @@ File file_read(char *path);
|
||||
|
||||
bool file_should_update(File file);
|
||||
|
||||
void file_update(File *file);
|
||||
|
||||
void file_prepend(File *src, File extra);
|
||||
bool file_update(File *file);
|
||||
|
||||
void file_write(char *path, StringArray lines);
|
||||
|
||||
void file_free(File *file);
|
||||
|
||||
void file_free_array(FileArray *files);
|
||||
|
||||
#endif /* FILE_H */
|
||||
+9
-6
@@ -81,7 +81,7 @@ static void init_context(Parameters params, unsigned int in_count) {
|
||||
static void free_context() { shared_close_context(context); }
|
||||
|
||||
static void reload_shader(unsigned int i) {
|
||||
shaders_update(program, project.fragment_shaders, i);
|
||||
shaders_update(program, project.fragment_shaders[i][0], i);
|
||||
}
|
||||
|
||||
static void init_inputs(StringArray video_in, unsigned int video_size) {
|
||||
@@ -186,7 +186,11 @@ void forge_run(Parameters params) {
|
||||
|
||||
context->stop = false;
|
||||
|
||||
project = project_init(params.project_path, params.config_file);
|
||||
project_init(&project, params.project_path, params.config_file);
|
||||
|
||||
if (project.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
init_inputs(params.video_in, params.video_size);
|
||||
|
||||
@@ -222,7 +226,7 @@ void forge_run(Parameters params) {
|
||||
|
||||
window_use(window_output, context);
|
||||
|
||||
program = shaders_init(project, context, inputs, NULL);
|
||||
shaders_init(&program, &project, context, inputs, false);
|
||||
} else {
|
||||
window_output = NULL;
|
||||
}
|
||||
@@ -234,8 +238,7 @@ void forge_run(Parameters params) {
|
||||
|
||||
window_use(window_monitor, context);
|
||||
|
||||
program = shaders_init(project, context, inputs,
|
||||
window_output != NULL ? &program : NULL);
|
||||
shaders_init(&program, &project, context, inputs, window_output != NULL);
|
||||
} else {
|
||||
window_monitor = NULL;
|
||||
}
|
||||
@@ -279,7 +282,7 @@ void forge_run(Parameters params) {
|
||||
|
||||
free_context();
|
||||
|
||||
project_free(project);
|
||||
project_free(&project);
|
||||
|
||||
window_terminate();
|
||||
}
|
||||
+103
-56
@@ -1,95 +1,142 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "config_file.h"
|
||||
#include "file.h"
|
||||
#include "log.h"
|
||||
#include "project.h"
|
||||
#include "state.h"
|
||||
#include "string.h"
|
||||
|
||||
static File read_fragment_shader_file(char *frag_path, char *frag_prefix,
|
||||
static bool parse_fragment_shader_file(Project *project, unsigned int i) {
|
||||
File tmp_file, fragment_shader;
|
||||
char file_path[STR_LEN];
|
||||
char *include_pos, *include_end;
|
||||
char included_file[STR_LEN];
|
||||
char *new_content;
|
||||
|
||||
fragment_shader = project->fragment_shaders[i][0];
|
||||
|
||||
project->sub_counts.values[i] = 0;
|
||||
|
||||
include_pos = strstr(fragment_shader.content, "#include ");
|
||||
|
||||
while (include_pos != NULL && project->sub_counts.values[i] < MAX_SUB_FILE) {
|
||||
include_end = strstr(include_pos, "\n");
|
||||
if (include_end == NULL) {
|
||||
log_error("Invalid '#include' directive in '%s'", fragment_shader.path);
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(included_file, include_pos + 9, include_end - include_pos - 8);
|
||||
|
||||
snprintf(file_path, STR_LEN, "%s/%s", project->path, included_file);
|
||||
|
||||
tmp_file = file_read(file_path);
|
||||
|
||||
if (tmp_file.error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
project->fragment_shaders[i][++project->sub_counts.values[i]] = tmp_file;
|
||||
|
||||
new_content = string_replace_at(
|
||||
fragment_shader.content, include_pos - fragment_shader.content,
|
||||
include_end - fragment_shader.content, tmp_file.content);
|
||||
|
||||
project->fragment_shaders[i][0].content = new_content;
|
||||
|
||||
file_free(&tmp_file);
|
||||
|
||||
include_pos = strstr(fragment_shader.content, "#include ");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_fragment_shader_file(Project *project, char *frag_prefix,
|
||||
unsigned int i) {
|
||||
File fragment_shader;
|
||||
char file_path[STR_LEN];
|
||||
|
||||
snprintf(file_path, STR_LEN, "%s/%s%d.glsl", frag_path, frag_prefix, i);
|
||||
fragment_shader = file_read(file_path);
|
||||
if (fragment_shader.error) {
|
||||
exit(EXIT_FAILURE);
|
||||
snprintf(file_path, STR_LEN, "%s/%s%d.glsl", project->path, frag_prefix,
|
||||
i + 1);
|
||||
|
||||
project->fragment_shaders[i][0] = file_read(file_path);
|
||||
|
||||
if (project->fragment_shaders[i][0].error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fragment_shader;
|
||||
return parse_fragment_shader_file(project, i);
|
||||
}
|
||||
|
||||
static void init_files(Project *output, char *frag_path, char *frag_prefix,
|
||||
unsigned int frag_count) {
|
||||
unsigned int i;
|
||||
|
||||
output->fragment_shaders.length = frag_count;
|
||||
|
||||
for (i = 0; i < frag_count + 1; i++) {
|
||||
if (i == 0) {
|
||||
output->common_shader_code =
|
||||
read_fragment_shader_file(frag_path, frag_prefix, i);
|
||||
} else {
|
||||
output->fragment_shaders.values[i - 1] =
|
||||
read_fragment_shader_file(frag_path, frag_prefix, i);
|
||||
|
||||
file_prepend(&output->fragment_shaders.values[i - 1],
|
||||
output->common_shader_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Project project_init(char *project_path, char *config_file) {
|
||||
Project project;
|
||||
void project_init(Project *project, char *project_path, char *config_file) {
|
||||
char config_path[STR_LEN];
|
||||
char *frag_prefix;
|
||||
unsigned int i;
|
||||
|
||||
strlcpy(project->path, project_path, STR_LEN);
|
||||
|
||||
snprintf(config_path, STR_LEN, "%s/%s", project_path, config_file);
|
||||
|
||||
project.config = config_file_read(config_path);
|
||||
project->config = config_file_read(config_path);
|
||||
|
||||
project.state_config = state_parse_config(project.config);
|
||||
project->state_config = state_parse_config(project->config);
|
||||
|
||||
project.frag_count = config_file_get_int(project.config, "FRAG_COUNT", 1);
|
||||
project.in_count = config_file_get_int(project.config, "IN_COUNT", 0);
|
||||
frag_prefix = config_file_get_str(project.config, "FRAG_FILE_PREFIX", "frag");
|
||||
project->frag_count = config_file_get_int(project->config, "FRAG_COUNT", 1);
|
||||
project->in_count = config_file_get_int(project->config, "IN_COUNT", 0);
|
||||
frag_prefix =
|
||||
config_file_get_str(project->config, "FRAG_FILE_PREFIX", "frag");
|
||||
|
||||
init_files(&project, project_path, frag_prefix, project.frag_count);
|
||||
if (project->frag_count > MAX_FRAG) {
|
||||
log_error("FRAG_COUNT over %d", MAX_FRAG);
|
||||
project->error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
return project;
|
||||
project->sub_counts.length = project->frag_count;
|
||||
|
||||
for (i = 0; i < project->frag_count; i++) {
|
||||
project->sub_counts.values[i] = 0;
|
||||
if (!read_fragment_shader_file(project, frag_prefix, i)) {
|
||||
project_free(project);
|
||||
project->error = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_reload(Project *project, void (*reload_callback)(unsigned int)) {
|
||||
unsigned int i;
|
||||
bool force_update;
|
||||
|
||||
force_update = false;
|
||||
|
||||
if (file_should_update(project->common_shader_code)) {
|
||||
file_update(&project->common_shader_code);
|
||||
force_update = true;
|
||||
}
|
||||
unsigned int i, j;
|
||||
bool should_update;
|
||||
|
||||
for (i = 0; i < project->frag_count; i++) {
|
||||
if (force_update ||
|
||||
file_should_update(project->fragment_shaders.values[i])) {
|
||||
file_update(&project->fragment_shaders.values[i]);
|
||||
file_prepend(&project->fragment_shaders.values[i],
|
||||
project->common_shader_code);
|
||||
should_update = file_should_update(project->fragment_shaders[i][0]);
|
||||
|
||||
for (j = 0; j < project->sub_counts.values[i]; j++) {
|
||||
should_update = should_update ||
|
||||
file_should_update(project->fragment_shaders[i][j + 1]);
|
||||
}
|
||||
|
||||
should_update =
|
||||
should_update && file_update(&project->fragment_shaders[i][0]);
|
||||
|
||||
should_update = should_update && parse_fragment_shader_file(project, i);
|
||||
|
||||
if (should_update) {
|
||||
reload_callback(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_free(Project project) {
|
||||
void project_free(Project *project) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < project.frag_count; i++) {
|
||||
file_free(&project.fragment_shaders.values[i]);
|
||||
for (i = 0; i < project->frag_count; i++) {
|
||||
file_free(&project->fragment_shaders[i][0]);
|
||||
}
|
||||
|
||||
file_free(&project.common_shader_code);
|
||||
|
||||
config_file_free(project.config);
|
||||
config_file_free(project->config);
|
||||
}
|
||||
+2
-2
@@ -3,10 +3,10 @@
|
||||
#ifndef PROJECT_H
|
||||
#define PROJECT_H
|
||||
|
||||
Project project_init(char *project_path, char *config_file);
|
||||
void project_init(Project *project, char *project_path, char *config_file);
|
||||
|
||||
void project_reload(Project *project, void (*reload_callback)(unsigned int));
|
||||
|
||||
void project_free(Project project);
|
||||
void project_free(Project *project);
|
||||
|
||||
#endif /* PROJECT_H */
|
||||
+37
-48
@@ -213,7 +213,7 @@ static bool compile_shader(GLuint shader_id, char *name, char *source_code) {
|
||||
return status_params == GL_TRUE;
|
||||
}
|
||||
|
||||
static void init_shaders(ShaderProgram *program, FileArray fragment_shaders) {
|
||||
static void init_shaders(ShaderProgram *program, Project *project) {
|
||||
unsigned int i;
|
||||
|
||||
// compile vertex shader
|
||||
@@ -225,8 +225,8 @@ static void init_shaders(ShaderProgram *program, FileArray fragment_shaders) {
|
||||
for (i = 0; i < program->frag_count; i++) {
|
||||
program->fragment_shaders[i] = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
program->error |= !compile_shader(program->fragment_shaders[i],
|
||||
fragment_shaders.values[i].path,
|
||||
fragment_shaders.values[i].content);
|
||||
project->fragment_shaders[i][0].path,
|
||||
project->fragment_shaders[i][0].content);
|
||||
|
||||
if (program->error) {
|
||||
return;
|
||||
@@ -377,69 +377,58 @@ static void init_programs(ShaderProgram *program, ConfigFile config,
|
||||
}
|
||||
}
|
||||
|
||||
ShaderProgram shaders_init(Project project, SharedContext *context,
|
||||
VideoCaptureArray inputs, ShaderProgram *previous) {
|
||||
ShaderProgram program;
|
||||
void shaders_init(ShaderProgram *program, Project *project,
|
||||
SharedContext *context, VideoCaptureArray inputs,
|
||||
bool rebind) {
|
||||
if (!rebind) {
|
||||
program->error = false;
|
||||
program->last_resolution[0] = context->resolution[0];
|
||||
program->last_resolution[1] = context->resolution[1];
|
||||
program->tex_count = config_file_get_int(project->config, "TEX_COUNT", 9);
|
||||
program->frag_count = project->frag_count;
|
||||
program->frag_output_index =
|
||||
config_file_get_int(project->config, "FRAG_OUTPUT", 1) - 1;
|
||||
program->frag_monitor_index =
|
||||
config_file_get_int(project->config, "FRAG_MONITOR", 1) - 1;
|
||||
program->sub_type_count =
|
||||
config_file_get_int(project->config, "SUB_TYPE_COUNT", 0);
|
||||
program->in_count = config_file_get_int(project->config, "IN_COUNT", 0);
|
||||
program->sub_variant_count = project->state_config.state_max;
|
||||
program->active_count = project->state_config.midi_active_counts.length;
|
||||
program->midi_lengths.length = 0;
|
||||
|
||||
if (previous == NULL) {
|
||||
program.error = false;
|
||||
program.last_resolution[0] = context->resolution[0];
|
||||
program.last_resolution[1] = context->resolution[1];
|
||||
program.tex_count = config_file_get_int(project.config, "TEX_COUNT", 9);
|
||||
program.frag_count = project.frag_count;
|
||||
program.frag_output_index =
|
||||
config_file_get_int(project.config, "FRAG_OUTPUT", 1) - 1;
|
||||
program.frag_monitor_index =
|
||||
config_file_get_int(project.config, "FRAG_MONITOR", 1) - 1;
|
||||
program.sub_type_count =
|
||||
config_file_get_int(project.config, "SUB_TYPE_COUNT", 0);
|
||||
program.in_count = config_file_get_int(project.config, "IN_COUNT", 0);
|
||||
program.sub_variant_count = project.state_config.state_max;
|
||||
program.active_count = project.state_config.midi_active_counts.length;
|
||||
program.midi_lengths.length = 0;
|
||||
init_gl(program);
|
||||
|
||||
if (program.frag_count > MAX_FRAG) {
|
||||
log_error("FRAG_COUNT over %d", MAX_FRAG);
|
||||
program.error = true;
|
||||
return program;
|
||||
init_shaders(program, project);
|
||||
|
||||
if (program->error) {
|
||||
return;
|
||||
}
|
||||
|
||||
init_gl(&program);
|
||||
init_textures(program, context);
|
||||
|
||||
init_shaders(&program, project.fragment_shaders);
|
||||
init_input(program, project->config, inputs);
|
||||
|
||||
if (program.error) {
|
||||
return program;
|
||||
}
|
||||
init_framebuffers(program, project->config);
|
||||
|
||||
init_textures(&program, context);
|
||||
init_programs(program, project->config, project->state_config);
|
||||
|
||||
init_input(&program, project.config, inputs);
|
||||
|
||||
init_framebuffers(&program, project.config);
|
||||
|
||||
init_programs(&program, project.config, project.state_config);
|
||||
|
||||
init_vertices(&program);
|
||||
init_vertices(program);
|
||||
|
||||
// log_debug("Error after init: %04x",
|
||||
// glGetError()); // TODO check error at each step
|
||||
} else {
|
||||
program = *previous;
|
||||
}
|
||||
|
||||
bind_vertices(&program, previous != NULL ? 1 : 0);
|
||||
|
||||
return program;
|
||||
bind_vertices(program, rebind ? 1 : 0);
|
||||
;
|
||||
}
|
||||
|
||||
void shaders_update(ShaderProgram program, FileArray fragment_shaders,
|
||||
void shaders_update(ShaderProgram program, File fragment_shader,
|
||||
unsigned int i) {
|
||||
bool result;
|
||||
|
||||
result = compile_shader(program.fragment_shaders[i],
|
||||
fragment_shaders.values[i].path,
|
||||
fragment_shaders.values[i].content);
|
||||
result = compile_shader(program.fragment_shaders[i], fragment_shader.path,
|
||||
fragment_shader.content);
|
||||
|
||||
if (result) {
|
||||
glLinkProgram(program.programs[i]);
|
||||
|
||||
+4
-3
@@ -3,10 +3,11 @@
|
||||
#ifndef SHADERS_H
|
||||
#define SHADERS_H
|
||||
|
||||
ShaderProgram shaders_init(Project project, SharedContext *context,
|
||||
VideoCaptureArray inputs, ShaderProgram *previous);
|
||||
void shaders_init(ShaderProgram *program, Project *project,
|
||||
SharedContext *context, VideoCaptureArray inputs,
|
||||
bool rebind);
|
||||
|
||||
void shaders_update(ShaderProgram program, FileArray fragment_shaders,
|
||||
void shaders_update(ShaderProgram program, File fragment_shader,
|
||||
unsigned int i);
|
||||
|
||||
void shaders_compute(ShaderProgram program, SharedContext *context,
|
||||
|
||||
+18
-11
@@ -4,17 +4,6 @@
|
||||
|
||||
#include "string.h"
|
||||
|
||||
char *string_concat(const char *s1, const char *s2) {
|
||||
char *result;
|
||||
|
||||
result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
|
||||
|
||||
strcpy(result, s1);
|
||||
strcat(result, s2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int string_trim(char *str) {
|
||||
// https://www.delftstack.com/howto/c/trim-string-in-c/
|
||||
unsigned int start;
|
||||
@@ -62,3 +51,21 @@ bool string_is_number(char *value) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *string_replace_at(char *src, unsigned int from, unsigned int to,
|
||||
char *rpl) {
|
||||
unsigned long src_len, rpl_len;
|
||||
char *dst;
|
||||
|
||||
src_len = strlen(src);
|
||||
rpl_len = strlen(rpl);
|
||||
|
||||
dst =
|
||||
malloc(src_len - (to - from) + rpl_len + 1); // +1 for the null-terminator
|
||||
|
||||
strncpy(dst, src, from);
|
||||
strncpy(dst + from, rpl, rpl_len);
|
||||
strncpy(dst + from + rpl_len, src + to, src_len - to);
|
||||
|
||||
return dst;
|
||||
}
|
||||
+3
-2
@@ -3,10 +3,11 @@
|
||||
#ifndef STRINGS_H
|
||||
#define STRINGS_H
|
||||
|
||||
char *string_concat(const char *s1, const char *s2);
|
||||
|
||||
unsigned int string_trim(char *str);
|
||||
|
||||
bool string_is_number(char *value);
|
||||
|
||||
char *string_replace_at(char *src, unsigned int from, unsigned int to,
|
||||
char *rpl);
|
||||
|
||||
#endif /* STRINGS_H */
|
||||
+3
-2
@@ -242,12 +242,13 @@ typedef struct MidiDevice {
|
||||
|
||||
typedef struct Project {
|
||||
bool error;
|
||||
char path[STR_LEN];
|
||||
ConfigFile config;
|
||||
StateConfig state_config;
|
||||
FileArray fragment_shaders;
|
||||
File common_shader_code; // TODO change
|
||||
unsigned int frag_count;
|
||||
unsigned int in_count;
|
||||
UintArray sub_counts;
|
||||
File fragment_shaders[MAX_FRAG][MAX_SUB_FILE + 1];
|
||||
} Project;
|
||||
|
||||
#endif /* TYPES_H */
|
||||
Reference in New Issue
Block a user