diff --git a/res/text.f.glsl b/res/text.f.glsl index dd60333c..5915960f 100644 --- a/res/text.f.glsl +++ b/res/text.f.glsl @@ -14,7 +14,7 @@ #version 330 core in vec2 TexCoords; in vec3 fg; -in vec3 bg; +in vec4 bg; flat in float vb; flat in int background; @@ -27,8 +27,11 @@ uniform sampler2D mask; void main() { if (background != 0) { + if (bg.a == 0.0) + discard; + alphaMask = vec4(1.0); - color = vec4(bg + vb, 1.0) * bgOpacity; + color = vec4(bg.rgb + vb, 1.0); } else { vec3 textColor = texture(mask, TexCoords).rgb; alphaMask = vec4(textColor, textColor.r); diff --git a/res/text.v.glsl b/res/text.v.glsl index 081ca6b9..9580c71f 100644 --- a/res/text.v.glsl +++ b/res/text.v.glsl @@ -26,11 +26,11 @@ layout (location = 3) in vec4 uv; // text fg color layout (location = 4) in vec3 textColor; // Background color -layout (location = 5) in vec3 backgroundColor; +layout (location = 5) in vec4 backgroundColor; out vec2 TexCoords; out vec3 fg; -out vec3 bg; +out vec4 bg; // Terminal properties uniform vec2 termDim; @@ -63,7 +63,6 @@ void main() gl_Position = projection * vec4(finalPosition.xy, 0.0, 1.0); TexCoords = vec2(0, 0); } else { - // Glyphs are offset within their cell; account for y-flip vec2 cellOffset = vec2(glyphOffset.x, glyphOffset.y - glyphSize.y); @@ -76,6 +75,6 @@ void main() vb = visualBell; background = backgroundPass; - bg = backgroundColor / vec3(255.0, 255.0, 255.0); + bg = vec4(backgroundColor.rgb / 255.0, backgroundColor.a); fg = textColor / vec3(255.0, 255.0, 255.0); } diff --git a/scripts/fg-bg.sh b/scripts/fg-bg.sh new file mode 100755 index 00000000..f1ad4d0c --- /dev/null +++ b/scripts/fg-bg.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +printf "Fg=Black, Bg=Background \e[30;49mTEST\e[m\n" +printf "Fg=Black, Bg=Black \e[30;40mTEST\e[m\n" +printf "Fg=Foreground,Bg=Background \e[39;49mTEST\e[m\n" +printf "Fg=Foreground,Bg=Black \e[39;40mTEST\e[m\n" +printf "Fg=Foreground,Bg=White \e[39;47mTEST\e[m\n" +printf "Fg=White, Bg=Foreground \e[37;39mTEST\e[m\n" +printf "Fg=Black, Bg=Background, Inverse \e[7;30;49mTEST\e[m\n" +printf "Fg=Black, Bg=Black, Inverse \e[7;30;40mTEST\e[m\n" +printf "Fg=Foreground,Bg=Background, Inverse \e[7;39;49mTEST\e[m\n" +printf "Fg=Foreground,Bg=Black, Inverse \e[7;39;40mTEST\e[m\n" +printf "Fg=Foreground,Bg=White, Inverse \e[7;39;47mTEST\e[m\n" +printf "Fg=White, Bg=Foreground, Inverse \e[7;37;39mTEST\e[m\n" diff --git a/src/config.rs b/src/config.rs index 7980992c..858d9a46 100644 --- a/src/config.rs +++ b/src/config.rs @@ -186,6 +186,7 @@ impl Alpha { self.0 = Self::clamp_to_valid_range(value); } + #[inline(always)] pub fn get(&self) -> f32 { self.0 } @@ -1093,6 +1094,7 @@ impl Config { &self.colors } + #[inline] pub fn background_opacity(&self) -> Alpha { self.background_opacity } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 3db9ccb6..9305e135 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -125,8 +125,6 @@ pub struct ShaderProgram { padding_x: f32, padding_y: f32, - - u_bg_opacity: GLint, } @@ -351,6 +349,7 @@ struct InstanceData { bg_r: f32, bg_g: f32, bg_b: f32, + bg_a: f32, } #[derive(Debug)] @@ -436,6 +435,7 @@ impl Batch { bg_r: cell.bg.r as f32, bg_g: cell.bg.g as f32, bg_b: cell.bg.b as f32, + bg_a: cell.bg_alpha, }); } @@ -568,7 +568,7 @@ impl QuadRenderer { gl::EnableVertexAttribArray(4); gl::VertexAttribDivisor(4, 1); // color - gl::VertexAttribPointer(5, 3, + gl::VertexAttribPointer(5, 4, gl::FLOAT, gl::FALSE, size_of::() as i32, (13 * size_of::()) as *const _); @@ -648,7 +648,6 @@ impl QuadRenderer { self.program.activate(); self.program.set_term_uniforms(props); self.program.set_visual_bell(visual_bell_intensity as _); - self.program.set_bg_opacity(config.background_opacity().get()); gl::BindVertexArray(self.vao); gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo); @@ -692,17 +691,22 @@ impl QuadRenderer { } pub fn reload_shaders(&mut self, config: &Config, size: Size>) { - info!("Reloading shaders"); + warn!("Reloading shaders ..."); let program = match ShaderProgram::new(config, size) { - Ok(program) => program, + Ok(program) => { + warn!(" ... OK"); + program + }, Err(err) => { match err { ShaderCreationError::Io(err) => { error!("Error reading shader file: {}", err); }, ShaderCreationError::Compile(path, log) => { - error!("Error compiling shader at {:?}", path); - let _ = io::copy(&mut log.as_bytes(), &mut io::stdout()); + error!("Error compiling shader at {:?}\n{}", path, log); + } + ShaderCreationError::Link(log) => { + error!("Error reloading shaders: {}", log); } } @@ -791,6 +795,7 @@ impl<'a> RenderApi<'a> { bg: color, fg: Rgb { r: 0, g: 0, b: 0 }, flags: cell::Flags::empty(), + bg_alpha: 1.0 }) .collect::>(); @@ -957,7 +962,7 @@ impl ShaderProgram { gl::FRAGMENT_SHADER, frag_source )?; - let program = ShaderProgram::create_program(vertex_shader, fragment_shader); + let program = ShaderProgram::create_program(vertex_shader, fragment_shader)?; unsafe { gl::DeleteShader(vertex_shader); @@ -980,14 +985,13 @@ impl ShaderProgram { } // get uniform locations - let (projection, term_dim, cell_dim, visual_bell, background, bg_opacity) = unsafe { + let (projection, term_dim, cell_dim, visual_bell, background) = unsafe { ( gl::GetUniformLocation(program, cptr!(b"projection\0")), gl::GetUniformLocation(program, cptr!(b"termDim\0")), gl::GetUniformLocation(program, cptr!(b"cellDim\0")), gl::GetUniformLocation(program, cptr!(b"visualBell\0")), gl::GetUniformLocation(program, cptr!(b"backgroundPass\0")), - gl::GetUniformLocation(program, cptr!(b"bgOpacity\0")), ) }; @@ -1002,7 +1006,6 @@ impl ShaderProgram { u_background: background, padding_x: config.padding().x.floor(), padding_y: config.padding().y.floor(), - u_bg_opacity: bg_opacity, }; shader.update_projection(*size.width as f32, *size.height as f32); @@ -1063,13 +1066,7 @@ impl ShaderProgram { } } - fn set_bg_opacity(&self, bg_opacity: f32) { - unsafe { - gl::Uniform1f(self.u_bg_opacity, bg_opacity); - } - } - - fn create_program(vertex: GLuint, fragment: GLuint) -> GLuint { + fn create_program(vertex: GLuint, fragment: GLuint) -> Result { unsafe { let program = gl::CreateProgram(); gl::AttachShader(program, vertex); @@ -1080,10 +1077,10 @@ impl ShaderProgram { gl::GetProgramiv(program, gl::LINK_STATUS, &mut success); if success != (gl::TRUE as GLint) { - error!("{}", get_program_info_log(program)); - panic!("failed to link shader program"); + Err(ShaderCreationError::Link(get_program_info_log(program))) + } else { + Ok(program) } - program } } @@ -1198,13 +1195,16 @@ pub enum ShaderCreationError { /// Error compiling shader Compile(PathBuf, String), + + /// Problem linking + Link(String), } impl ::std::error::Error for ShaderCreationError { fn cause(&self) -> Option<&::std::error::Error> { match *self { ShaderCreationError::Io(ref err) => Some(err), - ShaderCreationError::Compile(_, _) => None, + _ => None, } } @@ -1212,6 +1212,7 @@ impl ::std::error::Error for ShaderCreationError { match *self { ShaderCreationError::Io(ref err) => err.description(), ShaderCreationError::Compile(ref _path, ref s) => s.as_str(), + ShaderCreationError::Link(ref s) => s.as_str(), } } } @@ -1223,6 +1224,9 @@ impl ::std::fmt::Display for ShaderCreationError { ShaderCreationError::Compile(ref _path, ref s) => { write!(f, "failed compiling shader: {}", s) }, + ShaderCreationError::Link(ref s) => { + write!(f, "failed linking shader: {}", s) + }, } } } diff --git a/src/term/mod.rs b/src/term/mod.rs index a16971b5..97460421 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -299,6 +299,14 @@ impl<'a> RenderableCellsIter<'a> { } } + #[inline] + fn compute_bg_alpha(&self, bg: &Color) -> f32 { + match *bg { + Color::Named(NamedColor::Background) => 0.0, + _ => 1.0 + } + } + fn compute_bg_rgb(&self, bg: &Color) -> Rgb { match *bg { Color::Spec(rgb) => rgb, @@ -314,6 +322,7 @@ pub struct RenderableCell { pub c: char, pub fg: Rgb, pub bg: Rgb, + pub bg_alpha: f32, pub flags: cell::Flags, } @@ -363,19 +372,35 @@ impl<'a> Iterator for RenderableCellsIter<'a> { }; // Apply inversion and lookup RGB values - let (fg, bg) = if selected || cell.inverse() { - (self.compute_bg_rgb(&cell.bg), self.compute_fg_rgb(&cell.fg, &cell)) + let mut bg_alpha = 1.0; + let fg_rgb; + let bg_rgb; + + let invert = selected ^ cell.inverse(); + + if invert { + if cell.fg == cell.bg { + bg_rgb = self.colors[NamedColor::Foreground]; + fg_rgb = self.colors[NamedColor::Background]; + bg_alpha = 1.0 + } else { + bg_rgb = self.compute_fg_rgb(&cell.fg, &cell); + fg_rgb = self.compute_bg_rgb(&cell.bg); + } } else { - (self.compute_fg_rgb(&cell.fg, &cell), self.compute_bg_rgb(&cell.bg)) - }; + fg_rgb = self.compute_fg_rgb(&cell.fg, &cell); + bg_rgb = self.compute_bg_rgb(&cell.bg); + bg_alpha = self.compute_bg_alpha(&cell.bg); + } return Some(RenderableCell { line: line, column: column, flags: cell.flags, c: cell.c, - fg: fg, - bg: bg, + fg: fg_rgb, + bg: bg_rgb, + bg_alpha: bg_alpha, }) } @@ -976,7 +1001,7 @@ impl Term { self.mode, config, selection, - self.cursor_style + self.cursor_style, ) }