diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3d8a289..2c11ce7 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -98,7 +98,8 @@ make -f Makefile.dev release-arch - [x] `forge_project.cfg` - [x] Define frag prefix in config - [ ] Use custom `#include xxx.glsl` preprocessor - - [ ] `--auto-random` / `--no-auto-random` + - [ ] Clean and sort args + - [x] `--auto-random` / `--no-auto-random` - [ ] Update readme with usage documentation - [x] Documentation in default config file - [x] Clone "shaders" and config in system path at setup diff --git a/README.md b/README.md index 2342e83..1397b0e 100644 --- a/README.md +++ b/README.md @@ -97,11 +97,12 @@ When running, the following keybindings are available: * Esc: Exit window * R: Randomize shader state * D: Demo mode On/Off +* A: Auto Random mode On/Off ### CLI arguments ```txt -usage: forge [-h] [-v] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-p=PROJECT_PATH] [-c=CFG_FILE] [-sf=STATE_PATH] [-ls / -nls] [-ss / -nss] [-is=SIZE] [-v=FILE] [-vs=SIZE] [-t=TEMPO] [-d] [-w] [-tm] [-tf] +usage: forge [-h] [-v] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-p=PROJECT_PATH] [-c=CFG_FILE] [-sf=STATE_PATH] [-ls / -nls] [-ss / -nss] [-is=SIZE] [-v=FILE] [-vs=SIZE] [-t=TEMPO] [-d] [-ar / -nar] [-w] [-tm] [-tf] Fusion Of Real-time Generative Effects. @@ -123,7 +124,9 @@ options: -v, --video-in path to video capture device (multiple allowed) -vs, --video-size video capture desired height (default: internal texture height) -t, --tempo base tempo (default: 60) - -d, --demo demonstration mode (assume --no-save-state and --no-load-state) + -d, --demo demonstration mode (assume --no-save-state , --no-load-state, --auto-random) + -ar, --auto-random randomize state every 4 beats + -nar, --no-auto-random do not randomize state (default) -w, --windowed not fullscreen -tm, --trace-midi print midi code and values -tf, --trace-fps print fps status of subsystems diff --git a/default/forge_project.cfg b/default/forge_project.cfg index c8ee1bf..6f6c4a9 100644 --- a/default/forge_project.cfg +++ b/default/forge_project.cfg @@ -35,6 +35,8 @@ UNIFORM_FPS=iFPS UNIFORM_IN_FPS_PREFIX=iInputFPS # 0/1 if demo UNIFORM_DEMO=iDemo +# 0/1 if auto random +UNIFORM_AUTORAND=iAutoRand # Current page UNIFORM_PAGE=iPage # Current selected shader diff --git a/default/frag0.glsl b/default/frag0.glsl index a8be55e..802b570 100644 --- a/default/frag0.glsl +++ b/default/frag0.glsl @@ -17,6 +17,7 @@ uniform vec2 iInputResolution2; uniform int iInputFormat1; uniform int iInputFormat2; uniform int iDemo; +uniform int iAutoRand; uniform int iPage; uniform int iSelected; @@ -1265,12 +1266,13 @@ subroutine(src_stage_sub) vec4 src_15(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 // logic - const int texts[5][5] = { + const int texts[6][5] = { {0x46, 0x50, 0x53, 0x00, 0x00}, // FPS {0x54, 0x45, 0x4D, 0x50, 0x4F}, // TEMPO {0x54, 0x49, 0x4D, 0x45, 0x00}, // TIME {0x44, 0x45, 0x4D, 0x4F, 0x00}, // DEMO {0x4C, 0x49, 0x56, 0x45, 0x00}, // LIVE + {0x2B, 0x52, 0x41, 0x4E, 0x44}, // +RAND }; vec2 uv2 = uv1; @@ -1384,7 +1386,12 @@ subroutine(src_stage_sub) vec4 src_15(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2); f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4)); - f += write_5(uv3, vec2(-2,-15), iDemo > 0 ? texts[3] : texts[4]); + if (iAutoRand > 0) { + f += write_5(uv3, vec2(-4,-15), iDemo > 0 ? texts[3] : texts[4]); + f += write_5(uv3, vec2(0,-15), texts[5]); + } else { + f += write_5(uv3, vec2(-2,-15), iDemo > 0 ? texts[3] : texts[4]); + } return vec4(f); } diff --git a/src/args.c b/src/args.c index f455b54..fe6a82d 100644 --- a/src/args.c +++ b/src/args.c @@ -30,6 +30,7 @@ static void print_help(int status_code) { "[-vs=SIZE] " "[-t=TEMPO] " "[-d] " + "[-ar / -nar] " "[-w] " "[-tm] " "[-tf] " @@ -59,7 +60,9 @@ static void print_help(int status_code) { "internal texture height)\n" " -t, --tempo base tempo (default: 60)\n" " -d, --demo demonstration mode (assume --no-save-state " - "and --no-load-state)\n" + ", --no-load-state, --auto-random)\n" + " -ar, --auto-random randomize state every 4 beats\n" + " -nar, --no-auto-random do not randomize state (default)\n" " -w, --windowed not fullscreen\n" " -tm, --trace-midi print midi code and values\n" " -tf, --trace-fps print fps status of subsystems\n"); @@ -116,6 +119,7 @@ Parameters args_parse(int argc, char **argv) { params.video_size = 0; params.base_tempo = 60.0f; params.demo = false; + params.auto_random = false; params.windowed = false; params.video_in.length = 0; params.trace_midi = false; @@ -175,6 +179,11 @@ Parameters args_parse(int argc, char **argv) { params.demo = true; params.load_state = false; params.save_state = false; + params.auto_random = true; + } else if (is_arg(arg, "-ar") || is_arg(arg, "--auto-random")) { + params.auto_random = true; + } else if (is_arg(arg, "-nar") || is_arg(arg, "--no-auto-random")) { + params.auto_random = false; } else if (is_arg(arg, "-w") || is_arg(arg, "--windowed")) { params.windowed = true; } else if (is_arg(arg, "-tm") || is_arg(arg, "--trace-midi")) { diff --git a/src/forge.c b/src/forge.c index 160a574..f2566b5 100644 --- a/src/forge.c +++ b/src/forge.c @@ -61,8 +61,8 @@ static void compute_fps(bool trace_fps) { static void init_context(Parameters params, unsigned int in_count) { unsigned int i; - state_init(context, state_config, params.demo, params.base_tempo, - params.state_file, params.load_state); + state_init(context, state_config, params.demo, params.auto_random, + params.base_tempo, params.state_file, params.load_state); context->monitor = params.monitor; @@ -199,6 +199,11 @@ static void key_callback(Window *window, int key, // D: demo on/off log_info((context->demo ? "[D] Demo OFF" : "[D] Demo ON")); context->demo = !context->demo; + } else if (window_char_key(key, action, 65)) { + // A: auto random on/off + log_info( + (context->auto_random ? "[A] Auto Random OFF" : "[A] Auto Random ON")); + context->auto_random = !context->auto_random; } } diff --git a/src/shaders.c b/src/shaders.c index de60551..69ad51e 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -268,6 +268,9 @@ static void init_single_program(ShaderProgram *program, unsigned int i, program->idemo_locations[i] = glGetUniformLocation( program->programs[i], config_file_get_str(config, "UNIFORM_DEMO", "iDemo")); + program->iautorand_locations[i] = glGetUniformLocation( + program->programs[i], + config_file_get_str(config, "UNIFORM_AUTORAND", "iAutoRand")); program->ipage_locations[i] = glGetUniformLocation( program->programs[i], config_file_get_str(config, "UNIFORM_PAGE", "iPage")); @@ -515,6 +518,8 @@ static void use_program(ShaderProgram program, int i, bool output, write_uniform_1f(program.ibeats_locations[i], context->tempo_total); write_uniform_1i(program.ifps_locations[i], context->fps); write_uniform_1i(program.idemo_locations[i], context->demo ? 1 : 0); + write_uniform_1i(program.iautorand_locations[i], + context->auto_random ? 1 : 0); write_uniform_1i(program.ipage_locations[i], context->page); write_uniform_1i(program.iselected_locations[i], context->selected + 1); write_uniform_2f(program.ires_locations[i], &context->resolution); diff --git a/src/state.c b/src/state.c index 038421c..78ecc3a 100644 --- a/src/state.c +++ b/src/state.c @@ -312,7 +312,7 @@ bool state_background_write(SharedContext *context, StateConfig state_config, change = tempo_progress(context->tempo, 4.0) < 0.25; - if (context->demo && change && !last_change) { + if (context->auto_random && change && !last_change) { state_randomize(context, state_config); } @@ -365,17 +365,19 @@ static void state_load(SharedContext *context, StateConfig state_config, } void state_init(SharedContext *context, StateConfig state_config, bool demo, - unsigned int base_tempo, char *state_file, bool load_state) { + bool auto_random, unsigned int base_tempo, char *state_file, + bool load_state) { unsigned int i; context->tempo = tempo_init(); tempo_set(&context->tempo, base_tempo); context->demo = demo; + context->auto_random = auto_random; context->state.length = state_config.select_frag_codes.length; memset(context->state.values, 0, sizeof(context->state.values)); - if (demo) { + if (auto_random) { state_randomize(context, state_config); } diff --git a/src/state.h b/src/state.h index b5aee05..b6bc929 100644 --- a/src/state.h +++ b/src/state.h @@ -13,7 +13,8 @@ bool state_background_write(SharedContext *context, StateConfig state_config, MidiDevice midi); void state_init(SharedContext *context, StateConfig state_config, bool demo, - unsigned int base_tempo, char *state_file, bool load_state); + bool auto_random, unsigned int base_tempo, char *state_file, + bool load_state); void state_randomize(SharedContext *context, StateConfig state_config); diff --git a/src/types.h b/src/types.h index c7b3e94..4d3a2d8 100644 --- a/src/types.h +++ b/src/types.h @@ -44,6 +44,7 @@ typedef struct Parameters { unsigned int video_size; float base_tempo; bool demo; + bool auto_random; bool windowed; StringArray video_in; bool trace_midi; @@ -96,6 +97,7 @@ typedef struct ShaderProgram { GLuint iinfmt_locations[ARRAY_SIZE]; GLuint iinfps_locations[ARRAY_SIZE]; GLuint idemo_locations[ARRAY_SIZE]; + GLuint iautorand_locations[ARRAY_SIZE]; GLuint iseed_locations[ARRAY_SIZE]; GLuint istate_locations[ARRAY_SIZE]; GLuint ipage_locations[ARRAY_SIZE]; @@ -165,6 +167,7 @@ typedef struct SharedContext { unsigned int active[ARRAY_SIZE]; vec3 values[ARRAY_SIZE]; bool demo; + bool auto_random; unsigned int seeds[MAX_FRAG]; bool monitor;