frag_render.glsl (2684B)
1 #version 430 core 2 3 layout(location = 0) in vec2 fragment_texture_coordinate; 4 layout(location = 1) in vec4 fragment_colour; 5 6 layout(location = 0) out vec4 colour; 7 8 struct RenderCell { 9 uint gpu_glyph; 10 uint fg; 11 uint bg; 12 }; 13 14 layout(std430, binding = 0) readonly restrict buffer ssbo_cells { 15 RenderCell cells[]; 16 }; 17 18 layout(std140, binding = 0) uniform parameters { 19 ivec2 cell_size; 20 ivec2 term_size_in_cells; 21 ivec2 term_size_in_pixels; 22 ivec2 top_left_margin; 23 uint margin_colour; 24 float blink_parameter; 25 26 float strike_min; 27 float strike_max; 28 29 float underline_min; 30 float underline_max; 31 32 uint reverse_video_mask; 33 }; 34 35 layout(location = 3) uniform sampler2D u_bitmap_texture; 36 37 #define ATTR_MASK 0xFFu 38 #define ATTR_FAINT (1u << 0u) 39 #define ATTR_UNDERLINED (1u << 1u) 40 #define ATTR_BLINK (1u << 2u) 41 #define ATTR_INVERSE (1u << 3u) 42 #define ATTR_INVISIBLE (1u << 4u) 43 #define ATTR_STRUCK (1u << 5u) 44 45 ivec2 46 unpack_glyph_position(uint glyph_position) 47 { 48 ivec2 result; 49 result.x = int(glyph_position & 0xFFFFu); 50 result.y = int(glyph_position >> 16u); 51 return result; 52 } 53 54 void main() 55 { 56 ivec2 pixel_coord = ivec2(gl_FragCoord.xy) - top_left_margin; 57 58 ivec2 cell_index = pixel_coord / cell_size; 59 ivec2 cell_pos = pixel_coord % cell_size; 60 61 vec3 result; 62 if (pixel_coord.x > 0 && cell_index.x < term_size_in_cells.x && 63 pixel_coord.y > 0 && cell_index.y < term_size_in_cells.y) 64 { 65 RenderCell cell = cells[term_size_in_cells.x * cell_index.y + cell_index.x]; 66 67 uint attr = cell.fg & ATTR_MASK; 68 vec3 fg = unpackUnorm4x8(cell.fg ^ reverse_video_mask).wzy; 69 vec3 bg = unpackUnorm4x8(cell.bg ^ reverse_video_mask).wzy; 70 71 if ((attr & ATTR_FAINT) != 0) fg *= 0.5; 72 if ((attr & ATTR_BLINK) != 0) fg = mix(bg, fg, 0.5 * (1 + sin(blink_parameter))); 73 74 if ((attr & ATTR_INVERSE) != 0) { 75 vec3 tmp = fg; 76 fg = bg; 77 bg = tmp; 78 } 79 80 ivec2 glyph_pos = unpack_glyph_position(cell.gpu_glyph) * cell_size; 81 vec4 smp = texelFetch(u_bitmap_texture, glyph_pos + cell_pos, 0); 82 result = mix(bg, fg * smp.xyz, smp.a); 83 84 if (((attr & ATTR_UNDERLINED) != 0) && 85 cell_pos.y >= underline_min && cell_pos.y < underline_max) 86 result = fg; 87 88 if (((attr & ATTR_STRUCK) != 0) && 89 cell_pos.y >= strike_min && cell_pos.y < strike_max) 90 result = fg; 91 } else { 92 result = unpackUnorm4x8(margin_colour ^ reverse_video_mask).wzy; 93 } 94 95 /* NOTE: set to true to see the glyph cache texture */ 96 if (false) { 97 /* NOTE: needs to use texture() since the cache texture 98 * may be different size than the window size */ 99 vec4 smp = texture(u_bitmap_texture, gl_FragCoord.xy / vec2(term_size_in_pixels)); 100 colour = smp; 101 } else { 102 colour = vec4(result, 1); 103 } 104 }