From 570c902909a2d7e58f2f5c6db48d453159e0013a Mon Sep 17 00:00:00 2001 From: klemek Date: Mon, 10 Nov 2025 23:00:45 +0100 Subject: [PATCH] docs: sample project --- default/forge_project.cfg | 6 +- sample/forge_project.cfg | 192 ++++++++++++++++++++++++++++++++++++++ sample/frag1.glsl | 66 +++++++++++++ sample/frag2.glsl | 10 ++ src/forge.c | 2 +- src/shaders.c | 6 +- src/shaders.h | 4 +- 7 files changed, 277 insertions(+), 9 deletions(-) create mode 100644 sample/forge_project.cfg create mode 100644 sample/frag1.glsl create mode 100644 sample/frag2.glsl diff --git a/default/forge_project.cfg b/default/forge_project.cfg index 6f6c4a9..430fd97 100644 --- a/default/forge_project.cfg +++ b/default/forge_project.cfg @@ -1,6 +1,6 @@ -########### -## FORGE ## -########### +################################## +## FORGE DEFAULT PROJECT CONFIG ## +################################## # Your reading a FORGE configuration file, don't panic # Everything here is designed to link elements between them # (shaders, video devices, textures, midi inputs, etc.) diff --git a/sample/forge_project.cfg b/sample/forge_project.cfg new file mode 100644 index 0000000..e47fca2 --- /dev/null +++ b/sample/forge_project.cfg @@ -0,0 +1,192 @@ +################################# +## FORGE SAMPLE PROJECT CONFIG ## +################################# +# Your reading a FORGE configuration file, don't panic +# Everything here is designed to link elements between them +# (shaders, video devices, textures, midi inputs, etc.) +# Every number based constant will be "one-based" (1,2,3,etc.) +# To read more, go to +# https://github.com/klemek/forge-steel + + +# ================ +# FRAGMENT SHADERS +# ================ + + +# === UNIFORMS === +# GLSL uniform names or prefixes +# Prefixed uniforms are "iVariableX" with a number + +# --- uniform float --- + +# Elapsed time +UNIFORM_TIME=iTime +# Current tempo +UNIFORM_TEMPO=iTempo +# Current total beats +UNIFORM_BEATS=iBeats + +# --- uniform int --- + +# Output frame per second +UNIFORM_FPS=iFPS +# 0/1 if demo +UNIFORM_DEMO=iDemo +# 0/1 if auto random +UNIFORM_AUTORAND=iAutoRand +# Seed for shader X +UNIFORM_SEED_PREFIX=iSeed + +# --- uniform vec2 --- + +# Output resolution +UNIFORM_RESOLUTION=iResolution + +# --- uniform vec3 --- + +# Midi group X layer Y (beware of group size) +# Injected as "iMidiX_Y[Z]" +UNIFORM_MIDI_PREFIX=iMidi + +# --- uniform sampler2D --- + +# Internal texture X +UNIFORM_TEX_PREFIX=iTex + + +# =========== +# TEXTURE I/O +# =========== + + +# Total number of internal textures +TEX_COUNT=1 + +# === FRAGMENT SHADERS +# Fragment shaders will be read from the CLI directory as "fragX.glsl" +# Special shader "frag0.glsl" will be prepend to each one + +# Prefix of fragment shaders to detect +FRAG_FILE_PREFIX=frag + +# Total number of fragment shaders (excluding frag0.glsl) +FRAG_COUNT=2 + +# To which texture will the shader fragX.glsl will render to +FRAG_1_OUT=0 +# Which fragment shader renders to output window +FRAG_OUTPUT=2 +# Which fragment shader renders to monitor window +FRAG_MONITOR=2 + + +# ======== +# MIDI I/O +# ======== + + +# The recognized ALSA name of the midi device +MIDI_HW=hw:CARD=nanoKONTROL2 + +# === TYPES OF EVENTS +# FORGE needs to differentiate between fader and buttons +# In the next configurations, when an event is not configured, +# it will be skipped + +# Total number of faders +FADER_COUNT=16 +# Midi codes of faders +FADER_1=0 +FADER_2=1 +FADER_3=2 +FADER_4=3 +FADER_5=4 +FADER_6=5 +FADER_7=6 +FADER_8=7 +FADER_9=16 +FADER_10=17 +FADER_11=18 +FADER_12=19 +FADER_13=20 +FADER_14=21 +FADER_15=22 +FADER_16=23 +# Midi code for tap tempo +TAP_TEMPO=46 + +# === MIDI INPUT STATES +# Midi inputs will control FORGE's state as follows +# X groups of Y layers sized Z +# You can manipulate only 1 layer at a time +# Every layer of every groups will be send as uniforms +# Each active layer will be sent back to the device +# with the same codes for nice display + +# Total number of groups +MIDI_COUNT=1 + +# Size of group 1 +MIDI_1_COUNT=20 +# Every code of active layer manipulation of group 1 +MIDI_1_1_X=32 +MIDI_1_1_Y=48 +MIDI_1_1_Z=64 +MIDI_1_2_X=0 +MIDI_1_2_Y=16 +MIDI_1_2_Z= +MIDI_1_3_X=33 +MIDI_1_3_Y=49 +MIDI_1_3_Z=65 +MIDI_1_4_X=1 +MIDI_1_4_Y=17 +MIDI_1_4_Z= +MIDI_1_5_X=34 +MIDI_1_5_Y=50 +MIDI_1_5_Z=66 +MIDI_1_6_X=2 +MIDI_1_6_Y=18 +MIDI_1_6_Z= +MIDI_1_7_X=35 +MIDI_1_7_Y=51 +MIDI_1_7_Z=67 +MIDI_1_8_X=3 +MIDI_1_8_Y=19 +MIDI_1_8_Z= +MIDI_1_9_X=36 +MIDI_1_9_Y=52 +MIDI_1_9_Z=68 +MIDI_1_10_X=4 +MIDI_1_10_Y=20 +MIDI_1_10_Z= +MIDI_1_11_X=37 +MIDI_1_11_Y=53 +MIDI_1_11_Z=69 +MIDI_1_12_X=5 +MIDI_1_12_Y=21 +MIDI_1_12_Z= +MIDI_1_13_X=38 +MIDI_1_13_Y=54 +MIDI_1_13_Z=70 +MIDI_1_14_X=6 +MIDI_1_14_Y=22 +MIDI_1_14_Z= +MIDI_1_15_X=39 +MIDI_1_15_Y=55 +MIDI_1_15_Z=71 +MIDI_1_16_X=7 +MIDI_1_16_Y=23 +MIDI_1_16_Z= +MIDI_1_17_X=58 +MIDI_1_17_Y=59 +MIDI_1_17_Z= +MIDI_1_18_X=60 +MIDI_1_18_Y=61 +MIDI_1_18_Z=62 +MIDI_1_19_X=43 +MIDI_1_19_Y=44 +MIDI_1_19_Z=42 +MIDI_1_20_X=41 +MIDI_1_20_Y=45 +MIDI_1_20_Z= diff --git a/sample/frag1.glsl b/sample/frag1.glsl new file mode 100644 index 0000000..a0ab544 --- /dev/null +++ b/sample/frag1.glsl @@ -0,0 +1,66 @@ +#version 460 + +#define PI 3.1415927 + +in vec2 vUV; +out vec4 fragColor; + +uniform float iTime; // elapsed time in seconds +uniform float iTempo; // current tempo in bpm +uniform float iBeats; // elapsed beats since last tempo reset +uniform int iFPS; // output window frames per seconds +uniform int iDemo; // 0/1 if demo mode +uniform int iAutoRand; // 0/1 if auto random mode +uniform int iSeed1; // a random seed assigned at start +uniform vec2 iResolution; // output window resolution in pixels +uniform vec3 iMidi1_1[20]; // all midi inputs defined +uniform sampler2D iTex0; // available texture (this code output, so feedback) + +void main() { + // all available buttons and faders + vec3 b1 = iMidi1_1[0]; + vec2 f1 = iMidi1_1[1].xy; + vec3 b2 = iMidi1_1[2]; + vec2 f2 = iMidi1_1[3].xy; + vec3 b3 = iMidi1_1[4]; + vec2 f3 = iMidi1_1[5].xy; + vec3 b4 = iMidi1_1[6]; + vec2 f4 = iMidi1_1[7].xy; + vec3 b5 = iMidi1_1[8]; + vec2 f5 = iMidi1_1[9].xy; + vec3 b6 = iMidi1_1[10]; + vec2 f6 = iMidi1_1[11].xy; + vec3 b7 = iMidi1_1[12]; + vec2 f7 = iMidi1_1[13].xy; + vec3 b8 = iMidi1_1[14]; + vec2 f8 = iMidi1_1[15].xy; + vec3 b9 = iMidi1_1[16]; + vec3 b10 = iMidi1_1[17]; + vec3 b11 = iMidi1_1[18]; + vec3 b12 = iMidi1_1[19]; + + // center UV and scale it to ratio + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // make small circle controlled by fader 1 and 2 + float circle_dist = 0.1 + 0.9 * f1.x; + float circle_size = 0.1 + 0.9 * f2.x; + vec2 circle_pos = circle_dist * vec2( + sin(iBeats * 2 * PI), + cos(iBeats * 2 * PI) + ); + float circle = 1 - step(circle_size, length(uv1 - circle_pos)); + + // fader 3, 4 and 5 controls the color + vec3 color = vec3( + f3.x, + f4.x, + f5.x + ); + vec3 out_color = mix(color, 1 - color, circle); + + // fader 8 controls the feedback value + fragColor = mix(vec4(out_color, 1), texture(iTex0, vUV.st), f8.x); +} \ No newline at end of file diff --git a/sample/frag2.glsl b/sample/frag2.glsl new file mode 100644 index 0000000..7f9ae21 --- /dev/null +++ b/sample/frag2.glsl @@ -0,0 +1,10 @@ +#version 460 + +in vec2 vUV; +out vec4 fragColor; + +uniform sampler2D iTex0; + +void main() { + fragColor = texture(iTex0, vUV); +} \ No newline at end of file diff --git a/src/forge.c b/src/forge.c index 5292f48..22e61f0 100644 --- a/src/forge.c +++ b/src/forge.c @@ -79,7 +79,7 @@ static void init_context(const 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][0], i); + shaders_update(&program, &project.fragment_shaders[i][0], i, &project); } static void init_inputs(const StringArray *video_in, unsigned int video_size) { diff --git a/src/shaders.c b/src/shaders.c index 4402144..faffcb1 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -458,15 +458,15 @@ void shaders_init(ShaderProgram *program, const Project *project, } } -void shaders_update(const ShaderProgram *program, const File *fragment_shader, - unsigned int i) { +void shaders_update(ShaderProgram *program, const File *fragment_shader, + unsigned int i, const Project *project) { bool result; result = compile_shader(program->fragment_shaders[i], fragment_shader->path, fragment_shader->content); if (result) { - glLinkProgram(program->programs[i]); + init_single_program(program, i, &project->config, &project->state_config); log_info("Program %d updated", i + 1); } diff --git a/src/shaders.h b/src/shaders.h index a71bbb8..ceb4913 100644 --- a/src/shaders.h +++ b/src/shaders.h @@ -7,8 +7,8 @@ void shaders_init(ShaderProgram *program, const Project *project, const SharedContext *context, VideoCaptureArray *inputs, bool rebind); -void shaders_update(const ShaderProgram *program, const File *fragment_shader, - unsigned int i); +void shaders_update(ShaderProgram *program, const File *fragment_shader, + unsigned int i, const Project *project); void shaders_compute(ShaderProgram *program, const SharedContext *context, bool monitor, bool output_only);