Use shader include for fore/background shaders

The two shaders use a lot of common logic for co-ordinate and attribute
look up, so it makes sense to use a common include shader for both.

Adds support for the inverse and blink attributes to the foreground shader.
This commit is contained in:
Leroy Hopson 2024-02-07 21:37:50 +13:00
parent a849423096
commit 8b320622f9
No known key found for this signature in database
GPG key ID: D2747312A6DB51AA
5 changed files with 95 additions and 49 deletions

View file

@ -332,14 +332,21 @@ void Terminal::update_sizes(bool force)
attr_image = Image::create(std::max(cols, 1u), std::max(rows, 1u), false, Image::FORMAT_L8); attr_image = Image::create(std::max(cols, 1u), std::max(rows, 1u), false, Image::FORMAT_L8);
attr_texture->set_image(attr_image); attr_texture->set_image(attr_image);
back_material->set_shader_parameter("cols", cols); update_shader_parameters(back_material);
back_material->set_shader_parameter("rows", rows); update_shader_parameters(fore_material);
back_material->set_shader_parameter("size", size);
back_material->set_shader_parameter("cell_size", cell_size);
refresh(); refresh();
} }
void Terminal::update_shader_parameters(Ref<ShaderMaterial> material)
{
material->set_shader_parameter("cols", cols);
material->set_shader_parameter("rows", rows);
material->set_shader_parameter("size", size);
material->set_shader_parameter("cell_size", cell_size);
material->set_shader_parameter("grid_size", Vector2(cols * cell_size.x, rows * cell_size.y));
}
void Terminal::initialize_rendering() { void Terminal::initialize_rendering() {
ResourceLoader* rl = ResourceLoader::get_singleton(); ResourceLoader* rl = ResourceLoader::get_singleton();
@ -354,7 +361,7 @@ void Terminal::initialize_rendering() {
back_material.instantiate(); back_material.instantiate();
back_material->set_shader(back_shader); back_material->set_shader(back_shader);
back_material->set_shader_parameter("cell_colors", back_texture); back_material->set_shader_parameter("background_colors", back_texture);
back_material->set_shader_parameter("attributes", attr_texture); back_material->set_shader_parameter("attributes", attr_texture);
back_canvas_item = rs->canvas_item_create(); back_canvas_item = rs->canvas_item_create();
@ -404,7 +411,7 @@ void Terminal::update_theme() {
tsm_vte_color color = static_cast<tsm_vte_color>(i); tsm_vte_color color = static_cast<tsm_vte_color>(i);
palette[color] = get_theme_color(String(COLOR_NAMES[i])); palette[color] = get_theme_color(String(COLOR_NAMES[i]));
} }
back_material->set_shader_parameter("background", palette[TSM_COLOR_BACKGROUND]); back_material->set_shader_parameter("background_color", palette[TSM_COLOR_BACKGROUND]);
// TODO: Default to mono font and handle other styles. // TODO: Default to mono font and handle other styles.
font = get_theme_font("normal_font"); font = get_theme_font("normal_font");

View file

@ -97,6 +97,7 @@ namespace godot
void initialize_rendering(); void initialize_rendering();
void update_theme(); void update_theme();
void update_sizes(bool force = false); void update_sizes(bool force = false);
void update_shader_parameters(Ref<ShaderMaterial> material);
void draw_screen(); void draw_screen();
void refresh(); void refresh();
void cleanup_rendering(); void cleanup_rendering();

View file

@ -1,38 +1,5 @@
// SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
// SPDX-License-Identifier: MIT
shader_type canvas_item; shader_type canvas_item;
#define BACKGROUND
uniform int cols; #include "./common.gdshaderinc"
uniform int rows;
uniform vec2 size; // Total size of the Terminal control.
uniform vec2 cell_size;
uniform vec4 background;
uniform sampler2D cell_colors; // Texture containing the cell colors, one pixel per cell.
const int INVERSE_FLAG = 1 << 0;
// Texture containing the cell attributes encoded using bit flags, one flag per cell in the R channel.
uniform sampler2D attributes;
void fragment() {
// Grid means the part of the terminal that contains the cells.
// Will vary depending on font size and the size of the control.
vec2 grid_size = vec2(cell_size.x * float(cols), cell_size.y * float(rows));
if (UV.x * size.x < grid_size.x && UV.y * size.y < grid_size.y) {
vec2 grid_uv = UV * size / cell_size;
int cell_x = int(grid_uv.x);
int cell_y = int(grid_uv.y);
vec2 sample_uv = (vec2(float(cell_x), float(cell_y)) + 0.5) / vec2(float(cols), float(rows));
vec4 color = texture(cell_colors, sample_uv);
int attr_flags = int(texture(attributes, sample_uv).r * 255.0 + 0.5);
if ((attr_flags & INVERSE_FLAG) != 0) {
color = vec4(1.0 - color.rgb, color.a);
}
COLOR = color;
} else {
// If outside the grid area, use the background color.
COLOR = background;
}
}

View file

@ -0,0 +1,73 @@
// SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
// SPDX-License-Identifier: MIT
#define FLAG_INVERSE 1 << 0
#define FLAG_BLINK 1 << 1
#define transparent vec4(0)
uniform int cols;
uniform int rows;
uniform vec2 size;
uniform vec2 cell_size;
uniform vec2 grid_size;
uniform sampler2D attributes;
#ifdef BACKGROUND
uniform vec4 background_color;
uniform sampler2D background_colors;
#endif
#ifdef FOREGROUND
uniform float blink_off_time = 0.3;
uniform float blink_on_time = 0.6;
#endif
bool has_attribute(vec2 uv, int flag) {
int flags = int(texture(attributes, uv).r * 255.0 + 0.5);
return (flags & flag) != 0;
}
void fragment() {
// Check if we are inside the grid.
if (UV.x * size.x < grid_size.x && UV.y * size.y < grid_size.y) {
vec2 grid_uv = UV * size / cell_size;
int cell_x = int(grid_uv.x);
int cell_y = int(grid_uv.y);
vec2 sample_uv = (vec2(float(cell_x), float(cell_y)) + 0.5) / vec2(float(cols), float(rows));
vec4 color;
#ifdef BACKGROUND
color = texture(background_colors, sample_uv);
#elif defined(FOREGROUND)
color = texture(TEXTURE, UV);
#endif
if (has_attribute(sample_uv, FLAG_INVERSE)) {
color = vec4(1.0 - color.rgb, color.a);
}
#ifdef FOREGROUND
if (has_attribute(sample_uv, FLAG_BLINK)) {
float blink_cycle = blink_on_time + blink_off_time;
float current_time = mod(TIME, blink_cycle);
if (current_time > blink_on_time) {
color = transparent;
}
}
#endif
#if defined(FOREGROUND) || defined(BACKGROUND)
COLOR = color;
#endif
} else { // Outside the grid.
#ifdef BACKGROUND
COLOR = background_color;
#elif defined(FOREGROUND)
COLOR = transparent;
#endif
}
}

View file

@ -1,7 +1,5 @@
// SPDX-FileCopyrightText: 2024 Leroy Hopson <godot-xterm@leroy.nix.nz>
// SPDX-License-Identifier: MIT
shader_type canvas_item; shader_type canvas_item;
#define FOREGROUND
void fragment() { #include "./common.gdshaderinc"
COLOR = texture(TEXTURE, UV);
// TODO: Check blink attribute and hide/show using the below.
//COLOR = vec4(0);
}