vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

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 }