From cc569501de2559624cf4ee39d064881fbc6e8c25 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 23 Feb 2018 15:31:53 +0100 Subject: initial video recording --- shader.frag | 66 +++++++++++++++++---- sv.c | 193 +++++++++++++++++++----------------------------------------- 2 files changed, 114 insertions(+), 145 deletions(-) diff --git a/shader.frag b/shader.frag index 07b7a28..f76c968 100644 --- a/shader.frag +++ b/shader.frag @@ -4,14 +4,12 @@ precision mediump float; #endif uniform vec2 resolution; +uniform float time; uniform float ticks; uniform int program; uniform sampler2D images[8]; layout (binding = 0,rgba32f) uniform image2D backbuffer; -uniform float ratios[4]; -uniform int idx[2]; -uniform float vel[2]; uniform float params[4]; out vec4 fragColor; @@ -20,19 +18,63 @@ float random (in float x) { return fract(sin(x)*43758.5453123)-0.5; } -vec2 coordinates(int i) { - vec2 st = gl_FragCoord.xy/resolution.xy; +vec2 st() { + return gl_FragCoord.xy/resolution.xy; +} +ivec2 ist() { + return ivec2(gl_FragCoord.xy/resolution.xy*resolution); +} + +vec2 zoom(vec2 st, float amount) { + st -= 0.5; + st *= amount; + st += 0.5; + return st; +} + +vec2 translate(vec2 st, vec2 amount) { + st -= 0.5; + st += amount; + st += 0.5; return st; } +mat2 rotate2d(float _angle){ + return mat2(cos(_angle),-sin(_angle), sin(_angle),cos(_angle)); +} + void main (void) { - vec4 img; - vec2 st = coordinates(idx[0]); - img = texture2D(images[idx[0]],st); - st = coordinates(idx[1]); - img = pow(img, texture2D(images[idx[1]],st)); - if (program != 0) { - img.rgb = img.rgb*params[0]; + vec4 img; + vec2 coord; + if (program == 0) { + //coord = zoom(st(),0.5*(1.0-params[0])); + coord = zoom(st(),sin(time)); + img = texture2D(images[0],coord); + img -= params[1]*(1.0-texture2D(images[1],st())); + } + else if (program == 1) { + coord = zoom(st(),(1.0-1.5*params[0])); + img = texture2D(images[3],coord); + coord = zoom(st(),0.5*(1.0-0.5*params[2])); + vec3 i2 = texture2D(images[2],coord).rgb; + img.rgb = pow(img.rgb,5*i2); } + else if (program == 2) { + coord = zoom(st(),(1.0-1.5*params[0])); + img = texture2D(images[3],coord); + coord = zoom(st(),0.5*(1.0-0.5*params[2])); + coord *= rotate2d(ticks); + vec3 i2 = texture2D(images[2],coord).rgb; + img.rgb = pow(img.rgb,5*i2); + } + vec4 feedback = imageLoad(backbuffer,ist()); + img = mix(img,feedback,0.5); + imageStore(backbuffer,ist(),img); fragColor = img; + /* + fragColor = vec4(params[1]); + feedback.b += 0.01*cos(time/4.); + color.r = max(i.r,feedback.r); + */ } + diff --git a/sv.c b/sv.c index 93a822d..2c48620 100644 --- a/sv.c +++ b/sv.c @@ -16,14 +16,13 @@ #define MIDICHK(stmt, msg) if((stmt) < 0) {puts("ERROR: "#msg); exit(1);} -int width = 1920; -int height = 1080; +int width = 1918; +int height = 1078; GLFWwindow* window; GLuint vertex; GLuint fragment; GLuint shaderProgram; GLuint backbuffer; -int bars; typedef struct Shad { GLuint id; @@ -37,26 +36,22 @@ Shader shader; typedef struct Img { GLuint id; char path[40]; - float ratio; int new; } Image; Image images[8]; -typedef struct Param { - float value; - int new; -} Parameter; +float params[4]; -Parameter params[4]; +int recording = 1; static snd_seq_t *seq_handle; static int in_port; void midi_open(void) { MIDICHK(snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0), "Could not open sequencer"); - MIDICHK(snd_seq_set_client_name(seq_handle, "Midi Listener"), "Could not set client name"); - MIDICHK(in_port = snd_seq_create_simple_port(seq_handle, "listen:in", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION), "Could not open port"); + MIDICHK(snd_seq_set_client_name(seq_handle, "SV"), "Could not set client name"); + MIDICHK(in_port = snd_seq_create_simple_port(seq_handle, "sv:in", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION), "Could not open port"); } void screenshot() { @@ -149,21 +144,30 @@ void createShader() { glUseProgram(shader.id); }; +void imageUniforms(int i) { + glUniform1i(glGetUniformLocation(shader.id, "images")+i,i); + //glUniform1f(glGetUniformLocation(shader.id, "ratios")+i,images[i].ratio); +} + +void resize_callback(GLFWwindow* window, int w, int h) { + width = w; + height = h; + glUniform2f(glGetUniformLocation(shader.id, "resolution"),width,height); +} + void createWindow() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - window = glfwCreateWindow(width,height, "", glfwGetPrimaryMonitor(), NULL); + //glfwWindowHint(GLFW_DECORATED, GL_FALSE); + window = glfwCreateWindow(width,height, "sv", NULL, NULL); + //window = glfwCreateWindow(width,height, "", glfwGetPrimaryMonitor(), NULL); + //glfwSetWindowSizeCallback(window, resize_callback); glfwMakeContextCurrent(window); glfwSetKeyCallback(window, key_callback); glfwSetErrorCallback(error_callback); glewInit(); } -void imageUniforms(int i) { - glUniform1i(glGetUniformLocation(shader.id, "images")+i,i); - glUniform1f(glGetUniformLocation(shader.id, "ratios")+i,images[i].ratio); -} - void readImage(int i) { images[i].new = 1; @@ -172,7 +176,7 @@ void readImage(int i) { stbi_set_flip_vertically_on_load(1); unsigned char* pixels = stbi_load(images[i].path, &w, &h, &comp, STBI_rgb_alpha); - images[i].ratio = (float) w/h; + //images[i].ratio = (float) w/h; imageUniforms(i); glActiveTexture(GL_TEXTURE0+i); @@ -184,6 +188,8 @@ void readImage(int i) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); stbi_image_free(pixels); } @@ -192,27 +198,20 @@ void updateImages(int force) { for (int i = 0; i<8; i++) { if (images[i].new || force) { readImage(i); - printf("%s\n",images[i].path); images[i].new = 0; } } } -void updateParams(int force) { - glUniform1i(glGetUniformLocation(shader.id, "bars"), bars); +void updateParams() { for (int i = 0; i<4; i++) { - if (params[i].new || force) { - glUniform1f(glGetUniformLocation(shader.id, "params")+i, params[i].value); - params[i].new = 0; - } + glUniform1f(glGetUniformLocation(shader.id, "params")+i, params[i]); } } int ticks =0; int running = 0; -int idx[2] = {0,1}; -float vel[2] = {0,0}; -int program; +int program=0; void *readMidi() { midi_open(); @@ -221,113 +220,23 @@ void *readMidi() { snd_seq_event_input(seq_handle, &ev); if (ev->type == SND_SEQ_EVENT_NOTEON) { int note = ev->data.note.note; - int v = ev->data.note.velocity; - int i,j; - if (note < 48) { - i = 0; - j = note-36; - } - else { - i = 1; - j = note-48; - } - // only white keys - if (j == 0) { - idx[i] = 0; vel[i] = (float)v/127.0; - } - else if (j == 2) { - idx[i] = 1; vel[i] = (float)v/127.0; - } - else if (j == 4) { - idx[i] = 2; vel[i] = (float)v/127.0; - } - else if (j == 5) { - idx[i] = 3; vel[i] = (float)v/127.0; - } - else if (j == 7) { - idx[i] = 4; vel[i] = (float)v/127.0; - } - else if (j == 9) { - idx[i] = 5; vel[i] = (float)v/127.0; - } - else if (j == 11) { - idx[i] = 6; vel[i] = (float)v/127.0; - } - else if (j == 12) { - idx[i] = 7; vel[i] = (float)v/127.0; - } - - } - else if (ev->type == SND_SEQ_EVENT_NOTEOFF) { - int note = ev->data.note.note; - int i,j; - if (note < 48) { - i = 0; - j = note-36; - } - else { - i = 1; - j = note-48; - } - // only white keys - if (j == 0) { - idx[i] = 0; vel[i] = 0; - } - else if (j == 2) { - idx[i] = 1; vel[i] = 0; - } - else if (j == 4) { - idx[i] = 2; vel[i] = 0; - } - else if (j == 5) { - idx[i] = 3; vel[i] = 0; - } - else if (j == 7) { - idx[i] = 4; vel[i] = 0; - } - else if (j == 9) { - idx[i] = 5; vel[i] = 0; - } - else if (j == 11) { - idx[i] = 6; vel[i] = 0; - } - else if (j == 12) { - idx[i] = 7; vel[i] = 0; - } + if (note >= 36) program = note-36; } else if(ev->type == SND_SEQ_EVENT_CONTROLLER) { int p = ev->data.control.param; int v = ev->data.control.value; - if (p < 4) { - params[p].value = (float)v/127; - params[p].new = 1; - } - /* - printf("[%d] Control: %2x val(%2x)\n", ev->time.tick, - ev->data.control.param, - ev->data.control.value); - */ + if (p < 4) params[p] = (float)v/127.0; } - else if(ev->type == SND_SEQ_EVENT_PGMCHANGE) { - program = ev->data.control.value; - } - else if(ev->type == SND_SEQ_EVENT_SONGPOS) { + else if(ev->type == SND_SEQ_EVENT_SONGPOS) ticks = ev->data.control.value*24; - printf("[%d] SPP: %i val(%i)\n", ev->time.tick, - ev->data.control.param, - ev->data.control.value); - } else if(ev->type == SND_SEQ_EVENT_START) running = 1; else if(ev->type == SND_SEQ_EVENT_STOP) running = 0; else if(ev->type == SND_SEQ_EVENT_CONTINUE) running = 1; - else if(ev->type == SND_SEQ_EVENT_CLOCK) { + else if(ev->type == SND_SEQ_EVENT_CLOCK) if (running == 1) ticks++; - } - //else - //printf("[%d] Unknown: Unhandled Event Received\n", ev->time.tick); } } @@ -355,36 +264,54 @@ int main(int argc, char **argv) { glCreateTextures(GL_TEXTURE_2D,1,&backbuffer); glTextureStorage2D(backbuffer,1,GL_RGBA32F,width,height); glBindImageTexture(0,backbuffer, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + updateImages(0); pthread_t midiin_t; pthread_create(&midiin_t, NULL, readMidi, NULL); pthread_t frag_t; pthread_create(&frag_t, NULL, watchShader, NULL); + FILE* ffmpeg; + if (recording) { + //char* cmd; + printf("%ix%i\n",width,height); + time_t current_time = time(NULL); + char output_file[25]; + strftime(output_file, 25, "%Y-%m-%d_%H%M%S.mp4", localtime(¤t_time)); + //printf(output_file); + const char* cmd = "ffmpeg -r 24 -f rawvideo -pix_fmt rgba -s 1918x1078 -i - " + "-threads 0 -preset veryfast -y -pix_fmt yuv420p -c:v libx264 -crf 18 -vf vflip output.mp4"; + + printf(cmd); + ffmpeg = popen(cmd, "w"); + /* + sprintf(cmd,"ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %ix%i -i - -threads 0 -preset fast -y -pix_fmt yuv420p -crf 21 -vf vflip %s",width,height,output_file); + */ + } + while (!glfwWindowShouldClose(window)) { - //glUniform1f(glGetUniformLocation(shader.id, "time"),glfwGetTime()); - //glUniform1f(glGetUniformLocation(shader.id, "time"),glfwGetTime()); + glUniform1f(glGetUniformLocation(shader.id, "time"),glfwGetTime()); glUniform1f(glGetUniformLocation(shader.id, "ticks"),(float)ticks); glUniform1i(glGetUniformLocation(shader.id, "program"),program); - for (int i = 0; i<2; i++) { - glUniform1i(glGetUniformLocation(shader.id, "idx")+i,idx[i]); - glUniform1f(glGetUniformLocation(shader.id, "vel")+i,vel[i]); - } if (shader.new) { createShader(); glUniform2f(glGetUniformLocation(shader.id, "resolution"),width,height); // important!! - for (int i = 0; i<4; i++) { imageUniforms(i); } - updateParams(1); + for (int i = 0; i<8; i++) { imageUniforms(i); } + updateParams(); shader.new = 0; } - updateImages(0); - updateParams(0); + updateParams(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glfwSwapBuffers(window); + if (recording) { + unsigned char buffer[width*height*4]; + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + fwrite(buffer, sizeof(int)*width*height, 1, ffmpeg); + } glfwPollEvents(); } - //pthread_cancel(stdin_t); + if (recording) pclose(ffmpeg); pthread_cancel(midiin_t); pthread_cancel(frag_t); glfwDestroyWindow(window); -- cgit v1.2.3