Simplify gradient border shader

This commit is contained in:
Ivan Molodetskikh 2024-02-22 10:17:06 +04:00
parent b091202d86
commit aefbad0cf7
5 changed files with 39 additions and 49 deletions

7
Cargo.lock generated
View File

@ -1390,6 +1390,12 @@ dependencies = [
"xml-rs",
]
[[package]]
name = "glam"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
[[package]]
name = "glib"
version = "0.19.0"
@ -2104,6 +2110,7 @@ dependencies = [
"directories",
"futures-util",
"git-version",
"glam",
"input",
"keyframe",
"libc",

View File

@ -50,6 +50,7 @@ clap = { workspace = true, features = ["string"] }
directories = "5.0.1"
futures-util = { version = "0.3.30", default-features = false, features = ["std", "io"] }
git-version = "0.3.9"
glam = "0.25.0"
input = { version = "0.9.0", features = ["libinput_1_21"] }
keyframe = { version = "1.1.1", default-features = false }
libc = "0.2.153"

View File

@ -1,5 +1,4 @@
use std::f32::consts::{self, FRAC_PI_2, PI};
use glam::Vec2;
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
use smithay::backend::renderer::gles::element::PixelShaderElement;
use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer, Uniform};
@ -23,31 +22,25 @@ impl GradientRenderElement {
gradient_area: Rectangle<i32, Logical>,
color_from: [f32; 4],
color_to: [f32; 4],
mut angle: f32,
angle: f32,
) -> Option<Self> {
let shader = Shaders::get(renderer).gradient_border.clone()?;
let g_offset = (area.loc - gradient_area.loc).to_f64().to_physical(scale);
let grad_offset = (area.loc - gradient_area.loc).to_f64().to_physical(scale);
let g_size = gradient_area.size.to_f64().to_physical(scale);
let (w, h) = (g_size.w as f32, g_size.h as f32);
let g_area_angle = f32::atan2(h, w);
let g_area_diag = f32::hypot(h, w);
let grad_dir = Vec2::from_angle(angle);
// Normalize the angle to [0°; 360°).
while angle < 0. {
angle += consts::TAU;
}
while angle >= consts::TAU {
angle -= consts::TAU;
let grad_area_size = gradient_area.size.to_f64().to_physical(scale);
let (w, h) = (grad_area_size.w as f32, grad_area_size.h as f32);
let mut grad_area_diag = Vec2::new(w, h);
if (grad_dir.x < 0. && 0. <= grad_dir.y) || (0. <= grad_dir.x && grad_dir.y < 0.) {
grad_area_diag.x = -w;
}
let angle_diag_to_grad =
if (0. ..=FRAC_PI_2).contains(&angle) || (PI..=PI + FRAC_PI_2).contains(&angle) {
angle - g_area_angle
} else {
(PI - angle) - g_area_angle
};
let g_total = angle_diag_to_grad.cos().abs() * g_area_diag;
let mut grad_vec = grad_area_diag.project_onto(grad_dir);
if grad_dir.y <= 0. {
grad_vec = -grad_vec;
}
let elem = PixelShaderElement::new(
shader,
@ -57,10 +50,9 @@ impl GradientRenderElement {
vec![
Uniform::new("color_from", color_from),
Uniform::new("color_to", color_to),
Uniform::new("angle", angle),
Uniform::new("gradient_offset", (g_offset.x as f32, g_offset.y as f32)),
Uniform::new("gradient_width", w),
Uniform::new("gradient_total", g_total),
Uniform::new("grad_offset", (grad_offset.x as f32, grad_offset.y as f32)),
Uniform::new("grad_width", w),
Uniform::new("grad_vec", grad_vec.to_array()),
],
Kind::Unspecified,
);

View File

@ -8,33 +8,24 @@ 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
uniform vec2 grad_offset;
uniform float grad_width;
uniform vec2 grad_vec;
void main() {
vec2 coords = v_coords * size + gradient_offset;
vec2 coords = v_coords * size + grad_offset;
if ((FRAC_PI_2 <= angle && angle < PI) || (FRAC_3_PI_2 <= angle && angle < TAU))
coords.x -= gradient_width;
if ((grad_vec.x < 0.0 && 0.0 <= grad_vec.y)
|| (0.0 <= grad_vec.x && grad_vec.y < 0.0)) {
coords.x -= grad_width;
}
float frag_angle = FRAC_PI_2;
if (coords.x != 0.0)
frag_angle = atan(coords.y, coords.x);
float frac = dot(coords, grad_vec) / dot(grad_vec, grad_vec);
float angle_frag_to_grad = frag_angle - angle;
if (grad_vec.y < 0.0)
frac = 1.0 + frac;
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)

View File

@ -16,10 +16,9 @@ impl Shaders {
&[
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),
UniformName::new("grad_offset", UniformType::_2f),
UniformName::new("grad_width", UniformType::_1f),
UniformName::new("grad_vec", UniformType::_2f),
],
)
.map_err(|err| {