From 140d98b4043bac88ca152d6d2f4ba73f48c865d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20M=C3=BCller?= Date: Wed, 30 Jan 2019 15:38:23 +0100 Subject: [PATCH 1/6] Join middle borders instead of clamping them down --- shaders/graph/1.frag | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/shaders/graph/1.frag b/shaders/graph/1.frag index b6d3da3..afdf2c4 100644 --- a/shaders/graph/1.frag +++ b/shaders/graph/1.frag @@ -81,16 +81,27 @@ out vec4 fragment; #define TWOPI 6.28318530718 float half_w; +float middle; +highp float pixel = 1.0F / float(screen.x); -void render_side(in sampler1D tex, float idx) { - highp float pixel = 1.0F / float(screen.x); +float get_line_height(in sampler1D tex, float idx) { float s = smooth_audio_adj(tex, audio_sz, idx / half_w, pixel); /* scale the data upwards so we can see it */ s *= VSCALE; /* clamp far ends of the screen down to make the ends of the graph smoother */ - s *= clamp((abs((screen.x / 2) - gl_FragCoord.x) / screen.x) * 48, 0.0F, 1.0F); + + float fact = clamp((abs((screen.x / 2) - gl_FragCoord.x) / screen.x) * 48, 0.0F, 1.0F); + fact = pow(fact, 1.8); /* To avoid spikes */ + s = fact * s + (1 - fact) * middle; + s *= clamp((min(gl_FragCoord.x, screen.x - gl_FragCoord.x) / screen.x) * 48, 0.0F, 1.0F); + return s; +} + +void render_side(in sampler1D tex, float idx) { + float s = get_line_height(tex, idx); + /* and finally set fragment color if we are in range */ #if INVERT > 0 float pos = float(screen.y) - gl_FragCoord.y; @@ -106,6 +117,9 @@ void render_side(in sampler1D tex, float idx) { void main() { half_w = (screen.x / 2); + + middle = VSCALE * (smooth_audio_adj(audio_l, audio_sz, 1, pixel) + smooth_audio_adj(audio_r, audio_sz, 0, pixel)) / 2; + if (gl_FragCoord.x < half_w) { render_side(audio_l, LEFT_IDX); } else { From a39a1324e1cd3606976c65a64cf5f5022923b505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20M=C3=BCller?= Date: Wed, 30 Jan 2019 15:43:47 +0100 Subject: [PATCH 2/6] Add anti-aliasing option for graph --- shaders/graph.glsl | 7 ++++ shaders/graph/3.frag | 76 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 shaders/graph/3.frag diff --git a/shaders/graph.glsl b/shaders/graph.glsl index b2993d5..846fb89 100644 --- a/shaders/graph.glsl +++ b/shaders/graph.glsl @@ -13,6 +13,13 @@ #define DRAW_OUTLINE 0 /* 1 to draw edge highlight, 0 to disable */ #define DRAW_HIGHLIGHT 1 +/* Whether to anti-alias the border of the graph, creating a smoother curve. + This may have a small impact on performance. Note that this only anti-aliases + the border, so that the seams between the graph and the outline and/or the + highlight (if present) will not be aliased. + Note: This requires `xroot` transparency to be enabled since it + relies on alpha blending with the background. */ +#define ANTI_ALIAS 0 /* outline color */ #define OUTLINE #262626 /* 1 to invert (vertically), 0 otherwise */ diff --git a/shaders/graph/3.frag b/shaders/graph/3.frag new file mode 100644 index 0000000..2e21a19 --- /dev/null +++ b/shaders/graph/3.frag @@ -0,0 +1,76 @@ + +in vec4 gl_FragCoord; + +#request uniform "screen" screen +uniform ivec2 screen; /* screen dimensions */ + +#request uniform "prev" tex +uniform sampler2D tex; /* screen texture */ + +out vec4 fragment; /* output */ + +#include "@graph.glsl" +#include ":graph.glsl" + +float get_col_height_up(float x, float oy) { + float y = oy; + while (y < screen.y) { + vec4 f = texelFetch(tex, ivec2(x, y), 0); + if (f.a <= 0) { + y -= 1; + break; + } + y += 1; + } + + return y; +} + +float get_col_height_down(float x, float oy) { + float y = oy; + while (y >= 0) { + vec4 f = texelFetch(tex, ivec2(x, y), 0); + if (f.a > 0) { + break; + } + y -= 1; + } + + return y; +} + +void main() { + fragment = texelFetch(tex, ivec2(gl_FragCoord.x, gl_FragCoord.y), 0); + + #if ANTI_ALIAS > 0 + + if (fragment.a <= 0) { + bool left_done = false; + float h2; + float a_fact = 0; + + if (texelFetch(tex, ivec2(gl_FragCoord.x - 1, gl_FragCoord.y), 0).a > 0) { + float h1 = get_col_height_up(gl_FragCoord.x - 1, gl_FragCoord.y); + h2 = get_col_height_down(gl_FragCoord.x, gl_FragCoord.y); + fragment = texelFetch(tex, ivec2(gl_FragCoord.x, h2), 0); + + a_fact = clamp((h1 - gl_FragCoord.y) / abs(h2 - h1), 0.0, 1.0); + + left_done = true; + } + if (texelFetch(tex, ivec2(gl_FragCoord.x + 1, gl_FragCoord.y), 0).a > 0) { + if (!left_done) { + h2 = get_col_height_down(gl_FragCoord.x, gl_FragCoord.y); + fragment = texelFetch(tex, ivec2(gl_FragCoord.x, h2), 0); + } + float h3 = get_col_height_up(gl_FragCoord.x + 1, gl_FragCoord.y); + + a_fact = max(a_fact, clamp((h3 - gl_FragCoord.y) / abs(h2 - h3), 0.0, 1.0)); + } + + fragment.a *= a_fact; + + } + + #endif +} From 91530dfc492947ef2d607c0ab23e0b626d58d07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20M=C3=BCller?= Date: Wed, 30 Jan 2019 20:26:35 +0100 Subject: [PATCH 3/6] Make joining optional --- shaders/graph.glsl | 2 ++ shaders/graph/1.frag | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/shaders/graph.glsl b/shaders/graph.glsl index 846fb89..1906195 100644 --- a/shaders/graph.glsl +++ b/shaders/graph.glsl @@ -22,6 +22,8 @@ #define ANTI_ALIAS 0 /* outline color */ #define OUTLINE #262626 +/* 1 to join the two channels together in the middle, 0 to clamp both down to zero */ +#define JOIN_CHANNELS 0 /* 1 to invert (vertically), 0 otherwise */ #define INVERT 0 diff --git a/shaders/graph/1.frag b/shaders/graph/1.frag index afdf2c4..04839d8 100644 --- a/shaders/graph/1.frag +++ b/shaders/graph/1.frag @@ -91,8 +91,12 @@ float get_line_height(in sampler1D tex, float idx) { /* clamp far ends of the screen down to make the ends of the graph smoother */ float fact = clamp((abs((screen.x / 2) - gl_FragCoord.x) / screen.x) * 48, 0.0F, 1.0F); + #if JOIN_CHANNELS > 0 fact = pow(fact, 1.8); /* To avoid spikes */ s = fact * s + (1 - fact) * middle; + #else + s *= fact; + #endif s *= clamp((min(gl_FragCoord.x, screen.x - gl_FragCoord.x) / screen.x) * 48, 0.0F, 1.0F); From 8cbf7bc579e889d627e864ee3da4e2c3ed8f1955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20M=C3=BCller?= Date: Thu, 31 Jan 2019 12:05:05 +0100 Subject: [PATCH 4/6] Cubic interpolation for joining graph channels --- shaders/graph/1.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shaders/graph/1.frag b/shaders/graph/1.frag index 04839d8..9b82d05 100644 --- a/shaders/graph/1.frag +++ b/shaders/graph/1.frag @@ -92,7 +92,7 @@ float get_line_height(in sampler1D tex, float idx) { float fact = clamp((abs((screen.x / 2) - gl_FragCoord.x) / screen.x) * 48, 0.0F, 1.0F); #if JOIN_CHANNELS > 0 - fact = pow(fact, 1.8); /* To avoid spikes */ + fact = -2 * pow(fact, 3) + 3 * pow(fact, 2); /* To avoid spikes */ s = fact * s + (1 - fact) * middle; #else s *= fact; From 041bfdfd5522923fcb5edb361a93587baf36ee82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20M=C3=BCller?= Date: Fri, 1 Feb 2019 20:19:15 +0100 Subject: [PATCH 5/6] Make anti-aliasing work with invert --- shaders/graph/1.frag | 6 ++---- shaders/graph/4.frag | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 shaders/graph/4.frag diff --git a/shaders/graph/1.frag b/shaders/graph/1.frag index 9b82d05..b52423f 100644 --- a/shaders/graph/1.frag +++ b/shaders/graph/1.frag @@ -107,11 +107,9 @@ void render_side(in sampler1D tex, float idx) { float s = get_line_height(tex, idx); /* and finally set fragment color if we are in range */ - #if INVERT > 0 - float pos = float(screen.y) - gl_FragCoord.y; - #else + float pos = gl_FragCoord.y; - #endif + if (pos + 1.5 <= s) { fragment = COLOR; } else { diff --git a/shaders/graph/4.frag b/shaders/graph/4.frag new file mode 100644 index 0000000..4630153 --- /dev/null +++ b/shaders/graph/4.frag @@ -0,0 +1,22 @@ + +in vec4 gl_FragCoord; + +#request uniform "screen" screen +uniform ivec2 screen; /* screen dimensions */ + +#request uniform "prev" tex +uniform sampler2D tex; /* screen texture */ + +out vec4 fragment; /* output */ + +#include "@graph.glsl" +#include ":graph.glsl" + +void main() { + float newy = gl_FragCoord.y; + #if INVERT > 0 + newy = float(screen.y + 1) - newy; + #endif + + fragment = texelFetch(tex, ivec2(gl_FragCoord.x, newy), 0); +} From 3ff109794160cdf978125d27628963036b3bea91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Theo=20M=C3=BCller?= Date: Fri, 1 Feb 2019 22:40:46 +0100 Subject: [PATCH 6/6] Fix inverting in antialias pass --- shaders/graph/1.frag | 6 ++++-- shaders/graph/3.frag | 30 +++++++++++++++++++++++++++--- shaders/graph/4.frag | 22 ---------------------- 3 files changed, 31 insertions(+), 27 deletions(-) delete mode 100644 shaders/graph/4.frag diff --git a/shaders/graph/1.frag b/shaders/graph/1.frag index b52423f..9b82d05 100644 --- a/shaders/graph/1.frag +++ b/shaders/graph/1.frag @@ -107,9 +107,11 @@ void render_side(in sampler1D tex, float idx) { float s = get_line_height(tex, idx); /* and finally set fragment color if we are in range */ - + #if INVERT > 0 + float pos = float(screen.y) - gl_FragCoord.y; + #else float pos = gl_FragCoord.y; - + #endif if (pos + 1.5 <= s) { fragment = COLOR; } else { diff --git a/shaders/graph/3.frag b/shaders/graph/3.frag index 2e21a19..df549bc 100644 --- a/shaders/graph/3.frag +++ b/shaders/graph/3.frag @@ -12,28 +12,52 @@ out vec4 fragment; /* output */ #include "@graph.glsl" #include ":graph.glsl" +/* Moves toward the border of the graph, gives the + y coordinate of the last colored pixel */ float get_col_height_up(float x, float oy) { float y = oy; + #if INVERT > 0 + while (y >= 0) { + #else while (y < screen.y) { + #endif vec4 f = texelFetch(tex, ivec2(x, y), 0); if (f.a <= 0) { + #if INVERT > 0 + y += 1; + #else y -= 1; + #endif break; } + #if INVERT > 0 + y -= 1; + #else y += 1; + #endif } return y; } +/* Moves toward the base of the graph, gives the + y coordinate of the first colored pixel */ float get_col_height_down(float x, float oy) { float y = oy; + #if INVERT > 0 + while (y < screen.y) { + #else while (y >= 0) { + #endif vec4 f = texelFetch(tex, ivec2(x, y), 0); if (f.a > 0) { break; } + #if INVERT > 0 + y += 1; + #else y -= 1; + #endif } return y; @@ -54,7 +78,7 @@ void main() { h2 = get_col_height_down(gl_FragCoord.x, gl_FragCoord.y); fragment = texelFetch(tex, ivec2(gl_FragCoord.x, h2), 0); - a_fact = clamp((h1 - gl_FragCoord.y) / abs(h2 - h1), 0.0, 1.0); + a_fact = clamp(abs((h1 - gl_FragCoord.y) / (h2 - h1)), 0.0, 1.0); left_done = true; } @@ -65,9 +89,9 @@ void main() { } float h3 = get_col_height_up(gl_FragCoord.x + 1, gl_FragCoord.y); - a_fact = max(a_fact, clamp((h3 - gl_FragCoord.y) / abs(h2 - h3), 0.0, 1.0)); + a_fact = max(a_fact, clamp(abs((h3 - gl_FragCoord.y) / (h2 - h3)), 0.0, 1.0)); } - + fragment.a *= a_fact; } diff --git a/shaders/graph/4.frag b/shaders/graph/4.frag deleted file mode 100644 index 4630153..0000000 --- a/shaders/graph/4.frag +++ /dev/null @@ -1,22 +0,0 @@ - -in vec4 gl_FragCoord; - -#request uniform "screen" screen -uniform ivec2 screen; /* screen dimensions */ - -#request uniform "prev" tex -uniform sampler2D tex; /* screen texture */ - -out vec4 fragment; /* output */ - -#include "@graph.glsl" -#include ":graph.glsl" - -void main() { - float newy = gl_FragCoord.y; - #if INVERT > 0 - newy = float(screen.y + 1) - newy; - #endif - - fragment = texelFetch(tex, ivec2(gl_FragCoord.x, newy), 0); -}