2022-09-29 10:52:58 -07:00
|
|
|
use crate::program::Version;
|
2022-10-04 18:24:46 -07:00
|
|
|
use crate::triangle::{simple_triangle_program, set_transform};
|
2022-09-29 10:52:58 -07:00
|
|
|
use glow::{Context, HasContext, NativeProgram};
|
2022-10-04 18:24:46 -07:00
|
|
|
use iced_graphics::gradient::Linear;
|
2022-09-29 10:52:58 -07:00
|
|
|
use iced_graphics::gradient::Gradient;
|
|
|
|
|
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 {
|
|
|
|
|
gradient_start_location: <Context as HasContext>::UniformLocation,
|
|
|
|
|
gradient_end_location: <Context as HasContext>::UniformLocation,
|
|
|
|
|
color_stops_size_location: <Context as HasContext>::UniformLocation,
|
|
|
|
|
//currently the maximum number of stops is 64 due to needing to allocate the
|
|
|
|
|
//memory for the array of stops with a const value in GLSL
|
|
|
|
|
color_stops_locations: [ColorStopLocation; 64],
|
|
|
|
|
transform_location: <Context as HasContext>::UniformLocation,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Debug, Clone)]
|
|
|
|
|
struct ColorStopLocation {
|
|
|
|
|
color: <Context as HasContext>::UniformLocation,
|
|
|
|
|
offset: <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 {
|
|
|
|
|
set_transform(gl, self.uniform_data.uniform_locations.transform_location, *transform);
|
|
|
|
|
}
|
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) => {
|
|
|
|
|
let gradient_start: [f32; 2] = (linear.start).into();
|
|
|
|
|
let gradient_end: [f32; 2] = (linear.end).into();
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
gl.uniform_2_f32(
|
|
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
|
|
|
|
.gradient_start_location,
|
|
|
|
|
),
|
|
|
|
|
gradient_start[0],
|
|
|
|
|
gradient_start[1],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
gl.uniform_2_f32(
|
|
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
|
|
|
|
.gradient_end_location,
|
|
|
|
|
),
|
|
|
|
|
gradient_end[0],
|
|
|
|
|
gradient_end[1],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
gl.uniform_1_u32(
|
|
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
|
|
|
|
.color_stops_size_location,
|
|
|
|
|
),
|
|
|
|
|
linear.color_stops.len() as u32,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for (index, stop) in
|
|
|
|
|
linear.color_stops.iter().enumerate()
|
|
|
|
|
{
|
|
|
|
|
gl.uniform_1_f32(
|
|
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
|
|
|
|
.color_stops_locations[index]
|
|
|
|
|
.offset,
|
|
|
|
|
),
|
|
|
|
|
stop.offset,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
gl.uniform_4_f32(
|
|
|
|
|
Some(
|
|
|
|
|
&self
|
|
|
|
|
.uniform_data
|
|
|
|
|
.uniform_locations
|
|
|
|
|
.color_stops_locations[index]
|
|
|
|
|
.color,
|
|
|
|
|
),
|
|
|
|
|
stop.color.r,
|
|
|
|
|
stop.color.g,
|
|
|
|
|
stop.color.b,
|
|
|
|
|
stop.color.a,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
self.uniform_data.gradient = gradient.clone();
|
2022-09-29 10:52:58 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
pub fn use_program(&mut self, gl: &glow::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 {
|
|
|
|
|
let gradient_start_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "gradient_start") }
|
|
|
|
|
.expect("Gradient - Get gradient_start.");
|
|
|
|
|
|
|
|
|
|
let gradient_end_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "gradient_end") }
|
|
|
|
|
.expect("Gradient - Get gradient_end.");
|
|
|
|
|
|
|
|
|
|
let color_stops_size_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "color_stops_size") }
|
|
|
|
|
.expect("Gradient - Get color_stops_size.");
|
|
|
|
|
|
|
|
|
|
let color_stops_locations: [ColorStopLocation; 64] =
|
|
|
|
|
core::array::from_fn(|index| {
|
|
|
|
|
let offset = unsafe {
|
|
|
|
|
gl.get_uniform_location(
|
|
|
|
|
program,
|
|
|
|
|
&format!("color_stop_offsets[{}]", index),
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-10-04 18:24:46 -07:00
|
|
|
.expect("Gradient - Color stop offset location.");
|
2022-09-29 10:52:58 -07:00
|
|
|
|
|
|
|
|
let color = unsafe {
|
|
|
|
|
gl.get_uniform_location(
|
|
|
|
|
program,
|
|
|
|
|
&format!("color_stop_colors[{}]", index),
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-10-04 18:24:46 -07:00
|
|
|
.expect("Gradient - Color stop color location.");
|
2022-09-29 10:52:58 -07:00
|
|
|
|
|
|
|
|
ColorStopLocation { color, offset }
|
|
|
|
|
});
|
|
|
|
|
|
2022-10-04 18:24:46 -07:00
|
|
|
let transform_location =
|
|
|
|
|
unsafe { gl.get_uniform_location(program, "u_Transform") }
|
|
|
|
|
.expect("Get transform location.");
|
|
|
|
|
|
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 {
|
|
|
|
|
gradient_start_location,
|
|
|
|
|
gradient_end_location,
|
|
|
|
|
color_stops_size_location,
|
|
|
|
|
color_stops_locations,
|
2022-10-04 18:24:46 -07:00
|
|
|
transform_location,
|
2022-09-29 10:52:58 -07:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|