cranpose_ui_graphics/
alpha_mask.rs1use crate::{CornerRadii, RenderEffect, RuntimeShader};
8
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
11pub enum CutDirection {
12 #[default]
14 LeftToRight,
15 RightToLeft,
17 TopToBottom,
19 BottomToTop,
21}
22
23impl CutDirection {
24 fn uniform_code(self) -> f32 {
25 match self {
26 CutDirection::LeftToRight => 0.0,
27 CutDirection::RightToLeft => 1.0,
28 CutDirection::TopToBottom => 2.0,
29 CutDirection::BottomToTop => 3.0,
30 }
31 }
32}
33
34#[derive(Clone, Copy, Debug, PartialEq)]
36pub struct GradientCutMaskSpec {
37 pub progress: f32,
39 pub feather: f32,
41 pub corner_radius: f32,
43 pub direction: CutDirection,
45}
46
47impl Default for GradientCutMaskSpec {
48 fn default() -> Self {
49 Self {
50 progress: 0.5,
51 feather: 24.0,
52 corner_radius: 16.0,
53 direction: CutDirection::LeftToRight,
54 }
55 }
56}
57
58#[derive(Clone, Copy, Debug, PartialEq)]
61pub struct GradientFadeMaskSpec {
62 pub start: f32,
64 pub end: f32,
66 pub direction: CutDirection,
68}
69
70impl Default for GradientFadeMaskSpec {
71 fn default() -> Self {
72 Self {
73 start: 0.0,
74 end: 64.0,
75 direction: CutDirection::TopToBottom,
76 }
77 }
78}
79
80pub const GRADIENT_CUT_MASK_WGSL: &str = runtime_shader_wgsl!("gradient_cut_mask.wgsl");
89
90pub const ROUNDED_ALPHA_MASK_WGSL: &str = runtime_shader_wgsl!("rounded_alpha_mask.wgsl");
97
98pub const GRADIENT_FADE_DST_OUT_WGSL: &str = runtime_shader_wgsl!("gradient_fade_dst_out.wgsl");
106
107pub fn gradient_cut_mask_effect(
112 spec: &GradientCutMaskSpec,
113 area_width: f32,
114 area_height: f32,
115) -> RenderEffect {
116 let mut shader = RuntimeShader::new(GRADIENT_CUT_MASK_WGSL);
117 shader.set_position_independent(true);
118 shader.set_float2(0, area_width.max(1.0), area_height.max(1.0));
119 shader.set_float(2, spec.progress.clamp(0.0, 1.0));
120 shader.set_float(3, spec.feather.max(0.0));
121 shader.set_float(4, spec.corner_radius.max(0.0));
122 shader.set_float(5, spec.direction.uniform_code());
123 RenderEffect::runtime_shader(shader)
124}
125
126pub fn rounded_alpha_mask_effect(
131 area_width: f32,
132 area_height: f32,
133 corner_radius: f32,
134 edge_feather: f32,
135) -> RenderEffect {
136 rounded_corner_alpha_mask_effect(
137 area_width,
138 area_height,
139 CornerRadii::uniform(corner_radius),
140 edge_feather,
141 )
142}
143
144pub fn rounded_corner_alpha_mask_effect(
146 area_width: f32,
147 area_height: f32,
148 corner_radii: CornerRadii,
149 edge_feather: f32,
150) -> RenderEffect {
151 let mut shader = RuntimeShader::new(ROUNDED_ALPHA_MASK_WGSL);
152 shader.set_position_independent(true);
153 shader.set_float2(0, area_width.max(1.0), area_height.max(1.0));
154 shader.set_float(2, edge_feather.max(0.0));
155 shader.set_float4(
156 3,
157 corner_radii.top_left.max(0.0),
158 corner_radii.top_right.max(0.0),
159 corner_radii.bottom_right.max(0.0),
160 corner_radii.bottom_left.max(0.0),
161 );
162 RenderEffect::runtime_shader(shader)
163}
164
165pub fn gradient_fade_dst_out_effect(
171 spec: &GradientFadeMaskSpec,
172 area_width: f32,
173 area_height: f32,
174) -> RenderEffect {
175 let mut shader = RuntimeShader::new(GRADIENT_FADE_DST_OUT_WGSL);
176 shader.set_position_independent(true);
177 shader.set_float2(0, area_width.max(1.0), area_height.max(1.0));
178 shader.set_float(2, spec.start);
179 shader.set_float(3, spec.end);
180 shader.set_float(4, spec.direction.uniform_code());
181 RenderEffect::runtime_shader(shader)
182}
183
184#[cfg(test)]
185#[path = "tests/alpha_mask_tests.rs"]
186mod tests;