115 lines
3.3 KiB
GLSL
115 lines
3.3 KiB
GLSL
#version GLSL_VERSION
|
|
#define WHICH_PROGRAM
|
|
#define NOT_TRANSPARENT
|
|
|
|
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
|
|
#define NEEDS_BACKROUND
|
|
#endif
|
|
|
|
#if defined(SIMPLE) || defined(FOREGROUND)
|
|
#define NEEDS_FOREGROUND
|
|
#endif
|
|
|
|
#ifdef NEEDS_BACKROUND
|
|
in vec3 background;
|
|
#if defined(TRANSPARENT) || defined(SPECIAL)
|
|
in float bg_alpha;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef NEEDS_FOREGROUND
|
|
uniform sampler2DArray sprites;
|
|
in float effective_text_alpha;
|
|
in vec3 sprite_pos;
|
|
in vec3 underline_pos;
|
|
in vec3 cursor_pos;
|
|
in vec3 strike_pos;
|
|
in vec3 foreground;
|
|
in vec4 cursor_color_vec;
|
|
in vec3 decoration_fg;
|
|
in float colored_sprite;
|
|
#endif
|
|
|
|
out vec4 final_color;
|
|
|
|
// Util functions {{{
|
|
vec4 alpha_blend(vec3 over, float over_alpha, vec3 under, float under_alpha) {
|
|
// Alpha blend two colors returning the resulting color pre-multiplied by its alpha
|
|
// and its alpha.
|
|
// See https://en.wikipedia.org/wiki/Alpha_compositing
|
|
float alpha = mix(under_alpha, 1.0f, over_alpha);
|
|
vec3 combined_color = mix(under * under_alpha, over, over_alpha);
|
|
return vec4(combined_color, alpha);
|
|
}
|
|
|
|
vec3 premul_blend(vec3 over, float over_alpha, vec3 under) {
|
|
return over + (1.0f - over_alpha) * under;
|
|
}
|
|
|
|
vec4 alpha_blend_premul(vec3 over, float over_alpha, vec3 under, float under_alpha) {
|
|
// Same as alpha_blend() except that it assumes over and under are both premultiplied.
|
|
float alpha = mix(under_alpha, 1.0f, over_alpha);
|
|
return vec4(premul_blend(over, over_alpha, under), alpha);
|
|
}
|
|
// }}}
|
|
|
|
#ifdef NEEDS_FOREGROUND
|
|
vec4 calculate_foreground() {
|
|
vec4 text_fg = texture(sprites, sprite_pos);
|
|
vec3 fg = mix(foreground, text_fg.rgb, colored_sprite);
|
|
float text_alpha = text_fg.a;
|
|
float underline_alpha = texture(sprites, underline_pos).a;
|
|
float strike_alpha = texture(sprites, strike_pos).a;
|
|
float cursor_alpha = texture(sprites, cursor_pos).a;
|
|
// Since strike and text are the same color, we simply add the alpha values
|
|
float combined_alpha = min(text_alpha + strike_alpha, 1.0f);
|
|
// Underline color might be different, so alpha blend
|
|
vec4 ans = alpha_blend(fg, combined_alpha * effective_text_alpha, decoration_fg, underline_alpha * effective_text_alpha);
|
|
return mix(ans, cursor_color_vec, cursor_alpha);
|
|
}
|
|
#endif
|
|
|
|
void main() {
|
|
#ifdef BACKGROUND
|
|
#ifdef TRANSPARENT
|
|
final_color = vec4(background.rgb * bg_alpha, bg_alpha);
|
|
#else
|
|
final_color = vec4(background.rgb, 1.0f);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef SPECIAL
|
|
#ifdef TRANSPARENT
|
|
final_color = vec4(background.rgb * bg_alpha, bg_alpha);
|
|
#else
|
|
final_color = vec4(background.rgb, bg_alpha);
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(FOREGROUND) || defined(SIMPLE)
|
|
// FOREGROUND or SIMPLE
|
|
vec4 fg = calculate_foreground(); // pre-multiplied foreground
|
|
|
|
#ifdef FOREGROUND
|
|
// FOREGROUND
|
|
#ifdef TRANSPARENT
|
|
final_color = fg;
|
|
#else
|
|
final_color = vec4(fg.rgb / fg.a, fg.a);
|
|
#endif
|
|
|
|
#else
|
|
// SIMPLE
|
|
#ifdef TRANSPARENT
|
|
final_color = alpha_blend_premul(fg.rgb, fg.a, background * bg_alpha, bg_alpha);
|
|
final_color = vec4(final_color.rgb / final_color.a, final_color.a);
|
|
#else
|
|
// since background alpha is 1.0, it is effectively pre-multiplied
|
|
final_color = vec4(premul_blend(fg.rgb, fg.a, background), 1.0f);
|
|
final_color = vec4(final_color.rgb / final_color.a, final_color.a);
|
|
#endif
|
|
#endif
|
|
|
|
#endif
|
|
}
|