Updated gravity transform, cleaned up graph shader

This commit is contained in:
Jarcode
2017-11-28 11:47:28 -08:00
parent a0b7a1c363
commit bd3b0b1457
6 changed files with 109 additions and 43 deletions

View File

@@ -68,7 +68,7 @@ int main(int argc, char** argv) {
audio.modified = false; /* set this flag to false until the next time we read */
}
pthread_mutex_unlock(&audio.mutex);
/* Only render if needed (ie. stop rendering when fullscreen windows are focused) */
if (xwin_should_render()) {
rd_update(r, lb, rb, r->bufsize_request, modified);

View File

@@ -350,10 +350,10 @@ struct gl_data {
int lww, lwh; /* last window height */
int rate; /* framerate */
double tcounter;
int fcounter;
int fcounter, ucounter;
bool print_fps, avg_window;
void** t_data;
float gravity_step;
float gravity_step, target_spu;
};
#ifdef GLAD_DEBUG
@@ -388,7 +388,6 @@ static struct gl_bind_src bind_sources[] = {
#define window(t, sz) (0.53836 - (0.46164 * cos(TWOPI * (double) t / (double)(sz - 1))))
#define ALLOC_ONCE(u, udata, ...) \
if (*udata == NULL) { \
printf("alloc"); \
u = malloc(sizeof(*u)); \
*u = (typeof(*u)) __VA_ARGS__; \
*udata = u; \
@@ -563,6 +562,7 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
.rate = 0,
.tcounter = 0.0D,
.fcounter = 0,
.ucounter = 0,
.print_fps = true,
.bufscale = 1,
.avg_frames = 4,
@@ -805,7 +805,7 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
loading_module = false;
/* Iterate through shader passes in the shader directory and build textures, framebuffers, and
shader programs with each fragment shader. */
shader programs with each fragment shader. */
struct gl_sfbo* stages;
size_t count = 0;
@@ -870,7 +870,7 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
s->shader = id;
/* Only setup a framebuffer and texture if this isn't the final step,
as it can rendered directly */
as it can rendered directly */
if (idx != count)
setup_sfbo(&stages[idx - 1], w, h);
@@ -892,10 +892,15 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) {
++idx;
} while (found);
}
gl->stages = stages;
gl->stages_sz = count;
/* target seconds per update */
gl->target_spu = (float) (r->samplesize_request / 4) / (float) r->rate_request;
/* multiply gravity step by time occurred for each step */
gl->gravity_step *= gl->target_spu;
gl->audio_tex_r = create_1d_tex();
gl->audio_tex_l = create_1d_tex();
@@ -1000,16 +1005,18 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
/* Handle transformations and bindings for 1D samplers */
void handle_1d_tex(GLuint tex, float* buf, size_t sz, int offset) {
/* Only apply transformations if the buffers we given are newly copied from PA */
/* Only apply transformations if the buffers we
were given are newly copied from PA */
if (modified) {
size_t t;
struct gl_sampler_data d = {
.buf = buf, .sz = sz
};
for (t = 0; t < bind->t_sz; ++t) {
bind->transformations[t](gl, &gl->t_data[c], &d);
++c; /* index for transformation data (note: change if new transform types are added) */
++c; /* Index for transformation data (note: change if new
transform types are added) */
}
}
@@ -1077,11 +1084,16 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
/* print FPS counter (if needed) */
if (gl->print_fps) {
++gl->fcounter;
if (modified)
++gl->ucounter;
gl->tcounter += duration;
if (gl->tcounter >= 1.0D) {
printf("FPS: %.2f\n", ((double) gl->fcounter / gl->tcounter));
printf("FPS: %.2f, UPS: %.2f\n",
((double) gl->fcounter / gl->tcounter),
((double) gl->ucounter / gl->tcounter));
gl->tcounter = 0;
gl->fcounter = 0;
gl->ucounter = 0;
}
}
}

View File

@@ -7,10 +7,50 @@ uniform ivec2 screen; /* screen dimensions */
#request uniform "audio_sz" audio_sz
uniform int audio_sz;
#request setavgframes 4
/* How many frames to queue and run through the average function */
#request setavgframes 6
/* Whether to window frames ran through the average function (new & old frames
are weighted less). This massively helps smoothing out spikes in the animation */
#request setavgwindow true
// #request interpolate true
#request setgravitystep 0.06
/* Gravity step, higher values means faster drops. The step is applied in a rate
independant method like so:
val -= (gravitystep) * (seconds per update) */
#request setgravitystep 5.2
/* When we transform our audio, we need to go through the following steps:
transform -> "window"
First, apply a window function to taper off the ends of the spectrum, helping
avoid artifacts in the FFT output.
transform -> "fft"
Apply the Fast Fourier Transform algorithm to separate raw audio data (waves)
into their respective spectrums.
transform -> "fft"
As part of the FFT process, we return spectrum magnitude on a log(n) scale,
as this is how the (decibel) dB scale functions.
transform -> "gravity"
To help make our data more pleasing to look at, we apply our data received over
time to a buffer, taking the max of either the existing value in the buffer or
the data from the input. We then reduce the data by the 'gravity step', and
return the storage buffer.
This makes frequent and abrupt changes in frequency less distracting, and keeps
short frequency responses on the screen longer.
transform -> "avg"
As a final step, we take the average of several data frames (specified by
'setavgframes') and return the result to further help smooth the resulting
animation. In order to mitigate abrupt changes to the average, the values
at each end of the average buffer can be weighted less with a window function
(the same window function used at the start of this step!). It can be disabled
with 'setavgwindow'.
*/
#request uniform "audio_l" audio_l
#request transform audio_l "window"

37
shaders/graph/2.frag Normal file
View File

@@ -0,0 +1,37 @@
layout(pixel_center_integer) in vec4 gl_FragCoord;
#request uniform "prev" tex
uniform sampler2D tex; /* screen texture */
#request uniform "screen" screen
uniform ivec2 screen; /* screen dimensions */
out vec4 fragment; /* output */
#define OUTLINE vec4(0.15, 0.15, 0.15, 1)
void main() {
fragment = texture(tex, vec2(gl_FragCoord.x / screen.x, gl_FragCoord.y / screen.y));
vec4
a0 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)),
a1 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 1) / screen.y)),
a2 = texture(tex, vec2((gl_FragCoord.x + 0) / screen.x, (gl_FragCoord.y + 1) / screen.y)),
a3 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)),
a4 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y)),
a5 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 1) / screen.y)),
a6 = texture(tex, vec2((gl_FragCoord.x - 0) / screen.x, (gl_FragCoord.y - 1) / screen.y)),
a7 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y));
vec4 avg = (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7) / 8.0;
if (avg.a > 0){
if (fragment.a <= 0) {
/* outline */
fragment = OUTLINE;
} else if (avg.a < 1 && gl_FragCoord.y != 0) {
/* creates a nice 'glint' along the edge of the spectrum */
fragment.rgb *= avg.a * 2;
}
}
}

View File

@@ -1,28 +0,0 @@
layout(pixel_center_integer) in vec4 gl_FragCoord;
#request uniform "prev" tex
uniform sampler2D tex; /* screen texture */
#request uniform "screen" screen
uniform ivec2 screen; /* screen dimensions */
out vec4 fragment; /* output */
void main() {
fragment = texture(tex, vec2(gl_FragCoord.x / screen.x, gl_FragCoord.y / screen.y));
float a0 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)).a;
float a1 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 1) / screen.y)).a;
float a2 = texture(tex, vec2((gl_FragCoord.x + 0) / screen.x, (gl_FragCoord.y + 1) / screen.y)).a;
float a3 = texture(tex, vec2((gl_FragCoord.x + 1) / screen.x, (gl_FragCoord.y + 0) / screen.y)).a;
float a4 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y)).a;
float a5 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 1) / screen.y)).a;
float a6 = texture(tex, vec2((gl_FragCoord.x - 0) / screen.x, (gl_FragCoord.y - 1) / screen.y)).a;
float a7 = texture(tex, vec2((gl_FragCoord.x - 1) / screen.x, (gl_FragCoord.y - 0) / screen.y)).a;
float avg = (a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7) / 8.0;
if (gl_FragCoord.y > 1) {
fragment *= avg;
}
}

View File

@@ -33,7 +33,12 @@
simple set to zero (or lower) to disable the frame limiter. */
#request setframerate 0
/* Enable/disable printing framerate every second */
/* Enable/disable printing framerate every second. 'FPS' stands
for 'Frames Per Second', and 'UPS' stands for 'Updates Per
Second'. Updates are performed when new data is submitted
by pulseaudio, and require transformations to be re-applied
(thus being a good measure of how much work your CPU has to
perform over time) */
#request setprintframes true
/* Audio buffer size to be used for processing and shaders.