1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::traits::{Lerp, Real};
use crate::vector::{TVec2, TVec3};
pub struct LinearGradientBuilder<T: Real> {
start_pos: TVec2<T>,
start_col: TVec3<T>,
end_pos: TVec2<T>,
end_col: TVec3<T>,
}
impl<T: Real> LinearGradientBuilder<T> {
pub fn new() -> Self {
LinearGradientBuilder {
start_pos: TVec2::zero(),
start_col: TVec3::zero(),
end_pos: TVec2::zero(),
end_col: TVec3::zero(),
}
}
pub fn start(mut self, pos: TVec2<T>, color: TVec3<T>) -> Self {
self.start_pos = pos;
self.start_col = color;
self
}
pub fn end(mut self, pos: TVec2<T>, color: TVec3<T>) -> Self {
self.end_pos = pos;
self.end_col = color;
self
}
pub fn build(self) -> LinearGradient<T> {
let a = self.end_pos[0] - self.start_pos[0];
let b = self.end_pos[1] - self.start_pos[1];
LinearGradient {
start_col: self.start_col,
end_col: self.end_col,
a,
b,
c1: (a * self.start_pos[0]) + (b * self.start_pos[1]),
c2: (a * self.end_pos[0]) + (b * self.end_pos[1]),
}
}
}
impl<T: Real> Default for LinearGradientBuilder<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
pub struct LinearGradient<T: Real> {
start_col: TVec3<T>,
end_col: TVec3<T>,
a: T,
b: T,
c1: T,
c2: T,
}
impl<T: Real> LinearGradient<T> {
pub fn builder() -> LinearGradientBuilder<T> {
LinearGradientBuilder::new()
}
pub fn sample(&self, point: TVec2<T>) -> TVec3<T> {
let c = self.a * point[0] + self.b * point[1];
if c <= self.c1 {
self.start_col
} else if c >= self.c2 {
self.end_col
} else {
let factor =
(T::zero() * (self.c2 - c)) + (T::one() * (c - self.c1)) / (self.c2 - self.c1);
self.start_col.lerp(&self.end_col, factor)
}
}
}