diff --git a/README.md b/README.md index 3e0e485..9208f88 100644 --- a/README.md +++ b/README.md @@ -115,8 +115,8 @@ make -f Makefile.dev release-arch - [x] demo mode - [x] random seed injected into shaders - [x] internal texture size for speed - - [ ] pass state as uniform - - [ ] debug shader (and in monitor) + - [x] pass state as uniform + - [x] debug shader (and in monitor) - [ ] Clean code and fix things - [ ] Midi - [ ] Read Midi events diff --git a/config/shaders.cfg b/config/shaders.cfg index b175237..51a5c2f 100644 --- a/config/shaders.cfg +++ b/config/shaders.cfg @@ -4,9 +4,10 @@ UNIFORM_FPS=iFPS UNIFORM_DEMO=iDemo UNIFORM_RESOLUTION=iResolution UNIFORM_SEED_PREFIX=seed +UNIFORM_STATE_PREFIX=state UNIFORM_TEX_PREFIX=tex -TEX_COUNT=9 +TEX_COUNT=8 FRAG_COUNT=8 FRAG_OUTPUT=7 @@ -15,7 +16,7 @@ FRAG_1_OUT=2 FRAG_2_OUT=5 FRAG_3_OUT=3 FRAG_4_OUT=6 -FRAG_5_OUT=8 +FRAG_5_OUT=7 FRAG_6_OUT=0 SUB_TYPE_COUNT=3 diff --git a/shaders/frag0.glsl b/shaders/frag0.glsl index b099bf7..cd118c2 100644 --- a/shaders/frag0.glsl +++ b/shaders/frag0.glsl @@ -21,6 +21,13 @@ uniform int seed6; uniform int seed7; uniform int seed8; +uniform int state1_1; +uniform int state2_1; +uniform int state3_2; +uniform int state4_2; +uniform int state5_3; +uniform int state6_2; + // 2. textures // --------------- @@ -166,8 +173,8 @@ float cosTime(float k) vec2 magic_f(vec2 F, vec3 B, float i) { return vec2( - mix(F.x, randTime(i + 1), B.z + iDemo), - mix(F.y, randTime(i + 2), B.z + iDemo) + mix(F.x, randTime(i + 1), min(1, B.z + iDemo)), + mix(F.y, randTime(i + 2), min(1, B.z + iDemo)) ); } @@ -179,8 +186,8 @@ vec2 magic_f(float i) vec3 magic_b(vec3 B, float i) { return vec3( - mix(B.x, step(0.2, randTime(i + 3)), B.z + iDemo), - mix(B.y, step(0.5, randTime(i + 4)), B.z + iDemo), + mix(B.x, step(0.2, randTime(i + 3)), min(1, B.z + iDemo)), + mix(B.y, step(0.5, randTime(i + 4)), min(1, B.z + iDemo)), min(1, B.z + iDemo) ); } @@ -810,7 +817,7 @@ int read(sampler2D tex, vec2 uv, float k, int d, float t) float inv_k = 1 / k; vec2 tex_uv = floor(uv * k) * inv_k; tex_uv += vec2(d % 2, floor(d * 0.5)) * 0.5 * inv_k; - return // TODO threshold + return ((mean(reframe(tex, tex_uv + vec2(0, 3) * inv_k * 0.125)) > t) ? 1 : 0) + ((mean(reframe(tex, tex_uv + vec2(0, 2) * inv_k * 0.125)) > t) ? 2 : 0) + ((mean(reframe(tex, tex_uv + vec2(0, 1) * inv_k * 0.125)) > t) ? 4 : 0) + @@ -1237,13 +1244,89 @@ subroutine(src_stage_sub) vec4 src_16(vec2 vUV, int seed) float ratio = iResolution.x / iResolution.y; vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); - // controls + // inputs + + int selected = 0; // TODO debug selected + int page = 0; // TODO debug page + int selected_src = 0; // TODO debug selected + int selected_fx = 0; // TODO debug selected + int selected_srca = state1_1; + int selected_srcb = state2_1; + int selected_fxa = state3_2; + int selected_fxb = state4_2; + int selected_mfx = state6_2; + float fxa_value = magic(seed3); + float fxb_value = magic(seed4); + float mfx_value = magic(seed6); + float mix_value = magic(seed5); + int mix_type = state5_3 % 2; // logic - // TODO tmp + vec2 uv2 = uv1; + + uv2 *= 10; + uv2.x -= 0.5; + uv2.y += 0.5; + + // base frame + float f = + h_rect(uv2, vec2(-5, -2), vec2(1), 0.1) + + h_rect(uv2, vec2(-2, -2), vec2(1), 0.1) + + rect(uv2, vec2(-3.5, -2), vec2(0.5, 0.1)) + + h_rect(uv2, vec2(-5, 2), vec2(1), 0.1) + + h_rect(uv2, vec2(-2, 2), vec2(1), 0.1) + + rect(uv2, vec2(-3.5, 2), vec2(0.5, 0.1)) + + h_rect(uv2, vec2(2, 0), vec2(1), 0.1) + + h_rect(uv2, vec2(5, 0), vec2(1), 0.1) + + rect(uv2, vec2(3.5, 0), vec2(0.5, 0.1)) + + rect(uv2, vec2(0.55, -2), vec2(1.5, 0.1)) + + rect(uv2, vec2(2, -1.55), vec2(0.1, 0.55)) + + rect(uv2, vec2(0.55, 2), vec2(1.5, 0.1)) + + rect(uv2, vec2(2, 1.55), vec2(0.1, 0.55)) + + rect(uv2, vec2(7.5, 0), vec2(1.5, 0.1)) + + h_rect(uv2, vec2(-9, 5.1), vec2(1), 0.1); + + // show selected src/fx + f += char_at(uv2, vec2(-5.4, 1.45), hex_chars[selected_srca]); + f += char_at(uv2, vec2(-5.4, -2.55), hex_chars[selected_srcb]); + f += char_at(uv2, vec2(-2.4, 1.45), hex_chars[selected_fxa]); + f += char_at(uv2, vec2(4.6, -0.55), hex_chars[selected_fxb]); + f += char_at(uv2, vec2(-2.4, -2.55), hex_chars[selected_mfx]); + + // show current selected + f += selected == 0 ? h_rect(uv2, vec2(-5, 2), vec2(1.2), 0.1) : 0; + f += selected == 1 ? h_rect(uv2, vec2(-5, -2), vec2(1.2), 0.1) : 0; + f += selected == 2 ? h_rect(uv2, vec2(-2, 2), vec2(1.2), 0.1) : 0; + f += selected == 3 ? h_rect(uv2, vec2(5, 0), vec2(1.2), 0.1) : 0; + f += selected == 4 ? h_rect(uv2, vec2(-2, -2), vec2(1.2), 0.1) : 0; + + // show selected src/fx + f += selected_src == 0 ? h_rect(uv2, vec2(-5, 0.8), vec2(1, 0), 0.1) : 0; + f += selected_src == 1 ? h_rect(uv2, vec2(-5, -3.2), vec2(1, 0), 0.1) : 0; + f += selected_fx == 2 ? h_rect(uv2, vec2(-2, 0.8), vec2(1.2, 0), 0.1) : 0; + f += selected_fx == 3 ? h_rect(uv2, vec2(5, -1.2), vec2(1, 0), 0.1) : 0; + f += selected_fx == 4 ? h_rect(uv2, vec2(-2, -3.2), vec2(1, 0), 0.1) : 0; + + // show inputs / feedback + f += (selected_srca == 5 || selected_srca == 10) ? rect(uv2, vec2(-8, 2), vec2(2, 0.1)) : 0; + f += (selected_srca == 0 || selected_srca % 5 != 0 && selected_srca >= 8) ? rect(uv2, vec2(-6.5, 2), vec2(0.5, 0.1)) + rect(uv2, vec2(0, 4), vec2(7, 0.1)) + rect(uv2, vec2(-7, 3), vec2(0.1, 1.1)) + rect(uv2, vec2(7, 2), vec2(0.1, 2.1)) : 0; + f += (selected_srcb == 5 || selected_srcb == 10) ? rect(uv2, vec2(-8, -2), vec2(2, 0.1)) : 0; + f += (selected_srcb == 0 || selected_srcb % 5 != 0 && selected_srcb >= 8) ? rect(uv2, vec2(-6.5, -2), vec2(0.5, 0.1)) + rect(uv2, vec2(0, -4), vec2(7, 0.1)) + rect(uv2, vec2(-7, -3), vec2(0.1, 1.1)) + rect(uv2, vec2(7, -2), vec2(0.1, 2.1)) : 0; + + // show page + f += char_at(uv2, vec2(-9.2, 4.3), hex_chars[page]); + + // show fx values + f = mix(f, 1 - f, rect(uv2, vec2(-2, 1.1 + 0.9 * fxa_value), vec2(0.9, 0.9 * fxa_value))); + f = mix(f, 1 - f, rect(uv2, vec2(5, -0.9 + 0.9 * fxb_value), vec2(0.9, 0.9 * fxb_value))); + f = mix(f, 1 - f, rect(uv2, vec2(-2, -2.9 + 0.9 * mfx_value), vec2(0.9, 0.9 * mfx_value))); + + // show mix + f += char_at(uv2, vec2(1.55, -0.6), mix_type > 0 ? 0x4B : 0x4D); + f = mix(f, 1 - f, rect(uv2, vec2(2, -0.9 + 0.9 * mix_value), vec2(0.9, 0.9 * mix_value))); - return texture(tex0, vUV); + return vec4(f); } // 6. effects @@ -1706,7 +1789,7 @@ subroutine(mix_stage_sub) vec4 mix_1(vec2 vUV, sampler2D ta, sampler2D tb, int s // controls - float mix_src = magic(seed + 10); + float mix_src = magic(seed); // logic @@ -1725,7 +1808,7 @@ subroutine(mix_stage_sub) vec4 mix_2(vec2 vUV, sampler2D ta, sampler2D tb, int s // controls - float mix_src = magic(seed + 10); + float mix_src = magic(seed); // logic diff --git a/shaders/frag6.glsl b/shaders/frag6.glsl index 7b8b3cd..4899919 100644 --- a/shaders/frag6.glsl +++ b/shaders/frag6.glsl @@ -1,6 +1,6 @@ // MFX // ------------ -// IN: 8 (A+B) +// IN: 7 (A+B) // IN: 0 (OUT) // OUT: 0 (OUT) @@ -8,5 +8,5 @@ in vec2 vUV; out vec4 fragColor; void main() { - fragColor = fx_stage(vUV, tex8, tex0, seed6); + fragColor = fx_stage(vUV, tex7, tex0, seed6); } \ No newline at end of file diff --git a/shaders/frag8.glsl b/shaders/frag8.glsl index 4c7b3bc..6a60789 100644 --- a/shaders/frag8.glsl +++ b/shaders/frag8.glsl @@ -26,15 +26,15 @@ void main() { vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); vec2 uv2 = uv0 * 3; - vec2 uv3 = uv1 * 30; + vec2 uv3 = uv1 * 60; vec4 c = vec4(0); c += s(uv2,0,2) * texture(tex1, uv2); c += s(uv2,1,2) * texture(tex2, uv2); c += s(uv2,2,2) * texture(tex3, uv2); - c += s(uv2,0,1) * texture(tex7, uv2); - c += s(uv2,1,1) * texture(tex8, uv2); + c += s(uv2,0,1) * src_16(mod(uv2, 1), 0); + c += s(uv2,1,1) * texture(tex7, uv2); c += s(uv2,2,1) * texture(tex0, uv2); c += s(uv2,0,0) * texture(tex4, uv2); c += s(uv2,1,0) * texture(tex5, uv2); @@ -42,14 +42,14 @@ void main() { float t = 0; - t += write_5(uv3, vec2(-26.5,13.5), texts[0]); - t += write_5(uv3, vec2(-26.5,-6.5), texts[1]); - t += write_5(uv3, vec2(-8.5,13.5), texts[2]); - t += write_5(uv3, vec2(-8.5,-6.5), texts[3]); - t += write_5(uv3, vec2(9.5,13.5), texts[4]); - t += write_5(uv3, vec2(9.5,-6.5), texts[5]); - t += write_5(uv3, vec2(-8.5,3.5), texts[6]); - t += write_5(uv3, vec2(9.5,3.5), texts[7]); + t += write_5(uv3, vec2(-53,28), texts[0]); + t += write_5(uv3, vec2(-53,-12), texts[1]); + t += write_5(uv3, vec2(-17,28), texts[2]); + t += write_5(uv3, vec2(-17,-12), texts[3]); + t += write_5(uv3, vec2(19,28), texts[4]); + t += write_5(uv3, vec2(19,-12), texts[5]); + t += write_5(uv3, vec2(-17,8), texts[6]); + t += write_5(uv3, vec2(19,8), texts[7]); fragColor = mix(c, 1 - c, t); } \ No newline at end of file diff --git a/src/shaders.c b/src/shaders.c index 132b202..36f2ac5 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -141,6 +141,7 @@ static void init_single_program(ShaderProgram *program, unsigned int i, char *tex_prefix; char *sub_prefix; char *seed_prefix; + char *state_prefix; program->programs[i] = glCreateProgram(); @@ -173,6 +174,18 @@ static void init_single_program(ShaderProgram *program, unsigned int i, glGetUniformLocation(program->programs[i], name); } + state_prefix = + config_file_get_str(shader_config, "UNIFORM_STATE_PREFIX", "state"); + for (j = 0; j < program->frag_count; j++) { + for (k = 0; k < program->sub_type_count; k++) { + sprintf(name, "%s%d_%d", state_prefix, j + 1, k + 1); + program + ->istate_locations[i * program->frag_count * program->sub_type_count + + j * program->sub_type_count + k] = + glGetUniformLocation(program->programs[i], name); + } + } + for (j = 0; j < program->sub_type_count; j++) { sprintf(name, "SUB_%d_PREFIX", j + 1); sub_prefix = config_file_get_str(shader_config, name, 0); @@ -217,6 +230,8 @@ static void init_programs(ShaderProgram *program, ConfigFile shader_config) { program->idemo_locations = malloc(program->frag_count * sizeof(GLuint)); program->iseed_locations = malloc(program->frag_count * program->frag_count * sizeof(GLuint)); + program->istate_locations = malloc(program->frag_count * program->frag_count * + program->sub_type_count * sizeof(GLuint)); program->vpos_locations = malloc(program->frag_count * sizeof(GLuint)); program->textures_locations = malloc(program->frag_count * program->tex_count * sizeof(GLuint)); @@ -335,12 +350,19 @@ static void use_program(ShaderProgram program, int i, bool output, (const GLint)context.seeds[j]); } - // set subroutines for fragment + // set subroutines for fragment and update state uniforms for (j = 0; j < program.sub_type_count; j++) { k = context.sub_state[i * program.sub_type_count + j]; subroutines[j] = program.sub_locations[i * program.sub_type_count * program.sub_variant_count + j * program.sub_variant_count + k]; + for (k = 0; k < program.frag_count; k++) { + glUniform1i( + program.istate_locations[i * program.frag_count * + program.sub_type_count + + k * program.sub_type_count + j], + (const GLint)context.sub_state[k * program.sub_type_count + j]); + } } glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, program.sub_type_count, diff --git a/src/types.h b/src/types.h index f1254df..0ec205f 100644 --- a/src/types.h +++ b/src/types.h @@ -60,6 +60,7 @@ typedef struct ShaderProgram { GLuint *ires_locations; GLuint *idemo_locations; GLuint *iseed_locations; + GLuint *istate_locations; GLuint *vpos_locations;