diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-21 21:27:44 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-21 22:15:21 +0400 |
| commit | 48f0f6fb3ceb68fdb559ab38c8dcbb7b9ba3a13e (patch) | |
| tree | d71dbc10132f38f59e4a72d1d8a509102f701f8c /src/render_helpers/shaders | |
| parent | 340bac0690972ee6f6badc8d386162320d70b7bd (diff) | |
| download | niri-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.frag | 46 | ||||
| -rw-r--r-- | src/render_helpers/shaders/mod.rs | 47 |
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"); + } +} |
