2022-09-29 10:52:58 -07:00
|
|
|
use crate::program::Version;
|
2022-10-05 16:07:43 -07:00
|
|
|
use crate::triangle::{set_transform, simple_triangle_program};
|
2022-09-29 10:52:58 -07:00
|
|
|
use glow::{Context, HasContext, NativeProgram};
|
|
|
|
|
use iced_graphics::gradient::Gradient;
|
2022-10-05 16:07:43 -07:00
|
|
|
use iced_graphics::gradient::Linear;
|
2022-09-29 10:52:58 -07:00
|
|
|
use iced_graphics::Transformation;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2022-10-04 18:24:46 -07:00
|
|
|
pub struct GradientProgram {
|
|
|
|
|
pub program: <Context as HasContext>::Program,
|
|
|
|
|
pub uniform_data: GradientUniformData,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct GradientUniformData {
|
|
|
|
|
gradient: Gradient,
|
|
|
|
|
transform: Transformation,
|
|
|
|
|
uniform_locations: GradientUniformLocations,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
struct GradientUniformLocations {
|
2022-10-05 16:07:43 -07:00
|
|
|
gradient_direction_location: <Context as HasContext>::UniformLocation,
|
2022-10-04 18:24:46 -07:00
|
|
|
color_stops_size_location: <Context as HasContext>::UniformLocation,
|
2022-10-06 19:41:00 -07:00
|
|
|
//currently the maximum number of stops is 16 due to lack of SSBO in GL2.1
|
2022-10-05 16:07:43 -07:00
|
|
|
color_stops_location: <Context as HasContext>::UniformLocation,
|
2022-10-04 18:24:46 -07:00
|
|
|
transform_location: <Context as HasContext>::UniformLocation,
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-29 10:52:58 -07:00
|
|
|
impl GradientProgram {
|
2022-10-04 18:24:46 -07:00
|
|
|
pub fn new(gl: &Context, shader_version: &Version) -> Self {
|
2022-09-29 10:52:58 -07:00
|
|
|
let program = simple_triangle_program(
|
|
|
|
|
gl,
|
|
|
|
|
shader_version,
|
|
|
|
|
include_str!("../shader/common/gradient.frag"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
program,
|
|
|
|
|
uniform_data: GradientUniformData::new(gl, program),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
pub fn write_uniforms(
|
2022-09-29 10:52:58 -07:00
|
|
|
&mut self,
|
|
|
|
|
gl: &Context,
|
|
|
|
|
gradient: &Gradient,
|
2022-10-04 18:24:46 -07:00
|
|
|
transform: &Transformation,
|
2022-09-29 10:52:58 -07:00
|
|
|
) {
|
2022-10-04 18:24:46 -07:00
|
|
|
if transform != &self.uniform_data.transform {
|
2022-10-05 16:07:43 -07:00
|
|
|
set_transform(
|
|
|
|
|
gl,
|
|
|
|
|
self.uniform_data.uniform_locations.transform_location,
|
|
|
|
|
*transform,
|
|
|
|
|
);
|
2022-10-04 18:24:46 -07:00
|
|
|
}
|
2022-09-29 10:52:58 -07:00
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
if &self.uniform_data.gradient != gradient {
|
2022-09-29 10:52:58 -07:00
|
|
|
match gradient {
|
|
|
|
|
Gradient::Linear(linear) => {
|
|
|
|
|
unsafe {
|
2022-10-05 16:07:43 -07:00
|
|
|
gl.uniform_4_f32(
|
2022-09-29 10:52:58 -07:00
|
|
|
Some(
|
2022-10-05 16:07:43 -07:00
|
|
|
&self.uniform_data.uniform_locations.gradient_direction_location
|
2022-09-29 10:52:58 -07:00
|
|
|
),
|
2022-10-05 16:07:43 -07:00
|
|
|
linear.start.x,
|
|
|
|
|
linear.start.y,
|
|
|
|
|
linear.end.x,
|
|
|
|
|
linear.end.y
|
2022-09-29 10:52:58 -07:00
|
|
|
);
|
|
|
|
|
|
2022-10-05 16:07:43 -07:00
|
|
|
gl.uniform_1_u32(
|
2022-09-29 10:52:58 -07:00
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
2022-10-05 16:07:43 -07:00
|
|
|
.color_stops_size_location,
|
2022-09-29 10:52:58 -07:00
|
|
|
),
|
2022-10-05 16:07:43 -07:00
|
|
|
(linear.color_stops.len() * 2) as u32,
|
2022-09-29 10:52:58 -07:00
|
|
|
);
|
|
|
|
|
|
2022-10-05 16:07:43 -07:00
|
|
|
let mut stops = [0.0; 128];
|
|
|
|
|
|
|
|
|
|
for (index, stop) in linear.color_stops.iter().enumerate() {
|
|
|
|
|
if index == 16 { break; }
|
|
|
|
|
stops[index*8] = stop.color.r;
|
|
|
|
|
stops[(index*8)+1] = stop.color.g;
|
|
|
|
|
stops[(index*8)+2] = stop.color.b;
|
|
|
|
|
stops[(index*8)+3] = stop.color.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(
|
2022-09-29 10:52:58 -07:00
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
2022-10-05 16:07:43 -07:00
|
|
|
.color_stops_location,
|
2022-09-29 10:52:58 -07:00
|
|
|
),
|
2022-10-05 16:07:43 -07:00
|
|
|
&stops,
|
2022-09-29 10:52:58 -07:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
self.uniform_data.gradient = gradient.clone();
|
2022-09-29 10:52:58 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-05 16:07:43 -07:00
|
|
|
pub fn use_program(
|
|
|
|
|
&mut self,
|
|
|
|
|
gl: &Context,
|
|
|
|
|
gradient: &Gradient,
|
|
|
|
|
transform: &Transformation,
|
|
|
|
|
) {
|
|
|
|
|
unsafe { gl.use_program(Some(self.program)) }
|
2022-09-29 10:52:58 -07:00
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
self.write_uniforms(gl, gradient, transform);
|
|
|
|
|
}
|
2022-09-29 10:52:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl GradientUniformData {
|
|
|
|
|
fn new(gl: &Context, program: NativeProgram) -> Self {
|
2022-10-05 16:07:43 -07:00
|
|
|
let gradient_direction_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "gradient_direction") }
|
|
|
|
|
.expect("Gradient - Get gradient_direction.");
|
2022-09-29 10:52:58 -07:00
|
|
|
|
|
|
|
|
let color_stops_size_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "color_stops_size") }
|
|
|
|
|
.expect("Gradient - Get color_stops_size.");
|
|
|
|
|
|
2022-10-05 16:07:43 -07:00
|
|
|
let color_stops_location = unsafe {
|
|
|
|
|
gl.get_uniform_location(program, "color_stops")
|
|
|
|
|
.expect("Gradient - Get color_stops.")
|
|
|
|
|
};
|
2022-09-29 10:52:58 -07:00
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
let transform_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "u_Transform") }
|
2022-10-06 19:41:00 -07:00
|
|
|
.expect("Gradient - Get u_Transform.");
|
2022-10-04 18:24:46 -07:00
|
|
|
|
2022-09-29 10:52:58 -07:00
|
|
|
GradientUniformData {
|
2022-10-04 18:24:46 -07:00
|
|
|
gradient: Gradient::Linear(Linear {
|
2022-09-29 10:52:58 -07:00
|
|
|
start: Default::default(),
|
|
|
|
|
end: Default::default(),
|
|
|
|
|
color_stops: vec![],
|
|
|
|
|
}),
|
2022-10-04 18:24:46 -07:00
|
|
|
transform: Transformation::identity(),
|
2022-09-29 10:52:58 -07:00
|
|
|
uniform_locations: GradientUniformLocations {
|
2022-10-05 16:07:43 -07:00
|
|
|
gradient_direction_location,
|
2022-09-29 10:52:58 -07:00
|
|
|
color_stops_size_location,
|
2022-10-05 16:07:43 -07:00
|
|
|
color_stops_location,
|
2022-10-04 18:24:46 -07:00
|
|
|
transform_location,
|
2022-09-29 10:52:58 -07:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|