aboutsummaryrefslogtreecommitdiff
path: root/src/render_helpers/shaders
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-02-21 21:27:44 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-02-21 22:15:21 +0400
commit48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e (patch)
treed71dbc10132f38f59e4a72d1d8a509102f701f8c /src/render_helpers/shaders
parent340bac0690972ee6f6badc8d386162320d70b7bd (diff)
downloadniri-48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e.tar.gz
niri-48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e.tar.bz2
niri-48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e.zip
Implement gradient borders
Diffstat (limited to 'src/render_helpers/shaders')
-rw-r--r--src/render_helpers/shaders/gradient_border.frag46
-rw-r--r--src/render_helpers/shaders/mod.rs47
2 files changed, 93 insertions, 0 deletions
diff --git a/src/render_helpers/shaders/gradient_border.frag b/src/render_helpers/shaders/gradient_border.frag
new file mode 100644
index 00000000..354968cf
--- /dev/null
+++ b/src/render_helpers/shaders/gradient_border.frag
@@ -0,0 +1,46 @@
+precision mediump float;
+uniform float alpha;
+#if defined(DEBUG_FLAGS)
+uniform float tint;
+#endif
+uniform vec2 size;
+varying vec2 v_coords;
+
+uniform vec4 color_from;
+uniform vec4 color_to;
+uniform float angle;
+uniform vec2 gradient_offset;
+uniform float gradient_width;
+uniform float gradient_total;
+
+#define FRAC_PI_2 1.57079632679
+#define PI 3.14159265359
+#define FRAC_3_PI_2 4.71238898038
+#define TAU 6.28318530718
+
+void main() {
+ vec2 coords = v_coords * size + gradient_offset;
+
+ if ((FRAC_PI_2 <= angle && angle < PI) || (FRAC_3_PI_2 <= angle && angle < TAU))
+ coords.x -= gradient_width;
+
+ float frag_angle = FRAC_PI_2;
+ if (coords.x != 0.0)
+ frag_angle = atan(coords.y, coords.x);
+
+ float angle_frag_to_grad = frag_angle - angle;
+
+ float frac = cos(angle_frag_to_grad) * length(coords) / gradient_total;
+ if (PI <= angle)
+ frac += 1.0;
+ frac = clamp(frac, 0.0, 1.0);
+
+ vec4 out_color = mix(color_from, color_to, frac);
+
+#if defined(DEBUG_FLAGS)
+ if (tint == 1.0)
+ out_color = vec4(0.0, 0.3, 0.0, 0.2) + out_color * 0.8;
+#endif
+
+ gl_FragColor = out_color;
+}
diff --git a/src/render_helpers/shaders/mod.rs b/src/render_helpers/shaders/mod.rs
new file mode 100644
index 00000000..72e9fa1c
--- /dev/null
+++ b/src/render_helpers/shaders/mod.rs
@@ -0,0 +1,47 @@
+use smithay::backend::renderer::gles::{GlesPixelProgram, GlesRenderer, UniformName, UniformType};
+
+use super::renderer::NiriRenderer;
+
+pub struct Shaders {
+ pub gradient_border: Option<GlesPixelProgram>,
+}
+
+impl Shaders {
+ fn compile(renderer: &mut GlesRenderer) -> Self {
+ let _span = tracy_client::span!("Shaders::compile");
+
+ let gradient_border = renderer
+ .compile_custom_pixel_shader(
+ include_str!("gradient_border.frag"),
+ &[
+ UniformName::new("color_from", UniformType::_4f),
+ UniformName::new("color_to", UniformType::_4f),
+ UniformName::new("angle", UniformType::_1f),
+ UniformName::new("gradient_offset", UniformType::_2f),
+ UniformName::new("gradient_width", UniformType::_1f),
+ UniformName::new("gradient_total", UniformType::_1f),
+ ],
+ )
+ .map_err(|err| {
+ warn!("error compiling gradient border shader: {err:?}");
+ })
+ .ok();
+
+ Self { gradient_border }
+ }
+
+ pub fn get(renderer: &mut impl NiriRenderer) -> &Self {
+ let renderer = renderer.as_gles_renderer();
+ let data = renderer.egl_context().user_data();
+ data.get()
+ .expect("shaders::init() must be called when creating the renderer")
+ }
+}
+
+pub fn init(renderer: &mut GlesRenderer) {
+ let shaders = Shaders::compile(renderer);
+ let data = renderer.egl_context().user_data();
+ if !data.insert_if_missing(|| shaders) {
+ error!("shaders were already compiled");
+ }
+}