From 249335b146989b34d03ce26c7d6572bf48f82d53 Mon Sep 17 00:00:00 2001 From: K's Thinkpad Date: Tue, 2 Jul 2024 17:47:09 +0200 Subject: [PATCH 1/5] Added the better color averaging code (tested & functional) --- src/render_helpers/shaders/border.frag | 31 ++++++++++++++++++++++++- src/render_helpers/shaders/resize.frag | 32 +++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/render_helpers/shaders/border.frag b/src/render_helpers/shaders/border.frag index fe12103..a79835a 100644 --- a/src/render_helpers/shaders/border.frag +++ b/src/render_helpers/shaders/border.frag @@ -21,6 +21,35 @@ uniform vec2 geo_size; uniform vec4 outer_radius; uniform float border_width; + +vec4 linear_color_mix(vec4 color1, vec4 color2, float color_ratio) { + vec4 lin_color1 = vec4( + pow(color1.r, 2.0), + pow(color1.g, 2.0), + pow(color1.b, 2.0), + color1.a + ); + + vec4 lin_color2 = vec4( + pow(color2.r, 2.0), + pow(color2.g, 2.0), + pow(color2.b, 2.0), + color2.a + ); + + vec4 color_out = mix( + lin_color1, + lin_color2, + color_ratio + ); + + return vec4(sqrt(color_out.r), + sqrt(color_out.g), + sqrt(color_out.b), + color_out.a + ); +} + vec4 gradient_color(vec2 coords) { coords = coords + grad_offset; @@ -33,7 +62,7 @@ vec4 gradient_color(vec2 coords) { frac += 1.0; frac = clamp(frac, 0.0, 1.0); - return mix(color_from, color_to, frac); + return linear_color_mix(color_from, color_to, frac); } float rounding_alpha(vec2 coords, vec2 size, vec4 corner_radius) { diff --git a/src/render_helpers/shaders/resize.frag b/src/render_helpers/shaders/resize.frag index d1ed30f..94f250d 100644 --- a/src/render_helpers/shaders/resize.frag +++ b/src/render_helpers/shaders/resize.frag @@ -1,3 +1,33 @@ + +vec4 linear_color_mix(vec4 color1, vec4 color2, float color_ratio) { + vec4 lin_color1 = vec4( + pow(color1.r, 2.0), + pow(color1.g, 2.0), + pow(color1.b, 2.0), + color1.a + ); + + vec4 lin_color2 = vec4( + pow(color2.r, 2.0), + pow(color2.g, 2.0), + pow(color2.b, 2.0), + color2.a + ); + + vec4 color_out = mix( + lin_color1, + lin_color2, + color_ratio + ); + + return vec4(sqrt(color_out.r), + sqrt(color_out.g), + sqrt(color_out.b), + color_out.a + ); +} + + vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) { vec3 coords_tex_prev = niri_geo_to_tex_prev * coords_curr_geo; vec4 color_prev = texture2D(niri_tex_prev, coords_tex_prev.st); @@ -5,6 +35,6 @@ vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) { vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo; vec4 color_next = texture2D(niri_tex_next, coords_tex_next.st); - vec4 color = mix(color_prev, color_next, niri_clamped_progress); + vec4 color = linear_color_mix(color_prev, color_next, niri_clamped_progress); return color; } From 3c2f33dcd1a03eae8af059fc4589732e595dda69 Mon Sep 17 00:00:00 2001 From: K's Thinkpad Date: Thu, 4 Jul 2024 21:45:08 +0200 Subject: [PATCH 2/5] will soon have working gradient selection --- niri-config/src/lib.rs | 11 ++++ src/layout/focus_ring.rs | 12 ++++- src/layout/tile.rs | 1 + src/render_helpers/border.rs | 8 +++ src/render_helpers/shaders/border.frag | 54 +------------------ src/render_helpers/shaders/mod.rs | 16 +++++- src/render_helpers/shaders/resize.frag | 32 +---------- .../shaders/resize_prelude.frag | 1 + src/window/mapped.rs | 1 + 9 files changed, 49 insertions(+), 87 deletions(-) diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index f1bd0af..b833677 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -410,6 +410,8 @@ pub struct Gradient { pub angle: i16, #[knuffel(property, default)] pub relative_to: GradientRelativeTo, + #[knuffel(property, default)] + pub gradient_type: GradientType, } #[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)] @@ -419,6 +421,15 @@ pub enum GradientRelativeTo { WorkspaceView, } +#[derive(knuffel::DecodeScalar, Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum GradientType { + #[default] + CssLinear, + Linear, + Oklab, + Lch, +} + #[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] pub struct Border { #[knuffel(child)] diff --git a/src/layout/focus_ring.rs b/src/layout/focus_ring.rs index 97a1b75..7160362 100644 --- a/src/layout/focus_ring.rs +++ b/src/layout/focus_ring.rs @@ -1,7 +1,7 @@ use std::iter::zip; use arrayvec::ArrayVec; -use niri_config::{CornerRadius, Gradient, GradientRelativeTo}; +use niri_config::{CornerRadius, Gradient, GradientRelativeTo, GradientType}; use smithay::backend::renderer::element::Kind; use smithay::utils::{Logical, Point, Rectangle, Size}; @@ -91,6 +91,7 @@ impl FocusRing { to: color, angle: 0, relative_to: GradientRelativeTo::Window, + gradient_type: GradientType::CssLinear, }); let full_rect = Rectangle::from_loc_and_size((-width, -width), self.full_size); @@ -99,6 +100,13 @@ impl FocusRing { GradientRelativeTo::WorkspaceView => view_rect, }; + let gradient_format = match gradient.gradient_type { + GradientType::CssLinear => 0., + GradientType::Linear => 1., + GradientType::Oklab => 2., + GradientType::Lch => 3., + }; + let rounded_corner_border_width = if self.is_border { // HACK: increase the border width used for the inner rounded corners a tiny bit to // reduce background bleed. @@ -178,6 +186,7 @@ impl FocusRing { border.update( size, Rectangle::from_loc_and_size(gradient_area.loc - loc, gradient_area.size), + gradient_format, gradient.from.into(), gradient.to.into(), ((gradient.angle as f32) - 90.).to_radians(), @@ -198,6 +207,7 @@ impl FocusRing { gradient_area.loc - self.locations[0], gradient_area.size, ), + gradient_format, gradient.from.into(), gradient.to.into(), ((gradient.angle as f32) - 90.).to_radians(), diff --git a/src/layout/tile.rs b/src/layout/tile.rs index 710add8..68cb669 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -757,6 +757,7 @@ impl Tile { return BorderRenderElement::new( geo.size, Rectangle::from_loc_and_size((0., 0.), geo.size), + 0., elem.color(), elem.color(), 0., diff --git a/src/render_helpers/border.rs b/src/render_helpers/border.rs index 7e36c44..0b650f1 100644 --- a/src/render_helpers/border.rs +++ b/src/render_helpers/border.rs @@ -28,6 +28,7 @@ pub struct BorderRenderElement { struct Parameters { size: Size, gradient_area: Rectangle, + gradient_format: f32, color_from: [f32; 4], color_to: [f32; 4], angle: f32, @@ -43,6 +44,7 @@ impl BorderRenderElement { pub fn new( size: Size, gradient_area: Rectangle, + gradient_format: f32, color_from: [f32; 4], color_to: [f32; 4], angle: f32, @@ -57,6 +59,7 @@ impl BorderRenderElement { params: Parameters { size, gradient_area, + gradient_format, color_from, color_to, angle, @@ -77,6 +80,7 @@ impl BorderRenderElement { params: Parameters { size: Default::default(), gradient_area: Default::default(), + gradient_format: 0., color_from: Default::default(), color_to: Default::default(), angle: 0., @@ -97,6 +101,7 @@ impl BorderRenderElement { &mut self, size: Size, gradient_area: Rectangle, + gradient_format: f32, color_from: [f32; 4], color_to: [f32; 4], angle: f32, @@ -108,6 +113,7 @@ impl BorderRenderElement { let params = Parameters { size, gradient_area, + gradient_format, color_from, color_to, angle, @@ -128,6 +134,7 @@ impl BorderRenderElement { let Parameters { size, gradient_area, + gradient_format, color_from, color_to, angle, @@ -167,6 +174,7 @@ impl BorderRenderElement { None, scale, vec![ + Uniform::new("grad_format", gradient_format), Uniform::new("color_from", color_from), Uniform::new("color_to", color_to), Uniform::new("grad_offset", grad_offset.to_array()), diff --git a/src/render_helpers/shaders/border.frag b/src/render_helpers/shaders/border.frag index a79835a..52d2a04 100644 --- a/src/render_helpers/shaders/border.frag +++ b/src/render_helpers/shaders/border.frag @@ -1,55 +1,3 @@ -precision mediump float; - -#if defined(DEBUG_FLAGS) -uniform float niri_tint; -#endif - -uniform float niri_alpha; -uniform float niri_scale; - -uniform vec2 niri_size; -varying vec2 niri_v_coords; - -uniform vec4 color_from; -uniform vec4 color_to; -uniform vec2 grad_offset; -uniform float grad_width; -uniform vec2 grad_vec; - -uniform mat3 input_to_geo; -uniform vec2 geo_size; -uniform vec4 outer_radius; -uniform float border_width; - - -vec4 linear_color_mix(vec4 color1, vec4 color2, float color_ratio) { - vec4 lin_color1 = vec4( - pow(color1.r, 2.0), - pow(color1.g, 2.0), - pow(color1.b, 2.0), - color1.a - ); - - vec4 lin_color2 = vec4( - pow(color2.r, 2.0), - pow(color2.g, 2.0), - pow(color2.b, 2.0), - color2.a - ); - - vec4 color_out = mix( - lin_color1, - lin_color2, - color_ratio - ); - - return vec4(sqrt(color_out.r), - sqrt(color_out.g), - sqrt(color_out.b), - color_out.a - ); -} - vec4 gradient_color(vec2 coords) { coords = coords + grad_offset; @@ -62,7 +10,7 @@ vec4 gradient_color(vec2 coords) { frac += 1.0; frac = clamp(frac, 0.0, 1.0); - return linear_color_mix(color_from, color_to, frac); + return color_mix(color_from, color_to, frac); } float rounding_alpha(vec2 coords, vec2 size, vec4 corner_radius) { diff --git a/src/render_helpers/shaders/mod.rs b/src/render_helpers/shaders/mod.rs index b482493..d371f07 100644 --- a/src/render_helpers/shaders/mod.rs +++ b/src/render_helpers/shaders/mod.rs @@ -32,8 +32,13 @@ impl Shaders { let border = ShaderProgram::compile( renderer, - include_str!("border.frag"), + concat!( + include_str!("border_head.frag"), + include_str!("color_interpol.frag"), + include_str!("border.frag") + ), &[ + UniformName::new("grad_format", UniformType::_1f), UniformName::new("color_from", UniformType::_4f), UniformName::new("color_to", UniformType::_4f), UniformName::new("grad_offset", UniformType::_2f), @@ -66,7 +71,13 @@ impl Shaders { }) .ok(); - let resize = compile_resize_program(renderer, include_str!("resize.frag")) + let resize = compile_resize_program( + renderer, + concat!( + include_str!("color_interpol.frag"), + include_str!("resize.frag") + ) + ) .map_err(|err| { warn!("error compiling resize shader: {err:?}"); }) @@ -150,6 +161,7 @@ fn compile_resize_program( renderer, &program, &[ + UniformName::new("grad_format", UniformType::_1f), UniformName::new("niri_input_to_curr_geo", UniformType::Matrix3x3), UniformName::new("niri_curr_geo_to_prev_geo", UniformType::Matrix3x3), UniformName::new("niri_curr_geo_to_next_geo", UniformType::Matrix3x3), diff --git a/src/render_helpers/shaders/resize.frag b/src/render_helpers/shaders/resize.frag index 94f250d..de39625 100644 --- a/src/render_helpers/shaders/resize.frag +++ b/src/render_helpers/shaders/resize.frag @@ -1,33 +1,3 @@ - -vec4 linear_color_mix(vec4 color1, vec4 color2, float color_ratio) { - vec4 lin_color1 = vec4( - pow(color1.r, 2.0), - pow(color1.g, 2.0), - pow(color1.b, 2.0), - color1.a - ); - - vec4 lin_color2 = vec4( - pow(color2.r, 2.0), - pow(color2.g, 2.0), - pow(color2.b, 2.0), - color2.a - ); - - vec4 color_out = mix( - lin_color1, - lin_color2, - color_ratio - ); - - return vec4(sqrt(color_out.r), - sqrt(color_out.g), - sqrt(color_out.b), - color_out.a - ); -} - - vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) { vec3 coords_tex_prev = niri_geo_to_tex_prev * coords_curr_geo; vec4 color_prev = texture2D(niri_tex_prev, coords_tex_prev.st); @@ -35,6 +5,6 @@ vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) { vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo; vec4 color_next = texture2D(niri_tex_next, coords_tex_next.st); - vec4 color = linear_color_mix(color_prev, color_next, niri_clamped_progress); + vec4 color = color_mix(color_prev, color_next, niri_clamped_progress); return color; } diff --git a/src/render_helpers/shaders/resize_prelude.frag b/src/render_helpers/shaders/resize_prelude.frag index 519b1ee..34a1f87 100644 --- a/src/render_helpers/shaders/resize_prelude.frag +++ b/src/render_helpers/shaders/resize_prelude.frag @@ -7,6 +7,7 @@ uniform float niri_tint; varying vec2 niri_v_coords; uniform vec2 niri_size; +uniform float grad_format; uniform mat3 niri_input_to_curr_geo; uniform mat3 niri_curr_geo_to_prev_geo; uniform mat3 niri_curr_geo_to_next_geo; diff --git a/src/window/mapped.rs b/src/window/mapped.rs index 8b6b8e6..b66a513 100644 --- a/src/window/mapped.rs +++ b/src/window/mapped.rs @@ -289,6 +289,7 @@ impl Mapped { return BorderRenderElement::new( geo.size, Rectangle::from_loc_and_size((0., 0.), geo.size), + 0., elem.color(), elem.color(), 0., From e5e0cc449f689ebd170a93520ac0a225e869dccf Mon Sep 17 00:00:00 2001 From: K's Thinkpad Date: Thu, 4 Jul 2024 21:46:08 +0200 Subject: [PATCH 3/5] has functioning optional gradient change --- src/render_helpers/shaders/border_head.frag | 30 +++++++++++++ .../shaders/color_interpol.frag | 44 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/render_helpers/shaders/border_head.frag create mode 100644 src/render_helpers/shaders/color_interpol.frag diff --git a/src/render_helpers/shaders/border_head.frag b/src/render_helpers/shaders/border_head.frag new file mode 100644 index 0000000..8a9fe60 --- /dev/null +++ b/src/render_helpers/shaders/border_head.frag @@ -0,0 +1,30 @@ +precision mediump float; + +#if defined(DEBUG_FLAGS) +uniform float niri_tint; +#endif + +uniform float niri_alpha; +uniform float niri_scale; + +uniform vec2 niri_size; +varying vec2 niri_v_coords; + +uniform float grad_format; +uniform vec4 color_from; +uniform vec4 color_to; +uniform vec2 grad_offset; +uniform float grad_width; +uniform vec2 grad_vec; + +uniform mat3 input_to_geo; +uniform vec2 geo_size; +uniform vec4 outer_radius; +uniform float border_width; + + +// FIXME this is a terrible solution however, +// I need to insert a different file with +// functions after this part as adding them ahead will cause errors at runtime +// and havent found a clean way to do this +// this is prob super simple and im just too stupid diff --git a/src/render_helpers/shaders/color_interpol.frag b/src/render_helpers/shaders/color_interpol.frag new file mode 100644 index 0000000..70621e4 --- /dev/null +++ b/src/render_helpers/shaders/color_interpol.frag @@ -0,0 +1,44 @@ + +vec4 color_linear(vec4 color) { + return vec4( + pow(color.r, 2.0), + pow(color.g, 2.0), + pow(color.b, 2.0), + color.a + ); +} + +vec4 color_root(vec4 color) { + return vec4( + sqrt(color.r), + sqrt(color.g), + sqrt(color.b), + color.a + ); +} + +vec4 color_mix(vec4 color1, vec4 color2, float color_ratio) { + + float gradient_type = grad_format; + + if(gradient_type == 0.0) { // CssLinear + return mix(color1, color2, color_ratio); + } + + vec4 color_out; + + color1 = color_linear(color1); + color2 = color_linear(color2); + + if (gradient_type == 1.0) { + color_out = mix( + color1, + color2, + color_ratio + ); + }else{ + color_out = vec4(255.0,0.0,0.0,1.0); + } + + return color_root(color_out); +} From f3dbb0297598e13a6e9bb356d9140ab43416a3b7 Mon Sep 17 00:00:00 2001 From: K's Thinkpad Date: Fri, 5 Jul 2024 00:09:51 +0200 Subject: [PATCH 4/5] updated the config and the wiki to reflect current state --- resources/default-config.kdl | 1 + src/render_helpers/shaders/color_interpol.frag | 6 ++---- wiki/Configuration:-Layout.md | 13 ++++++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/resources/default-config.kdl b/resources/default-config.kdl index 469517d..a4b1cbd 100644 --- a/resources/default-config.kdl +++ b/resources/default-config.kdl @@ -152,6 +152,7 @@ layout { // The angle is the same as in linear-gradient, and is optional, // defaulting to 180 (top-to-bottom gradient). // You can use any CSS linear-gradient tool on the web to set these up. + // for gradient types visit the wiki // // active-gradient from="#80c8ff" to="#bbddff" angle=45 diff --git a/src/render_helpers/shaders/color_interpol.frag b/src/render_helpers/shaders/color_interpol.frag index 70621e4..00ed120 100644 --- a/src/render_helpers/shaders/color_interpol.frag +++ b/src/render_helpers/shaders/color_interpol.frag @@ -18,10 +18,8 @@ vec4 color_root(vec4 color) { } vec4 color_mix(vec4 color1, vec4 color2, float color_ratio) { - - float gradient_type = grad_format; - if(gradient_type == 0.0) { // CssLinear + if(grad_format == 0.0) { // CssLinear return mix(color1, color2, color_ratio); } @@ -30,7 +28,7 @@ vec4 color_mix(vec4 color1, vec4 color2, float color_ratio) { color1 = color_linear(color1); color2 = color_linear(color2); - if (gradient_type == 1.0) { + if (grad_format == 1.0) { // rgb linear color_out = mix( color1, color2, diff --git a/wiki/Configuration:-Layout.md b/wiki/Configuration:-Layout.md index e27d0ef..7e3d096 100644 --- a/wiki/Configuration:-Layout.md +++ b/wiki/Configuration:-Layout.md @@ -32,7 +32,7 @@ layout { active-color "#ffc87f" inactive-color "#505050" // active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view" - // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" + // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" gradient-type="linear" } struts { @@ -169,7 +169,7 @@ layout { inactive-color "#505050" // active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view" - // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" + // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view" gradient-type="linear" } } ``` @@ -209,7 +209,7 @@ There's also a *deprecated* syntax for setting colors with four numbers represen Similarly to colors, you can set `active-gradient` and `inactive-gradient`, which will take precedence. -Gradients are rendered the same as CSS [`linear-gradient(angle, from, to)`](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient). +Gradients can be rendered the same as CSS [`linear-gradient(angle, from, to)`](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient). The angle works the same as in `linear-gradient`, and is optional, defaulting to `180` (top-to-bottom gradient). You can use any CSS linear-gradient tool on the web to set these up, like [this one](https://www.css-gradient.com/). @@ -221,6 +221,13 @@ layout { } ``` +Gradients can be rendered with different kinds of color interpolation, this doesen't mean that the arguments the gradient takes +are any different. Except for an optional `gradient-type` argument which can currently be: +`gradient-type="css-linear"`(Default), +`gradient-type="linear"`, +`gradient-type="Oklab"`(Unimplemented), +`gradient-type="Lch"` + Gradients can be colored relative to windows individually (the default), or to the whole view of the workspace. To do that, set `relative-to="workspace-view"`. Here's a visual example: From 6c263d59c3d2fc6f9b3ac8996d25ccf723c9a950 Mon Sep 17 00:00:00 2001 From: Kiko Date: Thu, 4 Jul 2024 22:12:03 +0000 Subject: [PATCH 5/5] Update Configuration:-Layout.md --- wiki/Configuration:-Layout.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wiki/Configuration:-Layout.md b/wiki/Configuration:-Layout.md index 7e3d096..fcf3d8f 100644 --- a/wiki/Configuration:-Layout.md +++ b/wiki/Configuration:-Layout.md @@ -223,11 +223,16 @@ layout { Gradients can be rendered with different kinds of color interpolation, this doesen't mean that the arguments the gradient takes are any different. Except for an optional `gradient-type` argument which can currently be: + `gradient-type="css-linear"`(Default), + `gradient-type="linear"`, + `gradient-type="Oklab"`(Unimplemented), + `gradient-type="Lch"` + Gradients can be colored relative to windows individually (the default), or to the whole view of the workspace. To do that, set `relative-to="workspace-view"`. Here's a visual example: