summaryrefslogtreecommitdiffstats
path: root/glow/src/triangle
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2022-11-03 18:57:09 +0100
committerLibravatar GitHub <noreply@github.com>2022-11-03 18:57:09 +0100
commitd222b5c8b0befab665c20ba0112b28199df0ae44 (patch)
tree0ac3a59f04e1c1ca89ff43800efbefd825b015ea /glow/src/triangle
parenta8f510c39917b2ac42fcc854f0a7eff13aee9838 (diff)
parentf31c8f2504ea7c004c5caed8913e5da28d2e50e2 (diff)
downloadiced-d222b5c8b0befab665c20ba0112b28199df0ae44.tar.gz
iced-d222b5c8b0befab665c20ba0112b28199df0ae44.tar.bz2
iced-d222b5c8b0befab665c20ba0112b28199df0ae44.zip
Merge pull request #1448 from bungoboingo/fear/linear-gradients
Add linear gradient support to canvas widget
Diffstat (limited to 'glow/src/triangle')
-rw-r--r--glow/src/triangle/gradient.rs162
-rw-r--r--glow/src/triangle/solid.rs91
2 files changed, 253 insertions, 0 deletions
diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs
new file mode 100644
index 00000000..5225612e
--- /dev/null
+++ b/glow/src/triangle/gradient.rs
@@ -0,0 +1,162 @@
+use crate::program::Version;
+use crate::triangle;
+use glow::{Context, HasContext, NativeProgram};
+use iced_graphics::gradient::Gradient;
+use iced_graphics::gradient::Linear;
+use iced_graphics::Transformation;
+
+#[derive(Debug)]
+pub struct Program {
+ pub program: <Context as HasContext>::Program,
+ pub uniform_data: UniformData,
+}
+
+#[derive(Debug)]
+pub struct UniformData {
+ gradient: Gradient,
+ transform: Transformation,
+ uniform_locations: UniformLocations,
+}
+
+#[derive(Debug)]
+struct UniformLocations {
+ gradient_direction_location: <Context as HasContext>::UniformLocation,
+ color_stops_size_location: <Context as HasContext>::UniformLocation,
+ //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1
+ color_stops_location: <Context as HasContext>::UniformLocation,
+ transform_location: <Context as HasContext>::UniformLocation,
+}
+
+impl Program {
+ pub fn new(gl: &Context, shader_version: &Version) -> Self {
+ let program = triangle::program(
+ gl,
+ shader_version,
+ include_str!("../shader/common/gradient.frag"),
+ );
+
+ Self {
+ program,
+ uniform_data: UniformData::new(gl, program),
+ }
+ }
+
+ pub fn write_uniforms(
+ &mut self,
+ gl: &Context,
+ gradient: &Gradient,
+ transform: &Transformation,
+ ) {
+ if transform != &self.uniform_data.transform {
+ triangle::set_transform(
+ gl,
+ self.uniform_data.uniform_locations.transform_location,
+ *transform,
+ );
+ }
+
+ if &self.uniform_data.gradient != gradient {
+ match gradient {
+ Gradient::Linear(linear) => unsafe {
+ gl.uniform_4_f32(
+ Some(
+ &self
+ .uniform_data
+ .uniform_locations
+ .gradient_direction_location,
+ ),
+ linear.start.x,
+ linear.start.y,
+ linear.end.x,
+ linear.end.y,
+ );
+
+ gl.uniform_1_u32(
+ Some(
+ &self
+ .uniform_data
+ .uniform_locations
+ .color_stops_size_location,
+ ),
+ (linear.color_stops.len() * 2) as u32,
+ );
+
+ let mut stops = [0.0; 128];
+
+ for (index, stop) in
+ linear.color_stops.iter().enumerate().take(16)
+ {
+ let [r, g, b, a] = stop.color.into_linear();
+
+ stops[index * 8] = r;
+ stops[(index * 8) + 1] = g;
+ stops[(index * 8) + 2] = b;
+ stops[(index * 8) + 3] = a;
+ stops[(index * 8) + 4] = stop.offset;
+ stops[(index * 8) + 5] = 0.;
+ stops[(index * 8) + 6] = 0.;
+ stops[(index * 8) + 7] = 0.;
+ }
+
+ gl.uniform_4_f32_slice(
+ Some(
+ &self
+ .uniform_data
+ .uniform_locations
+ .color_stops_location,
+ ),
+ &stops,
+ );
+ },
+ }
+
+ self.uniform_data.gradient = gradient.clone();
+ }
+ }
+
+ pub fn use_program(
+ &mut self,
+ gl: &Context,
+ gradient: &Gradient,
+ transform: &Transformation,
+ ) {
+ unsafe { gl.use_program(Some(self.program)) }
+ self.write_uniforms(gl, gradient, transform);
+ }
+}
+
+impl UniformData {
+ fn new(gl: &Context, program: NativeProgram) -> Self {
+ let gradient_direction_location =
+ unsafe { gl.get_uniform_location(program, "gradient_direction") }
+ .expect("Gradient - Get gradient_direction.");
+
+ let color_stops_size_location =
+ unsafe { gl.get_uniform_location(program, "color_stops_size") }
+ .expect("Gradient - Get color_stops_size.");
+
+ let color_stops_location = unsafe {
+ gl.get_uniform_location(program, "color_stops")
+ .expect("Gradient - Get color_stops.")
+ };
+
+ let transform_location =
+ unsafe { gl.get_uniform_location(program, "u_Transform") }
+ .expect("Gradient - Get u_Transform.");
+
+ Self {
+ gradient: Gradient::Linear(Linear {
+ start: Default::default(),
+ end: Default::default(),
+ color_stops: vec![],
+ }),
+ transform: Transformation::identity(),
+ uniform_locations: UniformLocations {
+ gradient_direction_location,
+ color_stops_size_location,
+ color_stops_location,
+ transform_location,
+ },
+ }
+ }
+}
diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs
new file mode 100644
index 00000000..fb3d40c3
--- /dev/null
+++ b/glow/src/triangle/solid.rs
@@ -0,0 +1,91 @@
+use crate::program::Version;
+use crate::{triangle, Color};
+use glow::{Context, HasContext, NativeProgram};
+use iced_graphics::Transformation;
+
+#[derive(Debug)]
+pub struct Program {
+ program: <Context as HasContext>::Program,
+ uniform_data: UniformData,
+}
+
+#[derive(Debug)]
+struct UniformData {
+ pub color: Color,
+ pub color_location: <Context as HasContext>::UniformLocation,
+ pub transform: Transformation,
+ pub transform_location: <Context as HasContext>::UniformLocation,
+}
+
+impl UniformData {
+ fn new(gl: &Context, program: NativeProgram) -> Self {
+ Self {
+ color: Color::TRANSPARENT,
+ color_location: unsafe {
+ gl.get_uniform_location(program, "color")
+ }
+ .expect("Solid - Get color."),
+ transform: Transformation::identity(),
+ transform_location: unsafe {
+ gl.get_uniform_location(program, "u_Transform")
+ }
+ .expect("Solid - Get u_Transform."),
+ }
+ }
+}
+
+impl Program {
+ pub fn new(gl: &Context, shader_version: &Version) -> Self {
+ let program = triangle::program(
+ gl,
+ shader_version,
+ include_str!("../shader/common/triangle.frag"),
+ );
+
+ Self {
+ program,
+ uniform_data: UniformData::new(gl, program),
+ }
+ }
+
+ pub fn write_uniforms(
+ &mut self,
+ gl: &Context,
+ color: &Color,
+ transform: &Transformation,
+ ) {
+ if transform != &self.uniform_data.transform {
+ triangle::set_transform(
+ gl,
+ self.uniform_data.transform_location,
+ *transform,
+ )
+ }
+
+ if color != &self.uniform_data.color {
+ let [r, g, b, a] = color.into_linear();
+
+ unsafe {
+ gl.uniform_4_f32(
+ Some(&self.uniform_data.color_location),
+ r,
+ g,
+ b,
+ a,
+ );
+ }
+
+ self.uniform_data.color = *color;
+ }
+ }
+
+ pub fn use_program(
+ &mut self,
+ gl: &Context,
+ color: &Color,
+ transform: &Transformation,
+ ) {
+ unsafe { gl.use_program(Some(self.program)) }
+ self.write_uniforms(gl, color, transform)
+ }
+}