diff --git a/output/sdl_glsl.c b/output/sdl_glsl.c index 72697662..43c173c9 100644 --- a/output/sdl_glsl.c +++ b/output/sdl_glsl.c @@ -1,9 +1,3 @@ -#define GL_GLEXT_PROTOTYPES 0 -#ifdef _WIN32 -#include -#else -#include -#endif #include "sdl_glsl.h" #include @@ -21,8 +15,10 @@ GLint uniform_previous_bars; GLint uniform_bars_count; GLint uniform_time; GLint uniform_input_texture; +GLint uniform_gradient_texture; GLuint fbo; GLuint texture; +GLuint gradient_texture; uint64_t start_counter; double perf_freq; @@ -180,6 +176,59 @@ void init_sdl_glsl_window(int width, int height, int x, int y, int full_screen, } } +GLuint create_gradient_texture(int gradient_count, char **gradient_color_strings) { + if (gradient_count <= 0) { + return 0; + } + + int texture_width = 256; + float *texture_data = malloc(texture_width * 3 * sizeof(float)); + + struct colors color = {0}; + float t, segment_pos, blend, r1, g1, b1, r2, g2, b2; + int lower_idx, upper_idx; + + for (int i = 0; i < texture_width; i++) { + t = (float)i / (texture_width - 1); + segment_pos = t * (gradient_count - 1); + lower_idx = (int)segment_pos; + upper_idx = lower_idx + 1; + blend = segment_pos - lower_idx; + + // clamp + if (upper_idx >= gradient_count) { + upper_idx = gradient_count - 1; + } + + // reparse + parse_color(gradient_color_strings[lower_idx], &color); + r1 = (float)color.R / 255.0; + g1 = (float)color.G / 255.0; + b1 = (float)color.B / 255.0; + + parse_color(gradient_color_strings[upper_idx], &color); + r2 = (float)color.R / 255.0; + g2 = (float)color.G / 255.0; + b2 = (float)color.B / 255.0; + + // interpolate colours + texture_data[i * 3 + 0] = r1 * (1.0f - blend) + r2 * blend; + texture_data[i * 3 + 1] = g1 * (1.0f - blend) + g2 * blend; + texture_data[i * 3 + 2] = b1 * (1.0f - blend) + b2 * blend; + } + + GLuint tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_1D, tex); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, texture_width, 0, GL_RGB, GL_FLOAT, texture_data); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + free(texture_data); + return tex; +} + void init_sdl_glsl_surface(int *w, int *h, char *const fg_color_string, char *const bg_color_string, int bar_width, int bar_spacing, int gradient, int gradient_count, char **gradient_color_strings) { @@ -216,16 +265,20 @@ void init_sdl_glsl_surface(int *w, int *h, char *const fg_color_string, char *co gradient_count = 0; glUniform1i(uniform_gradient_count, gradient_count); - GLint uniform_gradient_colors; - uniform_gradient_colors = glGetUniformLocation(shading_program, "gradient_colors"); - float gradient_colors[8][3] = {0}; - for (int i = 0; i < gradient_count; i++) { - parse_color(gradient_color_strings[i], &color); - gradient_colors[i][0] = (float)color.R / 255.0; - gradient_colors[i][1] = (float)color.G / 255.0; - gradient_colors[i][2] = (float)color.B / 255.0; + // generate texture + if (gradient_count > 0) { + if (gradient_texture != 0) { + glDeleteTextures(1, &gradient_texture); + } + gradient_texture = create_gradient_texture(gradient_count, gradient_color_strings); + + uniform_gradient_texture = glGetUniformLocation(shading_program, "gradient_texture"); + if (uniform_gradient_texture != -1) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_1D, gradient_texture); + glUniform1i(uniform_gradient_texture, 1); + } } - glUniform3fv(uniform_gradient_colors, 8, (const GLfloat *)gradient_colors); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL); @@ -296,6 +349,10 @@ int draw_sdl_glsl(int bars_count, const float bars[], const float previous_bars[ // general: cleanup void cleanup_sdl_glsl(void) { + if (gradient_texture != 0) { + glDeleteTextures(1, &gradient_texture); + gradient_texture = 0; + } if (fbo != 0) { glDeleteFramebuffers(1, &fbo); fbo = 0; diff --git a/output/sdl_glsl.h b/output/sdl_glsl.h index c676383e..f4bdd6af 100644 --- a/output/sdl_glsl.h +++ b/output/sdl_glsl.h @@ -1,7 +1,15 @@ +#define GL_GLEXT_PROTOTYPES 0 +#ifdef _WIN32 +#include +#else +#include +#endif + #include "../config.h" void init_sdl_glsl_window(int width, int height, int x, int y, int full_screen, char *const vertex_shader, char *const fragment_shader); +GLuint create_gradient_texture(int gradient_count, char **gradient_color_strings); void init_sdl_glsl_surface(int *width, int *height, char *const fg_color_string, char *const bg_color_string, int bar_width, int bar_spacing, int gradient, int gradient_count, char **gradient_color_strings); diff --git a/output/shaders/bar_spectrum.frag b/output/shaders/bar_spectrum.frag index 473301cd..c2aaf7cd 100644 --- a/output/shaders/bar_spectrum.frag +++ b/output/shaders/bar_spectrum.frag @@ -17,7 +17,7 @@ uniform vec3 bg_color; // background color uniform vec3 fg_color; // foreground color uniform int gradient_count; -uniform vec3 gradient_colors[8]; // gradient colors +uniform sampler1D gradientTexture; // gradient colors uniform float shader_time; // shader execution time s (not used here) @@ -54,17 +54,11 @@ void main() { if (gradient_count == 0) { fragColor = vec4(fg_color, 1.0); } else { - // find which color in the configured gradient we are at - int color = int((gradient_count - 1) * fragCoord.y); - - // find where on y this and next color is supposed to be - float y_min = color / (gradient_count - 1.0); - float y_max = (color + 1.0) / (gradient_count - 1.0); + // sample the texture for which color in the configured gradient + vec3 color = texture(gradientTexture, fragCoord.y).rgb; // make color - fragColor = vec4(normalize_C(fragCoord.y, gradient_colors[color], - gradient_colors[color + 1], y_min, y_max), - 1.0); + fragColor = vec4(color, 1.0); } } } else {