Simplify and document the operation of the cell fragment shader
Also get rid of the unneccessary double bg_alpha followed by divide by alpha step when rendering interleaved and premult
This commit is contained in:
parent
ae9df1ffac
commit
a5aca35f1c
@ -7,5 +7,5 @@ out vec4 color;
|
||||
|
||||
void main() {
|
||||
color = texture(image, texcoord);
|
||||
color = vec4(color.rgb / color.a, color.a);
|
||||
color = vec4(color.rgb, color.a);
|
||||
}
|
||||
|
||||
@ -51,10 +51,45 @@ vec4 alpha_blend_premul(vec3 over, float over_alpha, vec3 under, float under_alp
|
||||
float alpha = mix(under_alpha, 1.0f, over_alpha);
|
||||
return vec4(premul_blend(over, over_alpha, under), alpha);
|
||||
}
|
||||
|
||||
vec4 blend_onto_opaque_premul(vec3 over, float over_alpha, vec3 under) {
|
||||
// same as alpha_blend_premul with under_alpha = 1 outputs a blended color
|
||||
// with alpha 1 which is effectively pre-multiplied since alpha is 1
|
||||
return vec4(premul_blend(over, over_alpha, under), 1.0);
|
||||
}
|
||||
|
||||
|
||||
// }}}
|
||||
|
||||
|
||||
/*
|
||||
* Explanation of rendering:
|
||||
* There are a couple of cases, in order of increasing complexity:
|
||||
* 1) Simple -- this path is used when there are either no images, or all images are
|
||||
* drawn on top of text and the background is opaque. In this case, there is a single pass,
|
||||
* of this shader with cell foreground and background colors blended directly.
|
||||
* Expected output is a color premultiplied by alpha, with an alpha specified as well.
|
||||
*
|
||||
* 2) Interleaved -- this path is used if background is not opaque and there are images or
|
||||
* if the background is opaque but there are images under text. Rendering happens in
|
||||
* multiple passes drawing the background and foreground separately and blending.
|
||||
*
|
||||
* 2a) Opaque bg with images under text
|
||||
* There are multiple passes, each pass is blended onto the previous using the opaque blend func (alpha, 1- alpha):
|
||||
* 1) Draw only the background -- expected output is color with alpha 1
|
||||
* 2) Draw the images that are supposed to be below text. This happens in the graphics shader
|
||||
* 3) Draw the special cells (selection/cursor). Output is same as from step 1, with bg_alpha 1 for special cells and 0 otherwise
|
||||
* 4) Draw the foreground -- expected output is color with alpha which is blended using the opaque blend func
|
||||
* 5) Draw the images that are supposed to be above text again in the graphics shader
|
||||
*
|
||||
* 2b) Transparent bg with images
|
||||
* First everything is rendered into a framebuffer, and then the framebauffer is blended onto
|
||||
* the screen. The framebuffer is needed because it allows access to the background color pixels
|
||||
* to blend with the image pixels. The steps are basically the same as for 2a.
|
||||
*/
|
||||
#ifdef NEEDS_FOREGROUND
|
||||
vec4 calculate_foreground() {
|
||||
// returns the effective foreground color in pre-multiplied form
|
||||
vec4 text_fg = texture(sprites, sprite_pos);
|
||||
vec3 fg = mix(foreground, text_fg.rgb, colored_sprite);
|
||||
float text_alpha = text_fg.a;
|
||||
@ -70,15 +105,12 @@ vec4 calculate_foreground() {
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#ifdef BACKGROUND
|
||||
#ifdef SIMPLE
|
||||
vec4 fg = calculate_foreground();
|
||||
#ifdef TRANSPARENT
|
||||
// bg_alpha is doubled to match rendering in the SIMPLE case
|
||||
// and also rendering of the margin/padding, see https://github.com/kovidgoyal/kitty/pull/1291
|
||||
// to test use background_opacity, window_margin_width and icat to display
|
||||
// an image.
|
||||
final_color = vec4(background.rgb * bg_alpha * bg_alpha, bg_alpha);
|
||||
final_color = alpha_blend_premul(fg.rgb, fg.a, background.rgb * bg_alpha, bg_alpha);
|
||||
#else
|
||||
final_color = vec4(background.rgb, 1.0f);
|
||||
final_color = blend_onto_opaque_premul(fg.rgb, fg.a, background.rgb);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -90,29 +122,22 @@ void main() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(FOREGROUND) || defined(SIMPLE)
|
||||
// FOREGROUND or SIMPLE
|
||||
vec4 fg = calculate_foreground(); // pre-multiplied foreground
|
||||
#ifdef BACKGROUND
|
||||
#ifdef TRANSPARENT
|
||||
final_color = vec4(background.rgb * bg_alpha, bg_alpha);
|
||||
#else
|
||||
final_color = vec4(background.rgb, 1.0f);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FOREGROUND
|
||||
// FOREGROUND
|
||||
vec4 fg = calculate_foreground(); // pre-multiplied 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);
|
||||
#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);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -438,7 +438,7 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen
|
||||
glDisable(GL_BLEND);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
// Now render the framebuffer to the screen reversing alpha pre-multiplication
|
||||
// Now render the framebuffer to the screen
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
bind_program(BLIT_PROGRAM); bind_vertex_array(blit_vertex_array);
|
||||
static bool blit_constants_set = false;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user