Adds linear gradient support to 2D meshes in the canvas widget.
This commit is contained in:
parent
97f385e093
commit
00a8a16712
40 changed files with 2041 additions and 653 deletions
|
|
@ -1,7 +1,6 @@
|
|||
use crate::program;
|
||||
use crate::{program, triangle};
|
||||
use crate::quad;
|
||||
use crate::text;
|
||||
use crate::triangle;
|
||||
use crate::{Settings, Transformation, Viewport};
|
||||
|
||||
use iced_graphics::backend;
|
||||
|
|
@ -100,16 +99,16 @@ impl Backend {
|
|||
);
|
||||
}
|
||||
|
||||
if !layer.meshes.is_empty() {
|
||||
if !layer.meshes.0.is_empty() {
|
||||
let scaled = transformation
|
||||
* Transformation::scale(scale_factor, scale_factor);
|
||||
|
||||
self.triangle_pipeline.draw(
|
||||
&layer.meshes,
|
||||
gl,
|
||||
target_height,
|
||||
scaled,
|
||||
scale_factor,
|
||||
&layer.meshes,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
48
glow/src/shader/common/gradient.frag
Normal file
48
glow/src/shader/common/gradient.frag
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// GLSL does not support dynamically sized arrays without SSBOs
|
||||
#define MAX_STOPS 64
|
||||
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp float;
|
||||
#else
|
||||
precision mediump float;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HIGHER_THAN_300
|
||||
layout (location = 0) out vec4 fragColor;
|
||||
#define gl_FragColor fragColor
|
||||
#endif
|
||||
|
||||
in vec2 raw_position;
|
||||
|
||||
uniform vec2 gradient_start;
|
||||
uniform vec2 gradient_end;
|
||||
|
||||
uniform uint color_stops_size;
|
||||
uniform float color_stop_offsets[MAX_STOPS];
|
||||
uniform vec4 color_stop_colors[MAX_STOPS];
|
||||
|
||||
void main() {
|
||||
vec2 gradient_vec = vec2(gradient_end - gradient_start);
|
||||
vec2 current_vec = vec2(raw_position.xy - gradient_start);
|
||||
vec2 unit = normalize(gradient_vec);
|
||||
float coord_offset = dot(unit, current_vec) / length(gradient_vec);
|
||||
|
||||
for (uint i = 0; i < color_stops_size - 1; i++) {
|
||||
float stop_offset = color_stop_offsets[i];
|
||||
float next_stop_offset = color_stop_offsets[i + 1];
|
||||
|
||||
if (stop_offset <= coord_offset && coord_offset <= next_stop_offset) {
|
||||
fragColor = mix(color_stop_colors[i], color_stop_colors[i+1], smoothstep(
|
||||
stop_offset,
|
||||
next_stop_offset,
|
||||
coord_offset
|
||||
));
|
||||
} else if (coord_offset < color_stop_offsets[0]) {
|
||||
fragColor = color_stop_colors[0];
|
||||
} else if (coord_offset > color_stop_offsets[color_stops_size - 1]) {
|
||||
fragColor = color_stop_colors[color_stops_size - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@ out vec4 fragColor;
|
|||
#define gl_FragColor fragColor
|
||||
#endif
|
||||
|
||||
in vec4 v_Color;
|
||||
uniform vec4 color;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = v_Color;
|
||||
fragColor = color;
|
||||
}
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
uniform mat4 u_Transform;
|
||||
|
||||
in vec2 i_Position;
|
||||
in vec4 i_Color;
|
||||
|
||||
out vec4 v_Color;
|
||||
out vec2 raw_position;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0);
|
||||
v_Color = i_Color;
|
||||
raw_position = i_Position;
|
||||
}
|
||||
|
|
@ -1,66 +1,41 @@
|
|||
//! Draw meshes of triangles.
|
||||
//! Draw meshes of triangle.
|
||||
mod gradient;
|
||||
mod solid;
|
||||
|
||||
use crate::program::{self, Shader};
|
||||
use crate::Transformation;
|
||||
use glow::HasContext;
|
||||
use iced_graphics::layer;
|
||||
use iced_graphics::layer::{Mesh, Meshes};
|
||||
use iced_graphics::shader;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::triangle::gradient::GradientProgram;
|
||||
use crate::triangle::solid::SolidProgram;
|
||||
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
|
||||
|
||||
const VERTEX_BUFFER_SIZE: usize = 10_000;
|
||||
const INDEX_BUFFER_SIZE: usize = 10_000;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Pipeline {
|
||||
program: <glow::Context as HasContext>::Program,
|
||||
vertex_array: <glow::Context as HasContext>::VertexArray,
|
||||
vertices: Buffer<Vertex2D>,
|
||||
indices: Buffer<u32>,
|
||||
transform_location: <glow::Context as HasContext>::UniformLocation,
|
||||
current_transform: Transformation,
|
||||
programs: TrianglePrograms,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TrianglePrograms {
|
||||
solid: TriangleProgram,
|
||||
gradient: TriangleProgram,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TriangleProgram {
|
||||
Solid(SolidProgram),
|
||||
Gradient(GradientProgram),
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
pub fn new(
|
||||
gl: &glow::Context,
|
||||
shader_version: &program::Version,
|
||||
) -> Pipeline {
|
||||
let program = unsafe {
|
||||
let vertex_shader = Shader::vertex(
|
||||
gl,
|
||||
shader_version,
|
||||
include_str!("shader/common/triangle.vert"),
|
||||
);
|
||||
let fragment_shader = Shader::fragment(
|
||||
gl,
|
||||
shader_version,
|
||||
include_str!("shader/common/triangle.frag"),
|
||||
);
|
||||
|
||||
program::create(
|
||||
gl,
|
||||
&[vertex_shader, fragment_shader],
|
||||
&[(0, "i_Position"), (1, "i_Color")],
|
||||
)
|
||||
};
|
||||
|
||||
let transform_location =
|
||||
unsafe { gl.get_uniform_location(program, "u_Transform") }
|
||||
.expect("Get transform location");
|
||||
|
||||
unsafe {
|
||||
gl.use_program(Some(program));
|
||||
|
||||
let transform: [f32; 16] = Transformation::identity().into();
|
||||
gl.uniform_matrix_4_f32_slice(
|
||||
Some(&transform_location),
|
||||
false,
|
||||
&transform,
|
||||
);
|
||||
|
||||
gl.use_program(None);
|
||||
}
|
||||
|
||||
pub fn new(gl: &glow::Context, shader_version: &program::Version) -> Self {
|
||||
let vertex_array =
|
||||
unsafe { gl.create_vertex_array().expect("Create vertex array") };
|
||||
|
||||
|
|
@ -73,7 +48,7 @@ impl Pipeline {
|
|||
gl,
|
||||
glow::ARRAY_BUFFER,
|
||||
glow::DYNAMIC_DRAW,
|
||||
VERTEX_BUFFER_SIZE,
|
||||
std::mem::size_of::<Vertex2D>() as usize,
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -82,7 +57,7 @@ impl Pipeline {
|
|||
gl,
|
||||
glow::ELEMENT_ARRAY_BUFFER,
|
||||
glow::DYNAMIC_DRAW,
|
||||
INDEX_BUFFER_SIZE,
|
||||
std::mem::size_of::<u32>() as usize,
|
||||
)
|
||||
};
|
||||
|
||||
|
|
@ -92,58 +67,45 @@ impl Pipeline {
|
|||
gl.enable_vertex_attrib_array(0);
|
||||
gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, stride, 0);
|
||||
|
||||
gl.enable_vertex_attrib_array(1);
|
||||
gl.vertex_attrib_pointer_f32(
|
||||
1,
|
||||
4,
|
||||
glow::FLOAT,
|
||||
false,
|
||||
stride,
|
||||
4 * 2,
|
||||
);
|
||||
|
||||
gl.bind_vertex_array(None);
|
||||
}
|
||||
};
|
||||
|
||||
Pipeline {
|
||||
program,
|
||||
Self {
|
||||
vertex_array,
|
||||
vertices,
|
||||
indices,
|
||||
transform_location,
|
||||
current_transform: Transformation::identity(),
|
||||
programs: TrianglePrograms {
|
||||
solid: TriangleProgram::Solid(SolidProgram::new(
|
||||
gl,
|
||||
shader_version,
|
||||
)),
|
||||
gradient: TriangleProgram::Gradient(GradientProgram::new(
|
||||
gl,
|
||||
shader_version,
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
meshes: &Meshes<'_>,
|
||||
gl: &glow::Context,
|
||||
target_height: u32,
|
||||
transformation: Transformation,
|
||||
scale_factor: f32,
|
||||
meshes: &[layer::Mesh<'_>],
|
||||
) {
|
||||
unsafe {
|
||||
gl.enable(glow::MULTISAMPLE);
|
||||
gl.enable(glow::SCISSOR_TEST);
|
||||
gl.use_program(Some(self.program));
|
||||
gl.bind_vertex_array(Some(self.vertex_array));
|
||||
gl.bind_vertex_array(Some(self.vertex_array))
|
||||
}
|
||||
|
||||
// This looks a bit crazy, but we are just counting how many vertices
|
||||
// and indices we will need to handle.
|
||||
// TODO: Improve readability
|
||||
let (total_vertices, total_indices) = meshes
|
||||
.iter()
|
||||
.map(|layer::Mesh { buffers, .. }| {
|
||||
(buffers.vertices.len(), buffers.indices.len())
|
||||
})
|
||||
.fold((0, 0), |(total_v, total_i), (v, i)| {
|
||||
(total_v + v, total_i + i)
|
||||
});
|
||||
//count the total number of vertices & indices we need to handle for all meshes
|
||||
let (total_vertices, total_indices) = meshes.attribute_count();
|
||||
|
||||
// Then we ensure the current buffers are big enough, resizing if
|
||||
// necessary
|
||||
// Then we ensure the current attribute buffers are big enough, resizing if necessary
|
||||
unsafe {
|
||||
self.vertices.bind(gl, total_vertices);
|
||||
self.indices.bind(gl, total_indices);
|
||||
|
|
@ -153,7 +115,7 @@ impl Pipeline {
|
|||
let mut last_vertex = 0;
|
||||
let mut last_index = 0;
|
||||
|
||||
for layer::Mesh { buffers, .. } in meshes {
|
||||
for Mesh { buffers, .. } in meshes.0.iter() {
|
||||
unsafe {
|
||||
gl.buffer_sub_data_u8_slice(
|
||||
glow::ARRAY_BUFFER,
|
||||
|
|
@ -176,11 +138,12 @@ impl Pipeline {
|
|||
let mut last_vertex = 0;
|
||||
let mut last_index = 0;
|
||||
|
||||
for layer::Mesh {
|
||||
for Mesh {
|
||||
buffers,
|
||||
origin,
|
||||
clip_bounds,
|
||||
} in meshes
|
||||
shader,
|
||||
} in meshes.0.iter()
|
||||
{
|
||||
let transform =
|
||||
transformation * Transformation::translate(origin.x, origin.y);
|
||||
|
|
@ -188,17 +151,6 @@ impl Pipeline {
|
|||
let clip_bounds = (*clip_bounds * scale_factor).snap();
|
||||
|
||||
unsafe {
|
||||
if self.current_transform != transform {
|
||||
let matrix: [f32; 16] = transform.into();
|
||||
gl.uniform_matrix_4_f32_slice(
|
||||
Some(&self.transform_location),
|
||||
false,
|
||||
&matrix,
|
||||
);
|
||||
|
||||
self.current_transform = transform;
|
||||
}
|
||||
|
||||
gl.scissor(
|
||||
clip_bounds.x as i32,
|
||||
(target_height - (clip_bounds.y + clip_bounds.height))
|
||||
|
|
@ -207,6 +159,15 @@ impl Pipeline {
|
|||
clip_bounds.height as i32,
|
||||
);
|
||||
|
||||
let t = if self.current_transform != transform {
|
||||
self.current_transform = transform;
|
||||
Some(transform)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.use_with_shader(gl, shader, t);
|
||||
|
||||
gl.draw_elements_base_vertex(
|
||||
glow::TRIANGLES,
|
||||
buffers.indices.len() as i32,
|
||||
|
|
@ -222,34 +183,79 @@ impl Pipeline {
|
|||
|
||||
unsafe {
|
||||
gl.bind_vertex_array(None);
|
||||
gl.use_program(None);
|
||||
gl.disable(glow::SCISSOR_TEST);
|
||||
gl.disable(glow::MULTISAMPLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Uniforms {
|
||||
transform: [f32; 16],
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Zeroable for Uniforms {}
|
||||
unsafe impl bytemuck::Pod for Uniforms {}
|
||||
|
||||
impl Default for Uniforms {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
transform: *Transformation::identity().as_ref(),
|
||||
fn use_with_shader(
|
||||
&mut self,
|
||||
gl: &glow::Context,
|
||||
shader: &shader::Shader,
|
||||
transform: Option<Transformation>,
|
||||
) {
|
||||
match shader {
|
||||
shader::Shader::Solid(color) => {
|
||||
if let TriangleProgram::Solid(solid_program) =
|
||||
&mut self.programs.solid
|
||||
{
|
||||
unsafe { gl.use_program(Some(solid_program.program)) }
|
||||
solid_program.set_uniforms(gl, color, transform);
|
||||
}
|
||||
}
|
||||
shader::Shader::Gradient(gradient) => {
|
||||
if let TriangleProgram::Gradient(gradient_program) =
|
||||
&mut self.programs.gradient
|
||||
{
|
||||
unsafe { gl.use_program(Some(gradient_program.program)) }
|
||||
gradient_program.set_uniforms(gl, gradient, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Transformation> for Uniforms {
|
||||
fn from(transformation: Transformation) -> Uniforms {
|
||||
Self {
|
||||
transform: transformation.into(),
|
||||
/// A simple shader program. Uses [`triangle.vert`] for its vertex shader and only binds position
|
||||
/// attribute location.
|
||||
pub(super) fn simple_triangle_program(
|
||||
gl: &glow::Context,
|
||||
shader_version: &program::Version,
|
||||
fragment_shader: &'static str,
|
||||
) -> <glow::Context as HasContext>::Program {
|
||||
unsafe {
|
||||
let vertex_shader = Shader::vertex(
|
||||
gl,
|
||||
shader_version,
|
||||
include_str!("shader/common/triangle.vert"),
|
||||
);
|
||||
|
||||
let fragment_shader =
|
||||
Shader::fragment(gl, shader_version, fragment_shader);
|
||||
|
||||
program::create(
|
||||
gl,
|
||||
&[vertex_shader, fragment_shader],
|
||||
&[(0, "i_Position")],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn update_transform(
|
||||
gl: &glow::Context,
|
||||
program: <glow::Context as HasContext>::Program,
|
||||
transform: Option<Transformation>
|
||||
) {
|
||||
if let Some(t) = transform {
|
||||
let transform_location =
|
||||
unsafe { gl.get_uniform_location(program, "u_Transform") }
|
||||
.expect("Get transform location.");
|
||||
|
||||
unsafe {
|
||||
gl.uniform_matrix_4_f32_slice(
|
||||
Some(&transform_location),
|
||||
false,
|
||||
t.as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
189
glow/src/triangle/gradient.rs
Normal file
189
glow/src/triangle/gradient.rs
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
use crate::program::Version;
|
||||
use crate::triangle::{simple_triangle_program, update_transform};
|
||||
use glow::{Context, HasContext, NativeProgram};
|
||||
use iced_graphics::gradient::Gradient;
|
||||
use iced_graphics::widget::canvas::gradient::Linear;
|
||||
use iced_graphics::Transformation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct GradientProgram {
|
||||
pub(super) program: <Context as HasContext>::Program,
|
||||
pub(super) uniform_data: GradientUniformData,
|
||||
}
|
||||
|
||||
impl GradientProgram {
|
||||
pub(super) fn new(gl: &Context, shader_version: &Version) -> Self {
|
||||
let program = simple_triangle_program(
|
||||
gl,
|
||||
shader_version,
|
||||
include_str!("../shader/common/gradient.frag"),
|
||||
);
|
||||
|
||||
Self {
|
||||
program,
|
||||
uniform_data: GradientUniformData::new(gl, program),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_uniforms<'a>(
|
||||
&mut self,
|
||||
gl: &Context,
|
||||
gradient: &Gradient,
|
||||
transform: Option<Transformation>,
|
||||
) {
|
||||
update_transform(gl, self.program, transform);
|
||||
|
||||
if &self.uniform_data.current_gradient != gradient {
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.uniform_data.current_gradient = gradient.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct GradientUniformData {
|
||||
current_gradient: Gradient,
|
||||
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],
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Clone)]
|
||||
struct ColorStopLocation {
|
||||
color: <Context as HasContext>::UniformLocation,
|
||||
offset: <Context as HasContext>::UniformLocation,
|
||||
}
|
||||
|
||||
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),
|
||||
)
|
||||
}
|
||||
.expect(&format!(
|
||||
"Gradient - Color stop offset with index {}",
|
||||
index
|
||||
));
|
||||
|
||||
let color = unsafe {
|
||||
gl.get_uniform_location(
|
||||
program,
|
||||
&format!("color_stop_colors[{}]", index),
|
||||
)
|
||||
}
|
||||
.expect(&format!(
|
||||
"Gradient - Color stop colors with index {}",
|
||||
index
|
||||
));
|
||||
|
||||
ColorStopLocation { color, offset }
|
||||
});
|
||||
|
||||
GradientUniformData {
|
||||
current_gradient: Gradient::Linear(Linear {
|
||||
start: Default::default(),
|
||||
end: Default::default(),
|
||||
color_stops: vec![],
|
||||
}),
|
||||
uniform_locations: GradientUniformLocations {
|
||||
gradient_start_location,
|
||||
gradient_end_location,
|
||||
color_stops_size_location,
|
||||
color_stops_locations,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
67
glow/src/triangle/solid.rs
Normal file
67
glow/src/triangle/solid.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use crate::program::Version;
|
||||
use crate::triangle::{simple_triangle_program, update_transform};
|
||||
use crate::Color;
|
||||
use glow::{Context, HasContext, NativeProgram};
|
||||
use iced_graphics::Transformation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SolidProgram {
|
||||
pub(crate) program: <Context as HasContext>::Program,
|
||||
pub(crate) uniform_data: SolidUniformData,
|
||||
}
|
||||
|
||||
impl SolidProgram {
|
||||
pub fn new(gl: &Context, shader_version: &Version) -> Self {
|
||||
let program = simple_triangle_program(
|
||||
gl,
|
||||
shader_version,
|
||||
include_str!("../shader/common/triangle.frag"),
|
||||
);
|
||||
|
||||
Self {
|
||||
program,
|
||||
uniform_data: SolidUniformData::new(gl, program),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_uniforms<'a>(
|
||||
&mut self,
|
||||
gl: &Context,
|
||||
color: &Color,
|
||||
transform: Option<Transformation>,
|
||||
) {
|
||||
update_transform(gl, self.program, transform);
|
||||
|
||||
if &self.uniform_data.color != color {
|
||||
unsafe {
|
||||
gl.uniform_4_f32(
|
||||
Some(&self.uniform_data.color_location),
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a,
|
||||
);
|
||||
}
|
||||
|
||||
self.uniform_data.color = *color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct SolidUniformData {
|
||||
pub color: Color,
|
||||
pub color_location: <Context as HasContext>::UniformLocation,
|
||||
}
|
||||
|
||||
impl SolidUniformData {
|
||||
fn new(gl: &Context, program: NativeProgram) -> Self {
|
||||
Self {
|
||||
color: Color::TRANSPARENT,
|
||||
color_location: unsafe {
|
||||
gl.get_uniform_location(program, "color")
|
||||
}
|
||||
.expect("Solid - Color uniform location."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,8 +26,7 @@ impl<Theme> iced_graphics::window::GLCompositor for Compositor<Theme> {
|
|||
log::info!("{:#?}", settings);
|
||||
|
||||
let version = gl.version();
|
||||
log::info!("Version: {:?}", version);
|
||||
log::info!("Embedded: {}", version.is_embedded);
|
||||
log::info!("OpenGL version: {:?} (Embedded: {}", version, version.is_embedded);
|
||||
|
||||
let renderer = gl.get_parameter_string(glow::RENDERER);
|
||||
log::info!("Renderer: {}", renderer);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue