From 40f45d7b7e35dd4937abe6b5ce16b6256b4f1eeb Mon Sep 17 00:00:00 2001 From: shan Date: Thu, 29 Sep 2022 10:52:58 -0700 Subject: Adds linear gradient support to 2D meshes in the canvas widget. --- glow/src/backend.rs | 7 +- glow/src/shader/common/gradient.frag | 48 ++++++++ glow/src/shader/common/triangle.frag | 4 +- glow/src/shader/common/triangle.vert | 6 +- glow/src/triangle.rs | 228 ++++++++++++++++++----------------- glow/src/triangle/gradient.rs | 189 +++++++++++++++++++++++++++++ glow/src/triangle/solid.rs | 67 ++++++++++ glow/src/window/compositor.rs | 3 +- 8 files changed, 429 insertions(+), 123 deletions(-) create mode 100644 glow/src/shader/common/gradient.frag create mode 100644 glow/src/triangle/gradient.rs create mode 100644 glow/src/triangle/solid.rs (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 78d4229e..6fc4fb38 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -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, ); } diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag new file mode 100644 index 00000000..588f63e0 --- /dev/null +++ b/glow/src/shader/common/gradient.frag @@ -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]; + } + } +} \ No newline at end of file diff --git a/glow/src/shader/common/triangle.frag b/glow/src/shader/common/triangle.frag index e8689f2e..0ee65239 100644 --- a/glow/src/shader/common/triangle.frag +++ b/glow/src/shader/common/triangle.frag @@ -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; } \ No newline at end of file diff --git a/glow/src/shader/common/triangle.vert b/glow/src/shader/common/triangle.vert index d0494a5f..09a4e324 100644 --- a/glow/src/shader/common/triangle.vert +++ b/glow/src/shader/common/triangle.vert @@ -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; } \ No newline at end of file diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index ae4f83ef..7d0e14c7 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -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: ::Program, vertex_array: ::VertexArray, vertices: Buffer, indices: Buffer, - transform_location: ::UniformLocation, current_transform: Transformation, + programs: TrianglePrograms, } -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, - ); +#[derive(Debug)] +struct TrianglePrograms { + solid: TriangleProgram, + gradient: TriangleProgram, +} - gl.use_program(None); - } +#[derive(Debug)] +enum TriangleProgram { + Solid(SolidProgram), + Gradient(GradientProgram), +} +impl Pipeline { + 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::() as usize, ) }; @@ -82,7 +57,7 @@ impl Pipeline { gl, glow::ELEMENT_ARRAY_BUFFER, glow::DYNAMIC_DRAW, - INDEX_BUFFER_SIZE, + std::mem::size_of::() 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) - }); - - // Then we ensure the current buffers are big enough, resizing if - // necessary + //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 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], + fn use_with_shader( + &mut self, + gl: &glow::Context, + shader: &shader::Shader, + transform: Option, + ) { + 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); + } + } + } + } } -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(), - } +/// 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, +) -> ::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")], + ) } } -impl From for Uniforms { - fn from(transformation: Transformation) -> Uniforms { - Self { - transform: transformation.into(), +pub(super) fn update_transform( + gl: &glow::Context, + program: ::Program, + transform: Option +) { + 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(), + ); } } } diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs new file mode 100644 index 00000000..d1b10d77 --- /dev/null +++ b/glow/src/triangle/gradient.rs @@ -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: ::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, + ) { + 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: ::UniformLocation, + gradient_end_location: ::UniformLocation, + color_stops_size_location: ::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: ::UniformLocation, + offset: ::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, + }, + } + } +} diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs new file mode 100644 index 00000000..3a33cea8 --- /dev/null +++ b/glow/src/triangle/solid.rs @@ -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: ::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, + ) { + 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: ::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."), + } + } +} diff --git a/glow/src/window/compositor.rs b/glow/src/window/compositor.rs index f6afaa68..e9cf6015 100644 --- a/glow/src/window/compositor.rs +++ b/glow/src/window/compositor.rs @@ -26,8 +26,7 @@ impl iced_graphics::window::GLCompositor for Compositor { 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); -- cgit From e25f3d3dea2d2c1ba7d2778948443df2745084be Mon Sep 17 00:00:00 2001 From: shan Date: Thu, 29 Sep 2022 17:13:32 -0700 Subject: Fixed issue where OpenGL would not render both shaders at once under certain circumstances. --- glow/src/triangle.rs | 52 ++++++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 30 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 7d0e14c7..85d873fe 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -24,14 +24,8 @@ pub(crate) struct Pipeline { #[derive(Debug)] struct TrianglePrograms { - solid: TriangleProgram, - gradient: TriangleProgram, -} - -#[derive(Debug)] -enum TriangleProgram { - Solid(SolidProgram), - Gradient(GradientProgram), + solid: SolidProgram, + gradient: GradientProgram, } impl Pipeline { @@ -76,14 +70,8 @@ impl Pipeline { indices, current_transform: Transformation::identity(), programs: TrianglePrograms { - solid: TriangleProgram::Solid(SolidProgram::new( - gl, - shader_version, - )), - gradient: TriangleProgram::Gradient(GradientProgram::new( - gl, - shader_version, - )), + solid: SolidProgram::new(gl, shader_version), + gradient: GradientProgram::new(gl, shader_version), }, } } @@ -138,16 +126,21 @@ impl Pipeline { let mut last_vertex = 0; let mut last_index = 0; - for Mesh { + for (index, Mesh { buffers, origin, clip_bounds, shader, - } in meshes.0.iter() + }) in meshes.0.iter().enumerate() { let transform = transformation * Transformation::translate(origin.x, origin.y); + if index == 0 { + //set initial transform uniform for both programs + self.programs.set_transforms(gl, transform); + } + let clip_bounds = (*clip_bounds * scale_factor).snap(); unsafe { @@ -196,25 +189,24 @@ impl Pipeline { ) { 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); - } + unsafe { gl.use_program(Some(self.programs.solid.program)) } + self.programs.solid.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); - } + unsafe { gl.use_program(Some(self.programs.gradient.program)) } + self.programs.gradient.set_uniforms(gl, gradient, transform); } } } } +impl TrianglePrograms { + pub fn set_transforms(&self, gl: &glow::Context, transform: Transformation) { + update_transform(gl, self.solid.program, Some(transform)); + update_transform(gl, self.gradient.program, Some(transform)); + } +} + /// A simple shader program. Uses [`triangle.vert`] for its vertex shader and only binds position /// attribute location. pub(super) fn simple_triangle_program( -- cgit From 6e7b3ced0b1daf368e44e181ecdb4ae529877eb6 Mon Sep 17 00:00:00 2001 From: shan Date: Tue, 4 Oct 2022 18:24:46 -0700 Subject: Reworked wgpu buffers, updated glow side to have proper transform location storage, attempting to fix visibility modifiers, implemented some of the feedback received in initial PR. --- glow/src/backend.rs | 2 +- glow/src/shader/common/gradient.frag | 1 + glow/src/triangle.rs | 126 ++++++++++++----------------------- glow/src/triangle/gradient.rs | 92 ++++++++++++++----------- glow/src/triangle/solid.rs | 62 ++++++++++------- 5 files changed, 134 insertions(+), 149 deletions(-) (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 6fc4fb38..7333d513 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -99,7 +99,7 @@ impl Backend { ); } - if !layer.meshes.0.is_empty() { + if !layer.meshes.is_empty() { let scaled = transformation * Transformation::scale(scale_factor, scale_factor); diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index 588f63e0..1afb557d 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -23,6 +23,7 @@ uniform uint color_stops_size; uniform float color_stop_offsets[MAX_STOPS]; uniform vec4 color_stop_colors[MAX_STOPS]; +//TODO: rewrite without branching to make ALUs happy void main() { vec2 gradient_vec = vec2(gradient_end - gradient_start); vec2 current_vec = vec2(raw_position.xy - gradient_start); diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 85d873fe..f16f8af4 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -2,23 +2,22 @@ mod gradient; mod solid; -use crate::program::{self, Shader}; -use crate::Transformation; +use crate::{program, Transformation}; use glow::HasContext; -use iced_graphics::layer::{Mesh, Meshes}; +use iced_graphics::layer::{attribute_count_of, Mesh}; 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}; +use shader::Shader; #[derive(Debug)] pub(crate) struct Pipeline { vertex_array: ::VertexArray, vertices: Buffer, indices: Buffer, - current_transform: Transformation, programs: TrianglePrograms, } @@ -68,7 +67,6 @@ impl Pipeline { vertex_array, vertices, indices, - current_transform: Transformation::identity(), programs: TrianglePrograms { solid: SolidProgram::new(gl, shader_version), gradient: GradientProgram::new(gl, shader_version), @@ -78,7 +76,7 @@ impl Pipeline { pub fn draw( &mut self, - meshes: &Meshes<'_>, + meshes: &[Mesh<'_>], gl: &glow::Context, target_height: u32, transformation: Transformation, @@ -90,8 +88,8 @@ impl Pipeline { gl.bind_vertex_array(Some(self.vertex_array)) } - //count the total number of vertices & indices we need to handle for all meshes - let (total_vertices, total_indices) = meshes.attribute_count(); + //count the total amount of vertices & indices we need to handle + let (total_vertices, total_indices) = attribute_count_of(meshes); // Then we ensure the current attribute buffers are big enough, resizing if necessary unsafe { @@ -100,25 +98,25 @@ impl Pipeline { } // We upload all the vertices and indices upfront - let mut last_vertex = 0; - let mut last_index = 0; + let mut vertex_offset = 0; + let mut index_offset = 0; - for Mesh { buffers, .. } in meshes.0.iter() { + for mesh in meshes { unsafe { gl.buffer_sub_data_u8_slice( glow::ARRAY_BUFFER, - (last_vertex * std::mem::size_of::()) as i32, - bytemuck::cast_slice(&buffers.vertices), + (vertex_offset * std::mem::size_of::()) as i32, + bytemuck::cast_slice(&mesh.buffers.vertices), ); gl.buffer_sub_data_u8_slice( glow::ELEMENT_ARRAY_BUFFER, - (last_index * std::mem::size_of::()) as i32, - bytemuck::cast_slice(&buffers.indices), + (index_offset * std::mem::size_of::()) as i32, + bytemuck::cast_slice(&mesh.buffers.indices), ); - last_vertex += buffers.vertices.len(); - last_index += buffers.indices.len(); + vertex_offset += mesh.buffers.vertices.len(); + index_offset += mesh.buffers.indices.len(); } } @@ -126,22 +124,11 @@ impl Pipeline { let mut last_vertex = 0; let mut last_index = 0; - for (index, Mesh { - buffers, - origin, - clip_bounds, - shader, - }) in meshes.0.iter().enumerate() - { - let transform = - transformation * Transformation::translate(origin.x, origin.y); - - if index == 0 { - //set initial transform uniform for both programs - self.programs.set_transforms(gl, transform); - } + for mesh in meshes { + let transform = transformation + * Transformation::translate(mesh.origin.x, mesh.origin.y); - let clip_bounds = (*clip_bounds * scale_factor).snap(); + let clip_bounds = (mesh.clip_bounds * scale_factor).snap(); unsafe { gl.scissor( @@ -152,25 +139,25 @@ 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); + match mesh.shader { + Shader::Solid(color) => { + self.programs.solid.use_program(gl, &color, &transform); + } + Shader::Gradient(gradient) => { + self.programs.gradient.use_program(gl, &gradient, &transform); + } + } gl.draw_elements_base_vertex( glow::TRIANGLES, - buffers.indices.len() as i32, + mesh.buffers.indices.len() as i32, glow::UNSIGNED_INT, (last_index * std::mem::size_of::()) as i32, last_vertex as i32, ); - last_vertex += buffers.vertices.len(); - last_index += buffers.indices.len(); + last_vertex += mesh.buffers.vertices.len(); + last_index += mesh.buffers.indices.len(); } } @@ -180,31 +167,6 @@ impl Pipeline { gl.disable(glow::MULTISAMPLE); } } - - fn use_with_shader( - &mut self, - gl: &glow::Context, - shader: &shader::Shader, - transform: Option, - ) { - match shader { - shader::Shader::Solid(color) => { - unsafe { gl.use_program(Some(self.programs.solid.program)) } - self.programs.solid.set_uniforms(gl, color, transform); - } - shader::Shader::Gradient(gradient) => { - unsafe { gl.use_program(Some(self.programs.gradient.program)) } - self.programs.gradient.set_uniforms(gl, gradient, transform); - } - } - } -} - -impl TrianglePrograms { - pub fn set_transforms(&self, gl: &glow::Context, transform: Transformation) { - update_transform(gl, self.solid.program, Some(transform)); - update_transform(gl, self.gradient.program, Some(transform)); - } } /// A simple shader program. Uses [`triangle.vert`] for its vertex shader and only binds position @@ -215,14 +177,14 @@ pub(super) fn simple_triangle_program( fragment_shader: &'static str, ) -> ::Program { unsafe { - let vertex_shader = Shader::vertex( + let vertex_shader = program::Shader::vertex( gl, shader_version, include_str!("shader/common/triangle.vert"), ); let fragment_shader = - Shader::fragment(gl, shader_version, fragment_shader); + program::Shader::fragment(gl, shader_version, fragment_shader); program::create( gl, @@ -232,23 +194,17 @@ pub(super) fn simple_triangle_program( } } -pub(super) fn update_transform( +pub fn set_transform( gl: &glow::Context, - program: ::Program, - transform: Option + location: ::UniformLocation, + transform: 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(), - ); - } + unsafe { + gl.uniform_matrix_4_f32_slice( + Some(&location), + false, + transform.as_ref() + ); } } diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index d1b10d77..547871e2 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -1,18 +1,42 @@ use crate::program::Version; -use crate::triangle::{simple_triangle_program, update_transform}; +use crate::triangle::{simple_triangle_program, set_transform}; use glow::{Context, HasContext, NativeProgram}; +use iced_graphics::gradient::Linear; 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: ::Program, - pub(super) uniform_data: GradientUniformData, +pub struct GradientProgram { + pub program: ::Program, + pub uniform_data: GradientUniformData, +} + +#[derive(Debug)] +pub struct GradientUniformData { + gradient: Gradient, + transform: Transformation, + uniform_locations: GradientUniformLocations, +} + +#[derive(Debug)] +struct GradientUniformLocations { + gradient_start_location: ::UniformLocation, + gradient_end_location: ::UniformLocation, + color_stops_size_location: ::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: ::UniformLocation, +} + +#[derive(Copy, Debug, Clone)] +struct ColorStopLocation { + color: ::UniformLocation, + offset: ::UniformLocation, } impl GradientProgram { - pub(super) fn new(gl: &Context, shader_version: &Version) -> Self { + pub fn new(gl: &Context, shader_version: &Version) -> Self { let program = simple_triangle_program( gl, shader_version, @@ -25,15 +49,17 @@ impl GradientProgram { } } - pub(super) fn set_uniforms<'a>( + pub fn write_uniforms( &mut self, gl: &Context, gradient: &Gradient, - transform: Option, + transform: &Transformation, ) { - update_transform(gl, self.program, transform); + if transform != &self.uniform_data.transform { + set_transform(gl, self.uniform_data.uniform_locations.transform_location, *transform); + } - if &self.uniform_data.current_gradient != gradient { + if &self.uniform_data.gradient != gradient { match gradient { Gradient::Linear(linear) => { let gradient_start: [f32; 2] = (linear.start).into(); @@ -104,31 +130,17 @@ impl GradientProgram { } } - self.uniform_data.current_gradient = gradient.clone(); + self.uniform_data.gradient = gradient.clone(); } } -} - -#[derive(Debug)] -pub(super) struct GradientUniformData { - current_gradient: Gradient, - uniform_locations: GradientUniformLocations, -} -#[derive(Debug)] -struct GradientUniformLocations { - gradient_start_location: ::UniformLocation, - gradient_end_location: ::UniformLocation, - color_stops_size_location: ::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], -} + pub fn use_program(&mut self, gl: &glow::Context, gradient: &Gradient, transform: &Transformation) { + unsafe { + gl.use_program(Some(self.program)) + } -#[derive(Copy, Debug, Clone)] -struct ColorStopLocation { - color: ::UniformLocation, - offset: ::UniformLocation, + self.write_uniforms(gl, gradient, transform); + } } impl GradientUniformData { @@ -153,10 +165,7 @@ impl GradientUniformData { &format!("color_stop_offsets[{}]", index), ) } - .expect(&format!( - "Gradient - Color stop offset with index {}", - index - )); + .expect("Gradient - Color stop offset location."); let color = unsafe { gl.get_uniform_location( @@ -164,25 +173,28 @@ impl GradientUniformData { &format!("color_stop_colors[{}]", index), ) } - .expect(&format!( - "Gradient - Color stop colors with index {}", - index - )); + .expect("Gradient - Color stop color location."); ColorStopLocation { color, offset } }); + let transform_location = + unsafe { gl.get_uniform_location(program, "u_Transform") } + .expect("Get transform location."); + GradientUniformData { - current_gradient: Gradient::Linear(Linear { + gradient: Gradient::Linear(Linear { start: Default::default(), end: Default::default(), color_stops: vec![], }), + transform: Transformation::identity(), uniform_locations: GradientUniformLocations { gradient_start_location, gradient_end_location, color_stops_size_location, color_stops_locations, + transform_location, }, } } diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs index 3a33cea8..d5b73eb9 100644 --- a/glow/src/triangle/solid.rs +++ b/glow/src/triangle/solid.rs @@ -1,13 +1,38 @@ use crate::program::Version; -use crate::triangle::{simple_triangle_program, update_transform}; +use crate::triangle::{set_transform, simple_triangle_program}; use crate::Color; use glow::{Context, HasContext, NativeProgram}; use iced_graphics::Transformation; #[derive(Debug)] pub struct SolidProgram { - pub(crate) program: ::Program, - pub(crate) uniform_data: SolidUniformData, + program: ::Program, + uniform_data: SolidUniformData, +} + +#[derive(Debug)] +pub(crate) struct SolidUniformData { + pub color: Color, + pub color_location: ::UniformLocation, + pub transform: Transformation, + pub transform_location: ::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."), + transform: Transformation::identity(), + transform_location: unsafe { + gl.get_uniform_location(program, "u_Transform") + } + .expect("Get transform location."), + } + } } impl SolidProgram { @@ -24,15 +49,17 @@ impl SolidProgram { } } - pub fn set_uniforms<'a>( + pub fn write_uniforms( &mut self, gl: &Context, color: &Color, - transform: Option, + transform: &Transformation, ) { - update_transform(gl, self.program, transform); + if transform != &self.uniform_data.transform { + set_transform(gl, self.uniform_data.transform_location, *transform) + } - if &self.uniform_data.color != color { + if color != &self.uniform_data.color { unsafe { gl.uniform_4_f32( Some(&self.uniform_data.color_location), @@ -46,22 +73,11 @@ impl SolidProgram { self.uniform_data.color = *color; } } -} - -#[derive(Debug)] -pub(crate) struct SolidUniformData { - pub color: Color, - pub color_location: ::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."), + pub fn use_program(&mut self, gl: &glow::Context, color: &Color, transform: &Transformation) { + unsafe { + gl.use_program(Some(self.program)) } + self.write_uniforms(gl, color, transform) } -} +} \ No newline at end of file -- cgit From 30432cbade3d9b25c4df62656a7494db3f4ea82a Mon Sep 17 00:00:00 2001 From: shan Date: Wed, 5 Oct 2022 10:49:58 -0700 Subject: Readjusted namespaces, removed Geometry example as it's no longer relevant. --- glow/src/triangle.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index f16f8af4..5e58f4e4 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -5,13 +5,13 @@ mod solid; use crate::{program, Transformation}; use glow::HasContext; use iced_graphics::layer::{attribute_count_of, Mesh}; -use iced_graphics::shader; use std::marker::PhantomData; +use iced_graphics::layer; use crate::triangle::gradient::GradientProgram; use crate::triangle::solid::SolidProgram; pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; -use shader::Shader; +use layer::mesh; #[derive(Debug)] pub(crate) struct Pipeline { @@ -139,11 +139,11 @@ impl Pipeline { clip_bounds.height as i32, ); - match mesh.shader { - Shader::Solid(color) => { + match mesh.style { + mesh::Style::Solid(color) => { self.programs.solid.use_program(gl, &color, &transform); } - Shader::Gradient(gradient) => { + mesh::Style::Gradient(gradient) => { self.programs.gradient.use_program(gl, &gradient, &transform); } } -- cgit From 1eb8d972ba60592da7bfc27fe7ec80138e64dd7b Mon Sep 17 00:00:00 2001 From: shan Date: Wed, 5 Oct 2022 16:07:43 -0700 Subject: Reduced memory transfer of OpenGL gradient uniform upload. Rearranged gradient uniforms on OpenGL side to be more performant. --- glow/src/quad/compatibility.rs | 6 +- glow/src/quad/core.rs | 6 +- glow/src/shader/common/gradient.frag | 43 ++++++----- glow/src/triangle/gradient.rs | 143 +++++++++++++---------------------- 4 files changed, 77 insertions(+), 121 deletions(-) (limited to 'glow') diff --git a/glow/src/quad/compatibility.rs b/glow/src/quad/compatibility.rs index eb3fb7e0..28a5ea7c 100644 --- a/glow/src/quad/compatibility.rs +++ b/glow/src/quad/compatibility.rs @@ -70,11 +70,10 @@ impl Pipeline { unsafe { gl.use_program(Some(program)); - let matrix: [f32; 16] = Transformation::identity().into(); gl.uniform_matrix_4_f32_slice( Some(&transform_location), false, - &matrix, + Transformation::identity().as_ref(), ); gl.uniform_1_f32(Some(&scale_location), 1.0); @@ -139,11 +138,10 @@ impl Pipeline { if transformation != self.current_transform { unsafe { - let matrix: [f32; 16] = transformation.into(); gl.uniform_matrix_4_f32_slice( Some(&self.transform_location), false, - &matrix, + transformation.as_ref(), ); self.current_transform = transformation; diff --git a/glow/src/quad/core.rs b/glow/src/quad/core.rs index 3e51b1ca..16bec385 100644 --- a/glow/src/quad/core.rs +++ b/glow/src/quad/core.rs @@ -65,11 +65,10 @@ impl Pipeline { unsafe { gl.use_program(Some(program)); - let matrix: [f32; 16] = Transformation::identity().into(); gl.uniform_matrix_4_f32_slice( Some(&transform_location), false, - &matrix, + Transformation::identity().as_ref(), ); gl.uniform_1_f32(Some(&scale_location), 1.0); @@ -119,11 +118,10 @@ impl Pipeline { if transformation != self.current_transform { unsafe { - let matrix: [f32; 16] = transformation.into(); gl.uniform_matrix_4_f32_slice( Some(&self.transform_location), false, - &matrix, + transformation.as_ref(), ); self.current_transform = transformation; diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index 1afb557d..89d2d398 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -1,6 +1,3 @@ -// GLSL does not support dynamically sized arrays without SSBOs -#define MAX_STOPS 64 - #ifdef GL_ES #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; @@ -16,34 +13,38 @@ layout (location = 0) out vec4 fragColor; in vec2 raw_position; -uniform vec2 gradient_start; -uniform vec2 gradient_end; - +uniform vec4 gradient_direction; uniform uint color_stops_size; -uniform float color_stop_offsets[MAX_STOPS]; -uniform vec4 color_stop_colors[MAX_STOPS]; +// GLSL does not support dynamically sized arrays without SSBOs so this is capped to 16 stops +//stored as color(vec4) -> offset(vec4) sequentially; +uniform vec4 color_stops[32]; //TODO: rewrite without branching to make ALUs happy void main() { - vec2 gradient_vec = vec2(gradient_end - gradient_start); - vec2 current_vec = vec2(raw_position.xy - gradient_start); + vec2 start = gradient_direction.xy; + vec2 end = gradient_direction.zw; + vec2 gradient_vec = vec2(end - start); + vec2 current_vec = vec2(raw_position.xy - 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]; + for (uint i = 0; i < color_stops_size - 2; i += 2) { + vec4 color = color_stops[i]; + float offset = color_stops[i+1].x; + + vec4 next_color = color_stops[i+2]; + float next_offset = color_stops[i+3].x; - 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, + if (offset <= coord_offset && coord_offset <= next_offset) { + fragColor = mix(color, next_color, smoothstep( + offset, + next_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]; + } else if (coord_offset < color_stops[1].x) { + fragColor = color_stops[0]; + } else if (coord_offset > color_stops[color_stops_size - 1].x) { + fragColor = color_stops[color_stops_size - 2]; } } } \ No newline at end of file diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index 547871e2..4b157890 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -1,8 +1,8 @@ use crate::program::Version; -use crate::triangle::{simple_triangle_program, set_transform}; +use crate::triangle::{set_transform, simple_triangle_program}; use glow::{Context, HasContext, NativeProgram}; -use iced_graphics::gradient::Linear; use iced_graphics::gradient::Gradient; +use iced_graphics::gradient::Linear; use iced_graphics::Transformation; #[derive(Debug)] @@ -20,21 +20,14 @@ pub struct GradientUniformData { #[derive(Debug)] struct GradientUniformLocations { - gradient_start_location: ::UniformLocation, - gradient_end_location: ::UniformLocation, + gradient_direction_location: ::UniformLocation, color_stops_size_location: ::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], + color_stops_location: ::UniformLocation, transform_location: ::UniformLocation, } -#[derive(Copy, Debug, Clone)] -struct ColorStopLocation { - color: ::UniformLocation, - offset: ::UniformLocation, -} - impl GradientProgram { pub fn new(gl: &Context, shader_version: &Version) -> Self { let program = simple_triangle_program( @@ -56,76 +49,60 @@ impl GradientProgram { transform: &Transformation, ) { if transform != &self.uniform_data.transform { - set_transform(gl, self.uniform_data.uniform_locations.transform_location, *transform); + set_transform( + gl, + self.uniform_data.uniform_locations.transform_location, + *transform, + ); } if &self.uniform_data.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( + gl.uniform_4_f32( Some( - &self - .uniform_data - .uniform_locations - .gradient_start_location, + &self.uniform_data.uniform_locations.gradient_direction_location ), - gradient_start[0], - gradient_start[1], + linear.start.x, + linear.start.y, + linear.end.x, + linear.end.y ); - gl.uniform_2_f32( + gl.uniform_1_u32( Some( &self .uniform_data .uniform_locations - .gradient_end_location, + .color_stops_size_location, ), - gradient_end[0], - gradient_end[1], + (linear.color_stops.len() * 2) as u32, ); - gl.uniform_1_u32( + 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( Some( &self .uniform_data .uniform_locations - .color_stops_size_location, + .color_stops_location, ), - linear.color_stops.len() as u32, + &stops, ); - - 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, - ); - } } } } @@ -134,10 +111,13 @@ impl GradientProgram { } } - pub fn use_program(&mut self, gl: &glow::Context, gradient: &Gradient, transform: &Transformation) { - unsafe { - gl.use_program(Some(self.program)) - } + 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); } @@ -145,38 +125,18 @@ impl GradientProgram { 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 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_locations: [ColorStopLocation; 64] = - core::array::from_fn(|index| { - let offset = unsafe { - gl.get_uniform_location( - program, - &format!("color_stop_offsets[{}]", index), - ) - } - .expect("Gradient - Color stop offset location."); - - let color = unsafe { - gl.get_uniform_location( - program, - &format!("color_stop_colors[{}]", index), - ) - } - .expect("Gradient - Color stop color location."); - - ColorStopLocation { color, offset } - }); + 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") } @@ -190,10 +150,9 @@ impl GradientUniformData { }), transform: Transformation::identity(), uniform_locations: GradientUniformLocations { - gradient_start_location, - gradient_end_location, + gradient_direction_location, color_stops_size_location, - color_stops_locations, + color_stops_location, transform_location, }, } -- cgit From cb7c4676543cd508dfae8d4dcbd9cc8b61b1a94e Mon Sep 17 00:00:00 2001 From: shan Date: Thu, 6 Oct 2022 07:28:05 -0700 Subject: Fixed lint issues & cleaned up some documentation. --- glow/src/shader/common/gradient.frag | 2 +- glow/src/shader/common/triangle.frag | 2 +- glow/src/shader/common/triangle.vert | 2 +- glow/src/triangle.rs | 2 +- glow/src/triangle/solid.rs | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'glow') diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index 89d2d398..ade9c4a1 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -47,4 +47,4 @@ void main() { fragColor = color_stops[color_stops_size - 2]; } } -} \ No newline at end of file +} diff --git a/glow/src/shader/common/triangle.frag b/glow/src/shader/common/triangle.frag index 0ee65239..ead40fe5 100644 --- a/glow/src/shader/common/triangle.frag +++ b/glow/src/shader/common/triangle.frag @@ -15,4 +15,4 @@ uniform vec4 color; void main() { fragColor = color; -} \ No newline at end of file +} diff --git a/glow/src/shader/common/triangle.vert b/glow/src/shader/common/triangle.vert index 09a4e324..fe505997 100644 --- a/glow/src/shader/common/triangle.vert +++ b/glow/src/shader/common/triangle.vert @@ -6,4 +6,4 @@ out vec2 raw_position; void main() { gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0); raw_position = i_Position; -} \ No newline at end of file +} diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 5e58f4e4..f26d1cea 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -1,4 +1,4 @@ -//! Draw meshes of triangle. +//! Draw meshes of triangles. mod gradient; mod solid; diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs index d5b73eb9..3d4d1968 100644 --- a/glow/src/triangle/solid.rs +++ b/glow/src/triangle/solid.rs @@ -11,7 +11,7 @@ pub struct SolidProgram { } #[derive(Debug)] -pub(crate) struct SolidUniformData { +struct SolidUniformData { pub color: Color, pub color_location: ::UniformLocation, pub transform: Transformation, @@ -74,10 +74,10 @@ impl SolidProgram { } } - pub fn use_program(&mut self, gl: &glow::Context, color: &Color, transform: &Transformation) { + 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) } -} \ No newline at end of file +} -- cgit From f9a6efcaa03728f43aaa105af8936c1ed4778388 Mon Sep 17 00:00:00 2001 From: shan Date: Thu, 6 Oct 2022 19:41:00 -0700 Subject: Fixed some more imports/documentation. --- glow/src/triangle/gradient.rs | 5 ++--- glow/src/triangle/solid.rs | 15 +++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index 4b157890..a8bb5ec5 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -22,8 +22,7 @@ pub struct GradientUniformData { struct GradientUniformLocations { gradient_direction_location: ::UniformLocation, color_stops_size_location: ::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 + //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1 color_stops_location: ::UniformLocation, transform_location: ::UniformLocation, } @@ -140,7 +139,7 @@ impl GradientUniformData { let transform_location = unsafe { gl.get_uniform_location(program, "u_Transform") } - .expect("Get transform location."); + .expect("Gradient - Get u_Transform."); GradientUniformData { gradient: Gradient::Linear(Linear { diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs index 3d4d1968..5ba7f91c 100644 --- a/glow/src/triangle/solid.rs +++ b/glow/src/triangle/solid.rs @@ -25,12 +25,12 @@ impl SolidUniformData { color_location: unsafe { gl.get_uniform_location(program, "color") } - .expect("Solid - Color uniform location."), + .expect("Solid - Get color."), transform: Transformation::identity(), transform_location: unsafe { gl.get_uniform_location(program, "u_Transform") } - .expect("Get transform location."), + .expect("Solid - Get u_Transform."), } } } @@ -74,10 +74,13 @@ impl SolidProgram { } } - pub fn use_program(&mut self, gl: &Context, color: &Color, transform: &Transformation) { - unsafe { - gl.use_program(Some(self.program)) - } + 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) } } -- cgit From 12a87c54eb68b992676060c80e518ffb29445cfc Mon Sep 17 00:00:00 2001 From: shan Date: Fri, 7 Oct 2022 11:41:50 -0700 Subject: Added support for relative positioning of gradient fills. Addressed some PR feedback. --- glow/src/shader/common/gradient.frag | 3 +++ 1 file changed, 3 insertions(+) (limited to 'glow') diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index ade9c4a1..3c701af7 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -45,6 +45,9 @@ void main() { fragColor = color_stops[0]; } else if (coord_offset > color_stops[color_stops_size - 1].x) { fragColor = color_stops[color_stops_size - 2]; + } else { + //This use case can happen if a gradient's start & end position are the same + fragColor = vec4(0.0, 0.0, 0.0, 0.0); } } } -- cgit From 87371ce93411ba900c83cd8230a5814b59092c4b Mon Sep 17 00:00:00 2001 From: shan Date: Fri, 7 Oct 2022 13:06:06 -0700 Subject: Fixed an edge case where when gradient start/end are identical the GL fragment shader was not choosing the appropriate color. --- glow/src/shader/common/gradient.frag | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'glow') diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index 3c701af7..82c7e251 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -27,27 +27,33 @@ void main() { vec2 current_vec = vec2(raw_position.xy - start); vec2 unit = normalize(gradient_vec); float coord_offset = dot(unit, current_vec) / length(gradient_vec); + //if a gradient has a start/end stop that is identical, the mesh will have a transparent fill + fragColor = vec4(0.0, 0.0, 0.0, 0.0); - for (uint i = 0; i < color_stops_size - 2; i += 2) { - vec4 color = color_stops[i]; - float offset = color_stops[i+1].x; + float min_offset = color_stops[1].x; + float max_offset = color_stops[color_stops_size - 1].x; - vec4 next_color = color_stops[i+2]; + for (uint i = 0; i < color_stops_size - 2; i += 2) { + float curr_offset = color_stops[i+1].x; float next_offset = color_stops[i+3].x; - if (offset <= coord_offset && coord_offset <= next_offset) { - fragColor = mix(color, next_color, smoothstep( - offset, + if (coord_offset <= min_offset) { + //current coordinate is before the first defined offset, set it to the start color + fragColor = color_stops[0]; + } + + if (curr_offset <= coord_offset && coord_offset <= next_offset) { + //current fragment is between the current offset processing & the next one, interpolate colors + fragColor = mix(color_stops[i], color_stops[i+2], smoothstep( + curr_offset, next_offset, coord_offset )); - } else if (coord_offset < color_stops[1].x) { - fragColor = color_stops[0]; - } else if (coord_offset > color_stops[color_stops_size - 1].x) { + } + + if (coord_offset >= max_offset) { + //current coordinate is before the last defined offset, set it to the last color fragColor = color_stops[color_stops_size - 2]; - } else { - //This use case can happen if a gradient's start & end position are the same - fragColor = vec4(0.0, 0.0, 0.0, 0.0); } } } -- cgit From 215e6c95be7370bdd29c75b904463f06f942b7c0 Mon Sep 17 00:00:00 2001 From: shan Date: Fri, 7 Oct 2022 13:21:32 -0700 Subject: More import adjusting. --- glow/src/triangle.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index f26d1cea..f7fe9235 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -4,14 +4,12 @@ mod solid; use crate::{program, Transformation}; use glow::HasContext; -use iced_graphics::layer::{attribute_count_of, Mesh}; +use iced_graphics::layer::{mesh, mesh::attribute_count_of, Mesh}; use std::marker::PhantomData; -use iced_graphics::layer; use crate::triangle::gradient::GradientProgram; use crate::triangle::solid::SolidProgram; pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; -use layer::mesh; #[derive(Debug)] pub(crate) struct Pipeline { @@ -144,7 +142,9 @@ impl Pipeline { self.programs.solid.use_program(gl, &color, &transform); } mesh::Style::Gradient(gradient) => { - self.programs.gradient.use_program(gl, &gradient, &transform); + self.programs + .gradient + .use_program(gl, &gradient, &transform); } } @@ -203,7 +203,7 @@ pub fn set_transform( gl.uniform_matrix_4_f32_slice( Some(&location), false, - transform.as_ref() + transform.as_ref(), ); } } -- cgit From bb8d46a3fdf925b4b2fa9e7db76e48caf020b212 Mon Sep 17 00:00:00 2001 From: bungoboingo Date: Mon, 10 Oct 2022 20:55:43 -0700 Subject: Fixed fragment shader compatibility issues with GLES 3.0+ --- glow/src/shader/common/gradient.frag | 26 +++++++++++++------------- glow/src/window/compositor.rs | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'glow') diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index 82c7e251..42d0201f 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -1,14 +1,14 @@ #ifdef GL_ES -#ifdef GL_FRAGMENT_PRECISION_HIGH -precision highp float; -#else -precision mediump float; -#endif + #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 + layout (location = 0) out vec4 fragColor; + #define gl_FragColor fragColor #endif in vec2 raw_position; @@ -31,11 +31,11 @@ void main() { fragColor = vec4(0.0, 0.0, 0.0, 0.0); float min_offset = color_stops[1].x; - float max_offset = color_stops[color_stops_size - 1].x; + float max_offset = color_stops[color_stops_size - 1u].x; - for (uint i = 0; i < color_stops_size - 2; i += 2) { - float curr_offset = color_stops[i+1].x; - float next_offset = color_stops[i+3].x; + for (uint i = 0u; i < color_stops_size - 2u; i += 2u) { + float curr_offset = color_stops[i+1u].x; + float next_offset = color_stops[i+3u].x; if (coord_offset <= min_offset) { //current coordinate is before the first defined offset, set it to the start color @@ -44,7 +44,7 @@ void main() { if (curr_offset <= coord_offset && coord_offset <= next_offset) { //current fragment is between the current offset processing & the next one, interpolate colors - fragColor = mix(color_stops[i], color_stops[i+2], smoothstep( + fragColor = mix(color_stops[i], color_stops[i+2u], smoothstep( curr_offset, next_offset, coord_offset @@ -53,7 +53,7 @@ void main() { if (coord_offset >= max_offset) { //current coordinate is before the last defined offset, set it to the last color - fragColor = color_stops[color_stops_size - 2]; + fragColor = color_stops[color_stops_size - 2u]; } } } diff --git a/glow/src/window/compositor.rs b/glow/src/window/compositor.rs index e9cf6015..6459dbce 100644 --- a/glow/src/window/compositor.rs +++ b/glow/src/window/compositor.rs @@ -26,7 +26,7 @@ impl iced_graphics::window::GLCompositor for Compositor { log::info!("{:#?}", settings); let version = gl.version(); - log::info!("OpenGL version: {:?} (Embedded: {}", version, version.is_embedded); + log::info!("OpenGL version: {:?} (Embedded: {})", version, version.is_embedded); let renderer = gl.get_parameter_string(glow::RENDERER); log::info!("Renderer: {}", renderer); -- cgit From c4565759e4294540f54a81e4d91ddea7a769d3d4 Mon Sep 17 00:00:00 2001 From: bungoboingo Date: Tue, 18 Oct 2022 15:18:37 -0700 Subject: Cleaned up namespaces re: PR comments. --- glow/src/triangle.rs | 22 ++++++++++------------ glow/src/triangle/gradient.rs | 27 +++++++++++++-------------- glow/src/triangle/solid.rs | 23 +++++++++++++---------- 3 files changed, 36 insertions(+), 36 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index f7fe9235..fff14910 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -4,11 +4,9 @@ mod solid; use crate::{program, Transformation}; use glow::HasContext; -use iced_graphics::layer::{mesh, mesh::attribute_count_of, Mesh}; +use iced_graphics::layer::{mesh, Mesh}; use std::marker::PhantomData; -use crate::triangle::gradient::GradientProgram; -use crate::triangle::solid::SolidProgram; pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; #[derive(Debug)] @@ -16,13 +14,13 @@ pub(crate) struct Pipeline { vertex_array: ::VertexArray, vertices: Buffer, indices: Buffer, - programs: TrianglePrograms, + programs: ProgramList, } #[derive(Debug)] -struct TrianglePrograms { - solid: SolidProgram, - gradient: GradientProgram, +struct ProgramList { + solid: solid::Program, + gradient: gradient::Program, } impl Pipeline { @@ -65,9 +63,9 @@ impl Pipeline { vertex_array, vertices, indices, - programs: TrianglePrograms { - solid: SolidProgram::new(gl, shader_version), - gradient: GradientProgram::new(gl, shader_version), + programs: ProgramList { + solid: solid::Program::new(gl, shader_version), + gradient: gradient::Program::new(gl, shader_version), }, } } @@ -87,7 +85,7 @@ impl Pipeline { } //count the total amount of vertices & indices we need to handle - let (total_vertices, total_indices) = attribute_count_of(meshes); + let (total_vertices, total_indices) = mesh::attribute_count_of(meshes); // Then we ensure the current attribute buffers are big enough, resizing if necessary unsafe { @@ -171,7 +169,7 @@ impl Pipeline { /// A simple shader program. Uses [`triangle.vert`] for its vertex shader and only binds position /// attribute location. -pub(super) fn simple_triangle_program( +pub(super) fn program( gl: &glow::Context, shader_version: &program::Version, fragment_shader: &'static str, diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index a8bb5ec5..6bca44ee 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -1,25 +1,25 @@ use crate::program::Version; -use crate::triangle::{set_transform, simple_triangle_program}; +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 GradientProgram { +pub struct Program { pub program: ::Program, - pub uniform_data: GradientUniformData, + pub uniform_data: UniformData, } #[derive(Debug)] -pub struct GradientUniformData { +pub struct UniformData { gradient: Gradient, transform: Transformation, - uniform_locations: GradientUniformLocations, + uniform_locations: UniformLocations, } #[derive(Debug)] -struct GradientUniformLocations { +struct UniformLocations { gradient_direction_location: ::UniformLocation, color_stops_size_location: ::UniformLocation, //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1 @@ -27,9 +27,9 @@ struct GradientUniformLocations { transform_location: ::UniformLocation, } -impl GradientProgram { +impl Program { pub fn new(gl: &Context, shader_version: &Version) -> Self { - let program = simple_triangle_program( + let program = triangle::program( gl, shader_version, include_str!("../shader/common/gradient.frag"), @@ -37,7 +37,7 @@ impl GradientProgram { Self { program, - uniform_data: GradientUniformData::new(gl, program), + uniform_data: UniformData::new(gl, program), } } @@ -48,7 +48,7 @@ impl GradientProgram { transform: &Transformation, ) { if transform != &self.uniform_data.transform { - set_transform( + triangle::set_transform( gl, self.uniform_data.uniform_locations.transform_location, *transform, @@ -117,12 +117,11 @@ impl GradientProgram { transform: &Transformation, ) { unsafe { gl.use_program(Some(self.program)) } - self.write_uniforms(gl, gradient, transform); } } -impl GradientUniformData { +impl UniformData { fn new(gl: &Context, program: NativeProgram) -> Self { let gradient_direction_location = unsafe { gl.get_uniform_location(program, "gradient_direction") } @@ -141,14 +140,14 @@ impl GradientUniformData { unsafe { gl.get_uniform_location(program, "u_Transform") } .expect("Gradient - Get u_Transform."); - GradientUniformData { + Self { gradient: Gradient::Linear(Linear { start: Default::default(), end: Default::default(), color_stops: vec![], }), transform: Transformation::identity(), - uniform_locations: GradientUniformLocations { + uniform_locations: UniformLocations { gradient_direction_location, color_stops_size_location, color_stops_location, diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs index 5ba7f91c..311e3704 100644 --- a/glow/src/triangle/solid.rs +++ b/glow/src/triangle/solid.rs @@ -1,24 +1,23 @@ use crate::program::Version; -use crate::triangle::{set_transform, simple_triangle_program}; -use crate::Color; +use crate::{triangle, Color}; use glow::{Context, HasContext, NativeProgram}; use iced_graphics::Transformation; #[derive(Debug)] -pub struct SolidProgram { +pub struct Program { program: ::Program, - uniform_data: SolidUniformData, + uniform_data: UniformData, } #[derive(Debug)] -struct SolidUniformData { +struct UniformData { pub color: Color, pub color_location: ::UniformLocation, pub transform: Transformation, pub transform_location: ::UniformLocation, } -impl SolidUniformData { +impl UniformData { fn new(gl: &Context, program: NativeProgram) -> Self { Self { color: Color::TRANSPARENT, @@ -35,9 +34,9 @@ impl SolidUniformData { } } -impl SolidProgram { +impl Program { pub fn new(gl: &Context, shader_version: &Version) -> Self { - let program = simple_triangle_program( + let program = triangle::program( gl, shader_version, include_str!("../shader/common/triangle.frag"), @@ -45,7 +44,7 @@ impl SolidProgram { Self { program, - uniform_data: SolidUniformData::new(gl, program), + uniform_data: UniformData::new(gl, program), } } @@ -56,7 +55,11 @@ impl SolidProgram { transform: &Transformation, ) { if transform != &self.uniform_data.transform { - set_transform(gl, self.uniform_data.transform_location, *transform) + triangle::set_transform( + gl, + self.uniform_data.transform_location, + *transform, + ) } if color != &self.uniform_data.color { -- cgit From 67ab4fd8c0ebd0e1e638307c6b303cce5cc13e9c Mon Sep 17 00:00:00 2001 From: bungoboingo Date: Tue, 18 Oct 2022 18:05:53 -0700 Subject: Updated syntax for color stop iteration re: PR comments. --- glow/src/triangle/gradient.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index 6bca44ee..36e434e3 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -81,8 +81,7 @@ impl Program { let mut stops = [0.0; 128]; - for (index, stop) in linear.color_stops.iter().enumerate() { - if index == 16 { break; } + for (index, stop) in linear.color_stops.iter().enumerate().take(16) { stops[index*8] = stop.color.r; stops[(index*8)+1] = stop.color.g; stops[(index*8)+2] = stop.color.b; -- cgit From b95745340441835bd25b5cadc2342254631f8c05 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 04:35:16 +0100 Subject: Run `cargo fmt` --- glow/src/backend.rs | 2 +- glow/src/triangle/gradient.rs | 93 ++++++++++++++++++++++--------------------- glow/src/window/compositor.rs | 6 ++- 3 files changed, 54 insertions(+), 47 deletions(-) (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 7333d513..21af2ecf 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -1,6 +1,6 @@ -use crate::{program, triangle}; use crate::quad; use crate::text; +use crate::{program, triangle}; use crate::{Settings, Transformation, Viewport}; use iced_graphics::backend; diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index 36e434e3..ad41dffd 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -57,52 +57,55 @@ impl Program { 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) { - 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( - Some( - &self - .uniform_data - .uniform_locations - .color_stops_location, - ), - &stops, - ); + 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) + { + 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( + Some( + &self + .uniform_data + .uniform_locations + .color_stops_location, + ), + &stops, + ); + }, } self.uniform_data.gradient = gradient.clone(); diff --git a/glow/src/window/compositor.rs b/glow/src/window/compositor.rs index 6459dbce..20756032 100644 --- a/glow/src/window/compositor.rs +++ b/glow/src/window/compositor.rs @@ -26,7 +26,11 @@ impl iced_graphics::window::GLCompositor for Compositor { log::info!("{:#?}", settings); let version = gl.version(); - log::info!("OpenGL version: {:?} (Embedded: {})", version, version.is_embedded); + log::info!( + "OpenGL version: {:?} (Embedded: {})", + version, + version.is_embedded + ); let renderer = gl.get_parameter_string(glow::RENDERER); log::info!("Renderer: {}", renderer); -- cgit From 62465842099908f9e50b8edabfec709b37b1ade3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 04:37:23 +0100 Subject: Convert colors to linear RGB before uploading in `solid` pipelines --- glow/src/triangle/solid.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs index 311e3704..fb3d40c3 100644 --- a/glow/src/triangle/solid.rs +++ b/glow/src/triangle/solid.rs @@ -63,13 +63,15 @@ impl Program { } 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), - color.r, - color.g, - color.b, - color.a, + r, + g, + b, + a, ); } -- cgit From 9a02d60ba51a91049466caa46db73d741520e051 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 04:41:27 +0100 Subject: Convert colors to linear RGB in `gradient` pipelines --- glow/src/triangle/gradient.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index ad41dffd..5225612e 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -86,10 +86,12 @@ impl Program { for (index, stop) in linear.color_stops.iter().enumerate().take(16) { - 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; + 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.; -- cgit From 7e22e2d45293c5916812be03dc7367134b69b3ad Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 04:53:27 +0100 Subject: Fix lints by `clippy` --- glow/src/triangle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index fff14910..68ebcb00 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -137,12 +137,12 @@ impl Pipeline { match mesh.style { mesh::Style::Solid(color) => { - self.programs.solid.use_program(gl, &color, &transform); + self.programs.solid.use_program(gl, color, &transform); } mesh::Style::Gradient(gradient) => { self.programs .gradient - .use_program(gl, &gradient, &transform); + .use_program(gl, gradient, &transform); } } -- cgit From 84d1b79fefc88534835fdfbe79bc0eb3b43627cf Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 05:50:53 +0100 Subject: Move `mesh::Style` to `triangle` and reuse it in `fill` and `stroke` --- glow/src/triangle.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 68ebcb00..5d14666c 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -3,8 +3,11 @@ mod gradient; mod solid; use crate::{program, Transformation}; + +use iced_graphics::layer::mesh::{self, Mesh}; +use iced_graphics::triangle; + use glow::HasContext; -use iced_graphics::layer::{mesh, Mesh}; use std::marker::PhantomData; pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; @@ -136,10 +139,10 @@ impl Pipeline { ); match mesh.style { - mesh::Style::Solid(color) => { + triangle::Style::Solid(color) => { self.programs.solid.use_program(gl, color, &transform); } - mesh::Style::Gradient(gradient) => { + triangle::Style::Gradient(gradient) => { self.programs .gradient .use_program(gl, gradient, &transform); -- cgit From f31c8f2504ea7c004c5caed8913e5da28d2e50e2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 3 Nov 2022 06:05:23 +0100 Subject: Refactor imports of `triangle` modules in `iced_glow` and `iced_wgpu` --- glow/src/triangle.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 5d14666c..0e27bcf2 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -2,16 +2,15 @@ mod gradient; mod solid; -use crate::{program, Transformation}; +use crate::program; +use crate::Transformation; use iced_graphics::layer::mesh::{self, Mesh}; -use iced_graphics::triangle; +use iced_graphics::triangle::{self, Vertex2D}; use glow::HasContext; use std::marker::PhantomData; -pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; - #[derive(Debug)] pub(crate) struct Pipeline { vertex_array: ::VertexArray, -- cgit From c0596179bd8582e4f4b5289cdeee8de4fa3de464 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Thu, 3 Nov 2022 00:35:01 +0100 Subject: non uniform border radius for quads --- glow/src/quad/compatibility.rs | 10 +++++----- glow/src/quad/core.rs | 4 ++-- glow/src/shader/core/quad.frag | 24 ++++++++++++++++++++---- glow/src/shader/core/quad.vert | 12 +++++++----- 4 files changed, 34 insertions(+), 16 deletions(-) (limited to 'glow') diff --git a/glow/src/quad/compatibility.rs b/glow/src/quad/compatibility.rs index 28a5ea7c..5734c159 100644 --- a/glow/src/quad/compatibility.rs +++ b/glow/src/quad/compatibility.rs @@ -254,7 +254,7 @@ unsafe fn create_buffers( gl.enable_vertex_attrib_array(4); gl.vertex_attrib_pointer_f32( 4, - 1, + 4, glow::FLOAT, false, stride, @@ -268,7 +268,7 @@ unsafe fn create_buffers( glow::FLOAT, false, stride, - 4 * (2 + 2 + 4 + 4 + 1), + 4 * (2 + 2 + 4 + 4 + 4), ); gl.enable_vertex_attrib_array(6); @@ -278,7 +278,7 @@ unsafe fn create_buffers( glow::FLOAT, false, stride, - 4 * (2 + 2 + 4 + 4 + 1 + 1), + 4 * (2 + 2 + 4 + 4 + 4 + 1), ); gl.bind_vertex_array(None); @@ -307,7 +307,7 @@ pub struct Vertex { pub border_color: [f32; 4], /// The border radius of the [`Vertex`]. - pub border_radius: f32, + pub border_radius: [f32; 4], /// The border width of the [`Vertex`]. pub border_width: f32, @@ -325,7 +325,7 @@ impl Vertex { size: quad.size, color: quad.color, border_color: quad.color, - border_radius: quad.border_radius, + border_radius: [quad.border_radius[0]; 4], border_width: quad.border_width, q_position: [0.0, 0.0], }; diff --git a/glow/src/quad/core.rs b/glow/src/quad/core.rs index 16bec385..89036530 100644 --- a/glow/src/quad/core.rs +++ b/glow/src/quad/core.rs @@ -218,7 +218,7 @@ unsafe fn create_instance_buffer( gl.enable_vertex_attrib_array(4); gl.vertex_attrib_pointer_f32( 4, - 1, + 4, glow::FLOAT, false, stride, @@ -233,7 +233,7 @@ unsafe fn create_instance_buffer( glow::FLOAT, false, stride, - 4 * (2 + 2 + 4 + 4 + 1), + 4 * (2 + 2 + 4 + 4 + 4), ); gl.vertex_attrib_divisor(5, 1); diff --git a/glow/src/shader/core/quad.frag b/glow/src/shader/core/quad.frag index 57e2e8e7..d036ea1a 100644 --- a/glow/src/shader/core/quad.frag +++ b/glow/src/shader/core/quad.frag @@ -17,7 +17,7 @@ in vec4 v_Color; in vec4 v_BorderColor; in vec2 v_Pos; in vec2 v_Scale; -in float v_BorderRadius; +in vec4 v_BorderRadius; in float v_BorderWidth; float fDistance(vec2 frag_coord, vec2 position, vec2 size, float radius) @@ -38,14 +38,30 @@ float fDistance(vec2 frag_coord, vec2 position, vec2 size, float radius) return sqrt(distance.x * distance.x + distance.y * distance.y); } +float selectBorderRadius(vec4 radi, vec2 position, vec2 center) +{ + float rx = radi.x; + float ry = radi.y; + rx = position.x > center.x ? radi.y : radi.x; + ry = position.x > center.x ? radi.z : radi.w; + rx = position.y > center.y ? ry : rx; + return rx; +} + void main() { vec4 mixed_color; vec2 fragCoord = vec2(gl_FragCoord.x, u_ScreenHeight - gl_FragCoord.y); + float borderRadius = selectBorderRadius( + v_BorderRadius, + fragCoord, + (v_Pos + v_Scale * 0.5).xy + ); + // TODO: Remove branching (?) if(v_BorderWidth > 0.0) { - float internal_border = max(v_BorderRadius - v_BorderWidth, 0.0); + float internal_border = max(borderRadius - v_BorderWidth, 0.0); float internal_distance = fDistance( fragCoord, @@ -69,11 +85,11 @@ void main() { fragCoord, v_Pos, v_Scale, - v_BorderRadius + borderRadius ); float radius_alpha = - 1.0 - smoothstep(max(v_BorderRadius - 0.5, 0.0), v_BorderRadius + 0.5, d); + 1.0 - smoothstep(max(borderRadius - 0.5, 0.0), borderRadius + 0.5, d); gl_FragColor = vec4(mixed_color.xyz, mixed_color.w * radius_alpha); } diff --git a/glow/src/shader/core/quad.vert b/glow/src/shader/core/quad.vert index b1fb2365..17c3e641 100644 --- a/glow/src/shader/core/quad.vert +++ b/glow/src/shader/core/quad.vert @@ -5,14 +5,14 @@ in vec2 i_Pos; in vec2 i_Scale; in vec4 i_Color; in vec4 i_BorderColor; -in float i_BorderRadius; +in vec4 i_BorderRadius; in float i_BorderWidth; out vec4 v_Color; out vec4 v_BorderColor; out vec2 v_Pos; out vec2 v_Scale; -out float v_BorderRadius; +out vec4 v_BorderRadius; out float v_BorderWidth; vec2 positions[4] = vec2[]( @@ -27,9 +27,11 @@ void main() { vec2 p_Pos = i_Pos * u_Scale; vec2 p_Scale = i_Scale * u_Scale; - float i_BorderRadius = min( - i_BorderRadius, - min(i_Scale.x, i_Scale.y) / 2.0 + vec4 i_BorderRadius = vec4( + min(i_BorderRadius.x, min(i_Scale.x, i_Scale.y) / 2.0), + min(i_BorderRadius.y, min(i_Scale.x, i_Scale.y) / 2.0), + min(i_BorderRadius.z, min(i_Scale.x, i_Scale.y) / 2.0), + min(i_BorderRadius.w, min(i_Scale.x, i_Scale.y) / 2.0) ); mat4 i_Transform = mat4( -- cgit From 5575e6ea0897e406674e7e4239808fbf9daa07c3 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 24 Oct 2022 17:06:02 -0700 Subject: Add image/svg support to `iced_glow` https://github.com/iced-rs/iced/issues/674 Uses image/svg support in `iced_graphics`. The is not currently using an atlas, and uses one texture/draw per image. This should be good enough for now; supporting images with glow is better than not supporting them, and if something else performs better, that improvement can be made without any change to the public API. --- glow/Cargo.toml | 19 +++- glow/src/backend.rs | 26 ++++- glow/src/image.rs | 212 ++++++++++++++++++++++++++++++++++++++ glow/src/image/textures.rs | 82 +++++++++++++++ glow/src/lib.rs | 2 + glow/src/shader/common/image.frag | 22 ++++ glow/src/shader/common/image.vert | 9 ++ 7 files changed, 366 insertions(+), 6 deletions(-) create mode 100644 glow/src/image.rs create mode 100644 glow/src/image/textures.rs create mode 100644 glow/src/shader/common/image.frag create mode 100644 glow/src/shader/common/image.vert (limited to 'glow') diff --git a/glow/Cargo.toml b/glow/Cargo.toml index 18215e9b..476547d4 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -8,12 +8,23 @@ license = "MIT AND OFL-1.1" repository = "https://github.com/iced-rs/iced" [features] +svg = ["iced_graphics/svg"] +image = ["image_rs", "iced_graphics/image", "png", "jpeg", "jpeg_rayon", "gif", "webp", "bmp"] +image_rs = ["iced_graphics/image_rs"] +png = ["iced_graphics/png"] +jpeg = ["iced_graphics/jpeg"] +jpeg_rayon = ["iced_graphics/jpeg_rayon"] +gif = ["iced_graphics/gif"] +webp = ["iced_graphics/webp"] +pnm = ["iced_graphics/pnm"] +ico = ["iced_graphics/ico"] +bmp = ["iced_graphics/bmp"] +hdr = ["iced_graphics/hdr"] +dds = ["iced_graphics/dds"] +farbfeld = ["iced_graphics/farbfeld"] canvas = ["iced_graphics/canvas"] qr_code = ["iced_graphics/qr_code"] default_system_font = ["iced_graphics/font-source"] -# Not supported yet! -image = [] -svg = [] [dependencies] glow = "0.11.1" @@ -22,6 +33,8 @@ glyph_brush = "0.7" euclid = "0.22" bytemuck = "1.4" log = "0.4" +kamadak-exif = "0.5" +bitflags = "1.2" [dependencies.iced_native] version = "0.5" diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 21af2ecf..1ba70a49 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -1,3 +1,5 @@ +#[cfg(any(feature = "image_rs", feature = "svg"))] +use crate::image; use crate::quad; use crate::text; use crate::{program, triangle}; @@ -15,6 +17,8 @@ use iced_native::{Font, Size}; /// [`iced`]: https://github.com/iced-rs/iced #[derive(Debug)] pub struct Backend { + #[cfg(any(feature = "image_rs", feature = "svg"))] + image_pipeline: image::Pipeline, quad_pipeline: quad::Pipeline, text_pipeline: text::Pipeline, triangle_pipeline: triangle::Pipeline, @@ -32,10 +36,14 @@ impl Backend { let shader_version = program::Version::new(gl); + #[cfg(any(feature = "image_rs", feature = "svg"))] + let image_pipeline = image::Pipeline::new(gl, &shader_version); let quad_pipeline = quad::Pipeline::new(gl, &shader_version); let triangle_pipeline = triangle::Pipeline::new(gl, &shader_version); Self { + #[cfg(any(feature = "image_rs", feature = "svg"))] + image_pipeline, quad_pipeline, text_pipeline, triangle_pipeline, @@ -70,6 +78,9 @@ impl Backend { viewport_size.height, ); } + + #[cfg(any(feature = "image_rs", feature = "svg"))] + self.image_pipeline.trim_cache(gl); } fn flush( @@ -112,6 +123,15 @@ impl Backend { ); } + #[cfg(any(feature = "image_rs", feature = "svg"))] + if !layer.images.is_empty() { + let scaled = transformation + * Transformation::scale(scale_factor, scale_factor); + + self.image_pipeline + .draw(gl, scaled, scale_factor, &layer.images); + } + if !layer.text.is_empty() { for text in layer.text.iter() { // Target physical coordinates directly to avoid blurry text @@ -236,10 +256,10 @@ impl backend::Text for Backend { } } -#[cfg(feature = "image")] +#[cfg(feature = "image_rs")] impl backend::Image for Backend { - fn dimensions(&self, _handle: &iced_native::image::Handle) -> (u32, u32) { - (50, 50) + fn dimensions(&self, handle: &iced_native::image::Handle) -> (u32, u32) { + self.image_pipeline.dimensions(handle) } } diff --git a/glow/src/image.rs b/glow/src/image.rs new file mode 100644 index 00000000..51e3016e --- /dev/null +++ b/glow/src/image.rs @@ -0,0 +1,212 @@ +use crate::program::{self, Shader}; +use crate::Transformation; +use glow::HasContext; +use iced_graphics::layer; +#[cfg(feature = "image_rs")] +use std::cell::RefCell; + +pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; + +#[cfg(feature = "image_rs")] +use iced_graphics::image::raster; + +#[cfg(feature = "svg")] +use iced_graphics::image::vector; + +mod textures; +use textures::{Entry, Textures}; + +#[derive(Debug)] +pub(crate) struct Pipeline { + program: ::Program, + vertex_array: ::VertexArray, + vertex_buffer: ::Buffer, + transform_location: ::UniformLocation, + textures: Textures, + #[cfg(feature = "image_rs")] + raster_cache: RefCell>, + #[cfg(feature = "svg")] + vector_cache: vector::Cache, +} + +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/image.vert"), + ); + let fragment_shader = Shader::fragment( + gl, + shader_version, + include_str!("shader/common/image.frag"), + ); + + program::create( + gl, + &[vertex_shader, fragment_shader], + &[(0, "i_Position")], + ) + }; + + 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); + } + + let vertex_buffer = + unsafe { gl.create_buffer().expect("Create vertex buffer") }; + let vertex_array = + unsafe { gl.create_vertex_array().expect("Create vertex array") }; + + unsafe { + gl.bind_vertex_array(Some(vertex_array)); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer)); + + let vertices = &[0u8, 0, 1, 0, 0, 1, 1, 1]; + gl.buffer_data_size( + glow::ARRAY_BUFFER, + vertices.len() as i32, + glow::STATIC_DRAW, + ); + gl.buffer_sub_data_u8_slice( + glow::ARRAY_BUFFER, + 0, + bytemuck::cast_slice(vertices), + ); + + gl.enable_vertex_attrib_array(0); + gl.vertex_attrib_pointer_f32( + 0, + 2, + glow::UNSIGNED_BYTE, + false, + 0, + 0, + ); + + gl.bind_buffer(glow::ARRAY_BUFFER, None); + gl.bind_vertex_array(None); + } + + Pipeline { + program, + vertex_array, + vertex_buffer, + transform_location, + textures: Textures::new(), + #[cfg(feature = "image_rs")] + raster_cache: RefCell::new(raster::Cache::default()), + #[cfg(feature = "svg")] + vector_cache: vector::Cache::default(), + } + } + + #[cfg(feature = "image_rs")] + pub fn dimensions( + &self, + handle: &iced_native::image::Handle, + ) -> (u32, u32) { + self.raster_cache.borrow_mut().load(handle).dimensions() + } + + pub fn draw( + &mut self, + mut gl: &glow::Context, + transformation: Transformation, + _scale_factor: f32, + images: &[layer::Image], + ) { + unsafe { + gl.use_program(Some(self.program)); + gl.bind_vertex_array(Some(self.vertex_array)); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vertex_buffer)); + } + + #[cfg(feature = "image_rs")] + let mut raster_cache = self.raster_cache.borrow_mut(); + for image in images { + let (entry, bounds) = match &image { + #[cfg(feature = "image_rs")] + layer::Image::Raster { handle, bounds } => ( + raster_cache.upload(handle, &mut gl, &mut self.textures), + bounds, + ), + #[cfg(not(feature = "image_rs"))] + layer::Image::Raster { handle: _, bounds } => (None, bounds), + + #[cfg(feature = "svg")] + layer::Image::Vector { handle, bounds } => { + let size = [bounds.width, bounds.height]; + ( + self.vector_cache.upload( + handle, + size, + _scale_factor, + &mut gl, + &mut self.textures, + ), + bounds, + ) + } + + #[cfg(not(feature = "svg"))] + layer::Image::Vector { handle: _, bounds } => (None, bounds), + }; + + unsafe { + if let Some(Entry { texture, .. }) = entry { + gl.bind_texture(glow::TEXTURE_2D, Some(*texture)) + } else { + continue; + } + + let translate = Transformation::translate(bounds.x, bounds.y); + let scale = Transformation::scale(bounds.width, bounds.height); + let transformation = transformation * translate * scale; + let matrix: [f32; 16] = transformation.into(); + gl.uniform_matrix_4_f32_slice( + Some(&self.transform_location), + false, + &matrix, + ); + + gl.draw_arrays(glow::TRIANGLE_STRIP, 0, 4); + + gl.bind_texture(glow::TEXTURE_2D, None); + } + } + + unsafe { + gl.bind_buffer(glow::ARRAY_BUFFER, None); + gl.bind_vertex_array(None); + gl.use_program(None); + } + } + + pub fn trim_cache(&mut self, mut gl: &glow::Context) { + #[cfg(feature = "image_rs")] + self.raster_cache + .borrow_mut() + .trim(&mut self.textures, &mut gl); + + #[cfg(feature = "svg")] + self.vector_cache.trim(&mut self.textures, &mut gl); + } +} diff --git a/glow/src/image/textures.rs b/glow/src/image/textures.rs new file mode 100644 index 00000000..f43cae1c --- /dev/null +++ b/glow/src/image/textures.rs @@ -0,0 +1,82 @@ +use glow::HasContext; +use iced_graphics::image::{TextureStore, TextureStoreEntry}; + +#[derive(Debug)] +pub struct Textures; + +impl Textures { + pub fn new() -> Self { + Self + } +} + +impl TextureStore for Textures { + type Entry = Entry; + type State<'a> = &'a glow::Context; + + fn upload( + &mut self, + width: u32, + height: u32, + data: &[u8], + gl: &mut &glow::Context, + ) -> Option { + unsafe { + let texture = gl.create_texture().expect("create texture"); + gl.bind_texture(glow::TEXTURE_2D, Some(texture)); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::SRGB8_ALPHA8 as i32, + width as i32, + height as i32, + 0, + glow::BGRA, + glow::UNSIGNED_BYTE, + Some(data), + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_S, + glow::CLAMP_TO_EDGE as _, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_T, + glow::CLAMP_TO_EDGE as _, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR as _, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::LINEAR as _, + ); + gl.bind_texture(glow::TEXTURE_2D, None); + + Some(Entry { + size: (width, height), + texture, + }) + } + } + + fn remove(&mut self, entry: &Entry, gl: &mut &glow::Context) { + unsafe { gl.delete_texture(entry.texture) } + } +} + +#[derive(Debug)] +pub struct Entry { + size: (u32, u32), + pub texture: glow::NativeTexture, +} + +impl TextureStoreEntry for Entry { + fn size(&self) -> (u32, u32) { + self.size + } +} diff --git a/glow/src/lib.rs b/glow/src/lib.rs index de9c0002..daeb3e32 100644 --- a/glow/src/lib.rs +++ b/glow/src/lib.rs @@ -24,6 +24,8 @@ pub use glow; mod backend; +#[cfg(any(feature = "image_rs", feature = "svg"))] +mod image; mod program; mod quad; mod text; diff --git a/glow/src/shader/common/image.frag b/glow/src/shader/common/image.frag new file mode 100644 index 00000000..5e05abdf --- /dev/null +++ b/glow/src/shader/common/image.frag @@ -0,0 +1,22 @@ +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#endif + +uniform sampler2D tex; +in vec2 tex_pos; + +#ifdef HIGHER_THAN_300 +out vec4 fragColor; +#define gl_FragColor fragColor +#endif +#ifdef GL_ES +#define texture texture2D +#endif + +void main() { + gl_FragColor = texture(tex, tex_pos); +} diff --git a/glow/src/shader/common/image.vert b/glow/src/shader/common/image.vert new file mode 100644 index 00000000..93e541f2 --- /dev/null +++ b/glow/src/shader/common/image.vert @@ -0,0 +1,9 @@ +uniform mat4 u_Transform; + +in vec2 i_Position; +out vec2 tex_pos; + +void main() { + gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0); + tex_pos = i_Position; +} -- cgit From 8ce8d374b1e8d1d394a42a5ee2bca8af790f0b71 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 03:13:04 +0100 Subject: Refactor some `image` traits a bit - Use `Size` were applicable. - Rename `TextureStore` to `image::Storage`. - Rename `TextureStoreEntry` to `image::storage::Entry`. - Wire up `viewport_dimensions` to `iced_glow` for `Svg`. --- glow/src/backend.rs | 8 ++--- glow/src/image.rs | 64 +++++++++++++++++++++++------------- glow/src/image/storage.rs | 78 +++++++++++++++++++++++++++++++++++++++++++ glow/src/image/textures.rs | 82 ---------------------------------------------- 4 files changed, 123 insertions(+), 109 deletions(-) create mode 100644 glow/src/image/storage.rs delete mode 100644 glow/src/image/textures.rs (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 1ba70a49..35a82c0f 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -258,7 +258,7 @@ impl backend::Text for Backend { #[cfg(feature = "image_rs")] impl backend::Image for Backend { - fn dimensions(&self, handle: &iced_native::image::Handle) -> (u32, u32) { + fn dimensions(&self, handle: &iced_native::image::Handle) -> Size { self.image_pipeline.dimensions(handle) } } @@ -267,8 +267,8 @@ impl backend::Image for Backend { impl backend::Svg for Backend { fn viewport_dimensions( &self, - _handle: &iced_native::svg::Handle, - ) -> (u32, u32) { - (50, 50) + handle: &iced_native::svg::Handle, + ) -> Size { + self.image_pipeline.viewport_dimensions(handle) } } diff --git a/glow/src/image.rs b/glow/src/image.rs index 51e3016e..66620537 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -1,20 +1,24 @@ -use crate::program::{self, Shader}; -use crate::Transformation; -use glow::HasContext; -use iced_graphics::layer; -#[cfg(feature = "image_rs")] -use std::cell::RefCell; +mod storage; + +use storage::Storage; pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; +use crate::program::{self, Shader}; +use crate::Transformation; + #[cfg(feature = "image_rs")] use iced_graphics::image::raster; #[cfg(feature = "svg")] use iced_graphics::image::vector; -mod textures; -use textures::{Entry, Textures}; +use iced_graphics::layer; +use iced_graphics::Size; + +use glow::HasContext; + +use std::cell::RefCell; #[derive(Debug)] pub(crate) struct Pipeline { @@ -22,11 +26,11 @@ pub(crate) struct Pipeline { vertex_array: ::VertexArray, vertex_buffer: ::Buffer, transform_location: ::UniformLocation, - textures: Textures, + storage: Storage, #[cfg(feature = "image_rs")] - raster_cache: RefCell>, + raster_cache: RefCell>, #[cfg(feature = "svg")] - vector_cache: vector::Cache, + vector_cache: RefCell>, } impl Pipeline { @@ -110,22 +114,30 @@ impl Pipeline { vertex_array, vertex_buffer, transform_location, - textures: Textures::new(), + storage: Storage::default(), #[cfg(feature = "image_rs")] raster_cache: RefCell::new(raster::Cache::default()), #[cfg(feature = "svg")] - vector_cache: vector::Cache::default(), + vector_cache: RefCell::new(vector::Cache::default()), } } #[cfg(feature = "image_rs")] - pub fn dimensions( - &self, - handle: &iced_native::image::Handle, - ) -> (u32, u32) { + pub fn dimensions(&self, handle: &iced_native::image::Handle) -> Size { self.raster_cache.borrow_mut().load(handle).dimensions() } + #[cfg(feature = "svg")] + pub fn viewport_dimensions( + &self, + handle: &iced_native::svg::Handle, + ) -> Size { + let mut cache = self.vector_cache.borrow_mut(); + let svg = cache.load(handle); + + svg.viewport_dimensions() + } + pub fn draw( &mut self, mut gl: &glow::Context, @@ -141,11 +153,15 @@ impl Pipeline { #[cfg(feature = "image_rs")] let mut raster_cache = self.raster_cache.borrow_mut(); + + #[cfg(feature = "svg")] + let mut vector_cache = self.vector_cache.borrow_mut(); + for image in images { let (entry, bounds) = match &image { #[cfg(feature = "image_rs")] layer::Image::Raster { handle, bounds } => ( - raster_cache.upload(handle, &mut gl, &mut self.textures), + raster_cache.upload(handle, &mut gl, &mut self.storage), bounds, ), #[cfg(not(feature = "image_rs"))] @@ -155,12 +171,12 @@ impl Pipeline { layer::Image::Vector { handle, bounds } => { let size = [bounds.width, bounds.height]; ( - self.vector_cache.upload( + vector_cache.upload( handle, size, _scale_factor, &mut gl, - &mut self.textures, + &mut self.storage, ), bounds, ) @@ -171,7 +187,7 @@ impl Pipeline { }; unsafe { - if let Some(Entry { texture, .. }) = entry { + if let Some(storage::Entry { texture, .. }) = entry { gl.bind_texture(glow::TEXTURE_2D, Some(*texture)) } else { continue; @@ -204,9 +220,11 @@ impl Pipeline { #[cfg(feature = "image_rs")] self.raster_cache .borrow_mut() - .trim(&mut self.textures, &mut gl); + .trim(&mut self.storage, &mut gl); #[cfg(feature = "svg")] - self.vector_cache.trim(&mut self.textures, &mut gl); + self.vector_cache + .borrow_mut() + .trim(&mut self.storage, &mut gl); } } diff --git a/glow/src/image/storage.rs b/glow/src/image/storage.rs new file mode 100644 index 00000000..e2171fb5 --- /dev/null +++ b/glow/src/image/storage.rs @@ -0,0 +1,78 @@ +use iced_graphics::image; +use iced_graphics::Size; + +use glow::HasContext; + +#[derive(Debug, Default)] +pub struct Storage; + +impl image::Storage for Storage { + type Entry = Entry; + type State<'a> = &'a glow::Context; + + fn upload( + &mut self, + width: u32, + height: u32, + data: &[u8], + gl: &mut &glow::Context, + ) -> Option { + unsafe { + let texture = gl.create_texture().expect("create texture"); + gl.bind_texture(glow::TEXTURE_2D, Some(texture)); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::SRGB8_ALPHA8 as i32, + width as i32, + height as i32, + 0, + glow::BGRA, + glow::UNSIGNED_BYTE, + Some(data), + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_S, + glow::CLAMP_TO_EDGE as _, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_T, + glow::CLAMP_TO_EDGE as _, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR as _, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::LINEAR as _, + ); + gl.bind_texture(glow::TEXTURE_2D, None); + + Some(Entry { + size: Size::new(width, height), + texture, + }) + } + } + + fn remove(&mut self, entry: &Entry, gl: &mut &glow::Context) { + unsafe { gl.delete_texture(entry.texture) } + } +} + +#[derive(Debug)] +pub struct Entry { + size: Size, + pub(super) texture: glow::NativeTexture, +} + +impl image::storage::Entry for Entry { + fn size(&self) -> Size { + self.size + } +} diff --git a/glow/src/image/textures.rs b/glow/src/image/textures.rs deleted file mode 100644 index f43cae1c..00000000 --- a/glow/src/image/textures.rs +++ /dev/null @@ -1,82 +0,0 @@ -use glow::HasContext; -use iced_graphics::image::{TextureStore, TextureStoreEntry}; - -#[derive(Debug)] -pub struct Textures; - -impl Textures { - pub fn new() -> Self { - Self - } -} - -impl TextureStore for Textures { - type Entry = Entry; - type State<'a> = &'a glow::Context; - - fn upload( - &mut self, - width: u32, - height: u32, - data: &[u8], - gl: &mut &glow::Context, - ) -> Option { - unsafe { - let texture = gl.create_texture().expect("create texture"); - gl.bind_texture(glow::TEXTURE_2D, Some(texture)); - gl.tex_image_2d( - glow::TEXTURE_2D, - 0, - glow::SRGB8_ALPHA8 as i32, - width as i32, - height as i32, - 0, - glow::BGRA, - glow::UNSIGNED_BYTE, - Some(data), - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_WRAP_S, - glow::CLAMP_TO_EDGE as _, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_WRAP_T, - glow::CLAMP_TO_EDGE as _, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MIN_FILTER, - glow::LINEAR as _, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MAG_FILTER, - glow::LINEAR as _, - ); - gl.bind_texture(glow::TEXTURE_2D, None); - - Some(Entry { - size: (width, height), - texture, - }) - } - } - - fn remove(&mut self, entry: &Entry, gl: &mut &glow::Context) { - unsafe { gl.delete_texture(entry.texture) } - } -} - -#[derive(Debug)] -pub struct Entry { - size: (u32, u32), - pub texture: glow::NativeTexture, -} - -impl TextureStoreEntry for Entry { - fn size(&self) -> (u32, u32) { - self.size - } -} -- cgit From 438f97a6d00ad0312e7c84b4c1529968bdfba849 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 03:18:13 +0100 Subject: Use RGBA texture for `image` and `svg` pipelines --- glow/src/image/storage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/src/image/storage.rs b/glow/src/image/storage.rs index e2171fb5..9bc20641 100644 --- a/glow/src/image/storage.rs +++ b/glow/src/image/storage.rs @@ -27,7 +27,7 @@ impl image::Storage for Storage { width as i32, height as i32, 0, - glow::BGRA, + glow::RGBA, glow::UNSIGNED_BYTE, Some(data), ); -- cgit From d3b613df446aaf47b62c7c24422026f8872e9448 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 03:22:06 +0100 Subject: Remove unnecessary dependencies from `iced_glow` --- glow/Cargo.toml | 2 -- 1 file changed, 2 deletions(-) (limited to 'glow') diff --git a/glow/Cargo.toml b/glow/Cargo.toml index 476547d4..31a548c8 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -33,8 +33,6 @@ glyph_brush = "0.7" euclid = "0.22" bytemuck = "1.4" log = "0.4" -kamadak-exif = "0.5" -bitflags = "1.2" [dependencies.iced_native] version = "0.5" -- cgit From 0a23f518c70d27f2e44af38e5d3be2a0ab1a9bc1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 5 Nov 2022 03:26:19 +0100 Subject: Remove redundant features in `iced_wgpu` and `iced_glow` --- glow/Cargo.toml | 3 +-- glow/src/backend.rs | 14 +++++++------- glow/src/image.rs | 16 ++++++++-------- glow/src/lib.rs | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) (limited to 'glow') diff --git a/glow/Cargo.toml b/glow/Cargo.toml index 31a548c8..a50fd375 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -9,8 +9,7 @@ repository = "https://github.com/iced-rs/iced" [features] svg = ["iced_graphics/svg"] -image = ["image_rs", "iced_graphics/image", "png", "jpeg", "jpeg_rayon", "gif", "webp", "bmp"] -image_rs = ["iced_graphics/image_rs"] +image = ["iced_graphics/image"] png = ["iced_graphics/png"] jpeg = ["iced_graphics/jpeg"] jpeg_rayon = ["iced_graphics/jpeg_rayon"] diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 35a82c0f..1a41d540 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -1,4 +1,4 @@ -#[cfg(any(feature = "image_rs", feature = "svg"))] +#[cfg(any(feature = "image", feature = "svg"))] use crate::image; use crate::quad; use crate::text; @@ -17,7 +17,7 @@ use iced_native::{Font, Size}; /// [`iced`]: https://github.com/iced-rs/iced #[derive(Debug)] pub struct Backend { - #[cfg(any(feature = "image_rs", feature = "svg"))] + #[cfg(any(feature = "image", feature = "svg"))] image_pipeline: image::Pipeline, quad_pipeline: quad::Pipeline, text_pipeline: text::Pipeline, @@ -36,13 +36,13 @@ impl Backend { let shader_version = program::Version::new(gl); - #[cfg(any(feature = "image_rs", feature = "svg"))] + #[cfg(any(feature = "image", feature = "svg"))] let image_pipeline = image::Pipeline::new(gl, &shader_version); let quad_pipeline = quad::Pipeline::new(gl, &shader_version); let triangle_pipeline = triangle::Pipeline::new(gl, &shader_version); Self { - #[cfg(any(feature = "image_rs", feature = "svg"))] + #[cfg(any(feature = "image", feature = "svg"))] image_pipeline, quad_pipeline, text_pipeline, @@ -79,7 +79,7 @@ impl Backend { ); } - #[cfg(any(feature = "image_rs", feature = "svg"))] + #[cfg(any(feature = "image", feature = "svg"))] self.image_pipeline.trim_cache(gl); } @@ -123,7 +123,7 @@ impl Backend { ); } - #[cfg(any(feature = "image_rs", feature = "svg"))] + #[cfg(any(feature = "image", feature = "svg"))] if !layer.images.is_empty() { let scaled = transformation * Transformation::scale(scale_factor, scale_factor); @@ -256,7 +256,7 @@ impl backend::Text for Backend { } } -#[cfg(feature = "image_rs")] +#[cfg(feature = "image")] impl backend::Image for Backend { fn dimensions(&self, handle: &iced_native::image::Handle) -> Size { self.image_pipeline.dimensions(handle) diff --git a/glow/src/image.rs b/glow/src/image.rs index 66620537..f906cd4c 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -7,7 +7,7 @@ pub use iced_graphics::triangle::{Mesh2D, Vertex2D}; use crate::program::{self, Shader}; use crate::Transformation; -#[cfg(feature = "image_rs")] +#[cfg(feature = "image")] use iced_graphics::image::raster; #[cfg(feature = "svg")] @@ -27,7 +27,7 @@ pub(crate) struct Pipeline { vertex_buffer: ::Buffer, transform_location: ::UniformLocation, storage: Storage, - #[cfg(feature = "image_rs")] + #[cfg(feature = "image")] raster_cache: RefCell>, #[cfg(feature = "svg")] vector_cache: RefCell>, @@ -115,14 +115,14 @@ impl Pipeline { vertex_buffer, transform_location, storage: Storage::default(), - #[cfg(feature = "image_rs")] + #[cfg(feature = "image")] raster_cache: RefCell::new(raster::Cache::default()), #[cfg(feature = "svg")] vector_cache: RefCell::new(vector::Cache::default()), } } - #[cfg(feature = "image_rs")] + #[cfg(feature = "image")] pub fn dimensions(&self, handle: &iced_native::image::Handle) -> Size { self.raster_cache.borrow_mut().load(handle).dimensions() } @@ -151,7 +151,7 @@ impl Pipeline { gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vertex_buffer)); } - #[cfg(feature = "image_rs")] + #[cfg(feature = "image")] let mut raster_cache = self.raster_cache.borrow_mut(); #[cfg(feature = "svg")] @@ -159,12 +159,12 @@ impl Pipeline { for image in images { let (entry, bounds) = match &image { - #[cfg(feature = "image_rs")] + #[cfg(feature = "image")] layer::Image::Raster { handle, bounds } => ( raster_cache.upload(handle, &mut gl, &mut self.storage), bounds, ), - #[cfg(not(feature = "image_rs"))] + #[cfg(not(feature = "image"))] layer::Image::Raster { handle: _, bounds } => (None, bounds), #[cfg(feature = "svg")] @@ -217,7 +217,7 @@ impl Pipeline { } pub fn trim_cache(&mut self, mut gl: &glow::Context) { - #[cfg(feature = "image_rs")] + #[cfg(feature = "image")] self.raster_cache .borrow_mut() .trim(&mut self.storage, &mut gl); diff --git a/glow/src/lib.rs b/glow/src/lib.rs index daeb3e32..e3690a69 100644 --- a/glow/src/lib.rs +++ b/glow/src/lib.rs @@ -24,7 +24,7 @@ pub use glow; mod backend; -#[cfg(any(feature = "image_rs", feature = "svg"))] +#[cfg(any(feature = "image", feature = "svg"))] mod image; mod program; mod quad; -- cgit From dcec3fd792cf422aef7a7217ec7f0311fbd12390 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 8 Nov 2022 04:50:26 +0100 Subject: Fix `compatibility::quad` pipeline in `iced_glow` --- glow/src/quad/compatibility.rs | 2 +- glow/src/shader/compatibility/quad.frag | 24 ++++++++++++++++++++---- glow/src/shader/compatibility/quad.vert | 12 +++++++----- 3 files changed, 28 insertions(+), 10 deletions(-) (limited to 'glow') diff --git a/glow/src/quad/compatibility.rs b/glow/src/quad/compatibility.rs index 5734c159..e909162c 100644 --- a/glow/src/quad/compatibility.rs +++ b/glow/src/quad/compatibility.rs @@ -325,7 +325,7 @@ impl Vertex { size: quad.size, color: quad.color, border_color: quad.color, - border_radius: [quad.border_radius[0]; 4], + border_radius: quad.border_radius, border_width: quad.border_width, q_position: [0.0, 0.0], }; diff --git a/glow/src/shader/compatibility/quad.frag b/glow/src/shader/compatibility/quad.frag index 8ea5693d..bb9d8122 100644 --- a/glow/src/shader/compatibility/quad.frag +++ b/glow/src/shader/compatibility/quad.frag @@ -12,7 +12,7 @@ varying vec4 v_Color; varying vec4 v_BorderColor; varying vec2 v_Pos; varying vec2 v_Scale; -varying float v_BorderRadius; +varying vec4 v_BorderRadius; varying float v_BorderWidth; float _distance(vec2 frag_coord, vec2 position, vec2 size, float radius) @@ -33,10 +33,26 @@ float _distance(vec2 frag_coord, vec2 position, vec2 size, float radius) return sqrt(distance.x * distance.x + distance.y * distance.y); } +float selectBorderRadius(vec4 radi, vec2 position, vec2 center) +{ + float rx = radi.x; + float ry = radi.y; + rx = position.x > center.x ? radi.y : radi.x; + ry = position.x > center.x ? radi.z : radi.w; + rx = position.y > center.y ? ry : rx; + return rx; +} + void main() { vec2 fragCoord = vec2(gl_FragCoord.x, u_ScreenHeight - gl_FragCoord.y); - float internal_border = max(v_BorderRadius - v_BorderWidth, 0.0); + float border_radius = selectBorderRadius( + v_BorderRadius, + fragCoord, + (v_Pos + v_Scale * 0.5).xy + ); + + float internal_border = max(border_radius - v_BorderWidth, 0.0); float internal_distance = _distance( fragCoord, @@ -57,11 +73,11 @@ void main() { fragCoord, v_Pos, v_Scale, - v_BorderRadius + border_radius ); float radius_alpha = - 1.0 - smoothstep(max(v_BorderRadius - 0.5, 0.0), v_BorderRadius + 0.5, d); + 1.0 - smoothstep(max(border_radius - 0.5, 0.0), border_radius + 0.5, d); gl_FragColor = vec4(mixed_color.xyz, mixed_color.w * radius_alpha); } diff --git a/glow/src/shader/compatibility/quad.vert b/glow/src/shader/compatibility/quad.vert index abe70c0e..89931f06 100644 --- a/glow/src/shader/compatibility/quad.vert +++ b/glow/src/shader/compatibility/quad.vert @@ -5,7 +5,7 @@ attribute vec2 i_Pos; attribute vec2 i_Scale; attribute vec4 i_Color; attribute vec4 i_BorderColor; -attribute float i_BorderRadius; +attribute vec4 i_BorderRadius; attribute float i_BorderWidth; attribute vec2 q_Pos; @@ -13,7 +13,7 @@ varying vec4 v_Color; varying vec4 v_BorderColor; varying vec2 v_Pos; varying vec2 v_Scale; -varying float v_BorderRadius; +varying vec4 v_BorderRadius; varying float v_BorderWidth; @@ -21,9 +21,11 @@ void main() { vec2 p_Pos = i_Pos * u_Scale; vec2 p_Scale = i_Scale * u_Scale; - float i_BorderRadius = min( - i_BorderRadius, - min(i_Scale.x, i_Scale.y) / 2.0 + vec4 i_BorderRadius = vec4( + min(i_BorderRadius.x, min(i_Scale.x, i_Scale.y) / 2.0), + min(i_BorderRadius.y, min(i_Scale.x, i_Scale.y) / 2.0), + min(i_BorderRadius.z, min(i_Scale.x, i_Scale.y) / 2.0), + min(i_BorderRadius.w, min(i_Scale.x, i_Scale.y) / 2.0) ); mat4 i_Transform = mat4( -- cgit From 15f21641b7a27bbfb99f9f9f5d21b84445173900 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 8 Nov 2022 04:51:45 +0100 Subject: Fix casing of `border_radius` in `quad` shader --- glow/src/shader/core/quad.frag | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'glow') diff --git a/glow/src/shader/core/quad.frag b/glow/src/shader/core/quad.frag index d036ea1a..71147aa5 100644 --- a/glow/src/shader/core/quad.frag +++ b/glow/src/shader/core/quad.frag @@ -53,7 +53,7 @@ void main() { vec2 fragCoord = vec2(gl_FragCoord.x, u_ScreenHeight - gl_FragCoord.y); - float borderRadius = selectBorderRadius( + float border_radius = selectBorderRadius( v_BorderRadius, fragCoord, (v_Pos + v_Scale * 0.5).xy @@ -61,7 +61,7 @@ void main() { // TODO: Remove branching (?) if(v_BorderWidth > 0.0) { - float internal_border = max(borderRadius - v_BorderWidth, 0.0); + float internal_border = max(border_radius - v_BorderWidth, 0.0); float internal_distance = fDistance( fragCoord, @@ -85,11 +85,11 @@ void main() { fragCoord, v_Pos, v_Scale, - borderRadius + border_radius ); float radius_alpha = - 1.0 - smoothstep(max(borderRadius - 0.5, 0.0), borderRadius + 0.5, d); + 1.0 - smoothstep(max(border_radius - 0.5, 0.0), border_radius + 0.5, d); gl_FragColor = vec4(mixed_color.xyz, mixed_color.w * radius_alpha); } -- cgit From 9841d1938142cb453495a50e4a88059c6eae3074 Mon Sep 17 00:00:00 2001 From: bungoboingo Date: Tue, 8 Nov 2022 11:32:27 -0800 Subject: Fixed issues with old GL versions ( <= 2.1 ) --- glow/src/shader/common/gradient.frag | 32 ++++++++++++++++---------------- glow/src/shader/common/triangle.frag | 2 +- glow/src/triangle/gradient.rs | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'glow') diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag index 42d0201f..9af0cb6e 100644 --- a/glow/src/shader/common/gradient.frag +++ b/glow/src/shader/common/gradient.frag @@ -1,20 +1,20 @@ #ifdef GL_ES - #ifdef GL_FRAGMENT_PRECISION_HIGH - precision highp float; - #else - precision mediump float; - #endif +#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 +layout (location = 0) out vec4 fragColor; +#define gl_FragColor fragColor #endif in vec2 raw_position; uniform vec4 gradient_direction; -uniform uint color_stops_size; +uniform int color_stops_size; // GLSL does not support dynamically sized arrays without SSBOs so this is capped to 16 stops //stored as color(vec4) -> offset(vec4) sequentially; uniform vec4 color_stops[32]; @@ -28,23 +28,23 @@ void main() { vec2 unit = normalize(gradient_vec); float coord_offset = dot(unit, current_vec) / length(gradient_vec); //if a gradient has a start/end stop that is identical, the mesh will have a transparent fill - fragColor = vec4(0.0, 0.0, 0.0, 0.0); + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); float min_offset = color_stops[1].x; - float max_offset = color_stops[color_stops_size - 1u].x; + float max_offset = color_stops[color_stops_size - 1].x; - for (uint i = 0u; i < color_stops_size - 2u; i += 2u) { - float curr_offset = color_stops[i+1u].x; - float next_offset = color_stops[i+3u].x; + for (int i = 0; i < color_stops_size - 2; i += 2) { + float curr_offset = color_stops[i+1].x; + float next_offset = color_stops[i+3].x; if (coord_offset <= min_offset) { //current coordinate is before the first defined offset, set it to the start color - fragColor = color_stops[0]; + gl_FragColor = color_stops[0]; } if (curr_offset <= coord_offset && coord_offset <= next_offset) { //current fragment is between the current offset processing & the next one, interpolate colors - fragColor = mix(color_stops[i], color_stops[i+2u], smoothstep( + gl_FragColor = mix(color_stops[i], color_stops[i+2], smoothstep( curr_offset, next_offset, coord_offset @@ -53,7 +53,7 @@ void main() { if (coord_offset >= max_offset) { //current coordinate is before the last defined offset, set it to the last color - fragColor = color_stops[color_stops_size - 2u]; + gl_FragColor = color_stops[color_stops_size - 2]; } } } diff --git a/glow/src/shader/common/triangle.frag b/glow/src/shader/common/triangle.frag index ead40fe5..8260f6a6 100644 --- a/glow/src/shader/common/triangle.frag +++ b/glow/src/shader/common/triangle.frag @@ -14,5 +14,5 @@ out vec4 fragColor; uniform vec4 color; void main() { - fragColor = color; + gl_FragColor = color; } diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs index 5225612e..d5f26877 100644 --- a/glow/src/triangle/gradient.rs +++ b/glow/src/triangle/gradient.rs @@ -71,14 +71,14 @@ impl Program { linear.end.y, ); - gl.uniform_1_u32( + gl.uniform_1_i32( Some( &self .uniform_data .uniform_locations .color_stops_size_location, ), - (linear.color_stops.len() * 2) as u32, + (linear.color_stops.len() * 2) as i32, ); let mut stops = [0.0; 128]; -- cgit From b0e8bafb6c51666e8b15531001263097ae7d7c0e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 10 Nov 2022 01:20:11 +0100 Subject: Bump versions :tada: --- glow/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'glow') diff --git a/glow/Cargo.toml b/glow/Cargo.toml index a50fd375..0351b480 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_glow" -version = "0.3.0" +version = "0.4.0" authors = ["Héctor Ramón Jiménez "] edition = "2021" description = "A glow renderer for iced" @@ -34,11 +34,11 @@ bytemuck = "1.4" log = "0.4" [dependencies.iced_native] -version = "0.5" +version = "0.6" path = "../native" [dependencies.iced_graphics] -version = "0.3" +version = "0.4" path = "../graphics" features = ["font-fallback", "font-icons", "opengl"] -- cgit From a6298ba12c038d5eaddca9327abb385aa72a82e9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 10 Nov 2022 18:14:40 +0100 Subject: Fix outdated links in documentation --- glow/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/src/lib.rs b/glow/src/lib.rs index e3690a69..e6ca0562 100644 --- a/glow/src/lib.rs +++ b/glow/src/lib.rs @@ -3,7 +3,7 @@ //! ![The native path of the Iced ecosystem](https://github.com/iced-rs/iced/blob/0525d76ff94e828b7b21634fa94a747022001c83/docs/graphs/native.png?raw=true) //! //! [`glow`]: https://github.com/grovesNL/glow -//! [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native +//! [`iced_native`]: https://github.com/iced-rs/iced/tree/0.5/native #![doc( html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" )] -- cgit From 23299a555f8b7e908a6a14915307792a7cf97b9a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 10 Nov 2022 18:15:10 +0100 Subject: Bump versions :tada: --- glow/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/Cargo.toml b/glow/Cargo.toml index 0351b480..1977f4b6 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_glow" -version = "0.4.0" +version = "0.4.1" authors = ["Héctor Ramón Jiménez "] edition = "2021" description = "A glow renderer for iced" -- cgit From 365f37a3ae10e7aff407b84050f77da10820866e Mon Sep 17 00:00:00 2001 From: bungoboingo Date: Thu, 10 Nov 2022 14:43:38 -0800 Subject: Added conditional configurations for WASM target for gradients & storage buffers, since storage buffers are not supported on wgpu WASM target at the moment. --- glow/src/triangle.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 0e27bcf2..cb7ab055 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -141,6 +141,7 @@ impl Pipeline { triangle::Style::Solid(color) => { self.programs.solid.use_program(gl, color, &transform); } + #[cfg(not(target_arch = "wasm32"))] triangle::Style::Gradient(gradient) => { self.programs .gradient -- cgit From 33c3c0c0aa774bb7462e3c42aa04c591a66376a7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 14 Nov 2022 00:02:42 +0100 Subject: Group all solid triangles independently of color --- glow/src/shader/common/gradient.vert | 9 + glow/src/shader/common/solid.frag | 18 ++ glow/src/shader/common/solid.vert | 11 + glow/src/shader/common/triangle.frag | 18 -- glow/src/shader/common/triangle.vert | 9 - glow/src/triangle.rs | 562 +++++++++++++++++++++++++++-------- glow/src/triangle/gradient.rs | 162 ---------- glow/src/triangle/solid.rs | 91 ------ 8 files changed, 484 insertions(+), 396 deletions(-) create mode 100644 glow/src/shader/common/gradient.vert create mode 100644 glow/src/shader/common/solid.frag create mode 100644 glow/src/shader/common/solid.vert delete mode 100644 glow/src/shader/common/triangle.frag delete mode 100644 glow/src/shader/common/triangle.vert delete mode 100644 glow/src/triangle/gradient.rs delete mode 100644 glow/src/triangle/solid.rs (limited to 'glow') diff --git a/glow/src/shader/common/gradient.vert b/glow/src/shader/common/gradient.vert new file mode 100644 index 00000000..fe505997 --- /dev/null +++ b/glow/src/shader/common/gradient.vert @@ -0,0 +1,9 @@ +uniform mat4 u_Transform; + +in vec2 i_Position; +out vec2 raw_position; + +void main() { + gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0); + raw_position = i_Position; +} diff --git a/glow/src/shader/common/solid.frag b/glow/src/shader/common/solid.frag new file mode 100644 index 00000000..174ffdd3 --- /dev/null +++ b/glow/src/shader/common/solid.frag @@ -0,0 +1,18 @@ +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#endif + +#ifdef HIGHER_THAN_300 +out vec4 fragColor; +#define gl_FragColor fragColor +#endif + +in vec4 v_Color; + +void main() { + gl_FragColor = v_Color; +} diff --git a/glow/src/shader/common/solid.vert b/glow/src/shader/common/solid.vert new file mode 100644 index 00000000..59ed88e5 --- /dev/null +++ b/glow/src/shader/common/solid.vert @@ -0,0 +1,11 @@ +uniform mat4 u_Transform; + +in vec2 i_Position; +in vec4 i_Color; + +out vec4 v_Color; + +void main() { + gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0); + v_Color = i_Color; +} diff --git a/glow/src/shader/common/triangle.frag b/glow/src/shader/common/triangle.frag deleted file mode 100644 index 8260f6a6..00000000 --- a/glow/src/shader/common/triangle.frag +++ /dev/null @@ -1,18 +0,0 @@ -#ifdef GL_ES -#ifdef GL_FRAGMENT_PRECISION_HIGH -precision highp float; -#else -precision mediump float; -#endif -#endif - -#ifdef HIGHER_THAN_300 -out vec4 fragColor; -#define gl_FragColor fragColor -#endif - -uniform vec4 color; - -void main() { - gl_FragColor = color; -} diff --git a/glow/src/shader/common/triangle.vert b/glow/src/shader/common/triangle.vert deleted file mode 100644 index fe505997..00000000 --- a/glow/src/shader/common/triangle.vert +++ /dev/null @@ -1,9 +0,0 @@ -uniform mat4 u_Transform; - -in vec2 i_Position; -out vec2 raw_position; - -void main() { - gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0); - raw_position = i_Position; -} diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index cb7ab055..849a7272 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -1,74 +1,49 @@ //! Draw meshes of triangles. -mod gradient; -mod solid; - use crate::program; use crate::Transformation; +use iced_graphics::gradient::Gradient; use iced_graphics::layer::mesh::{self, Mesh}; -use iced_graphics::triangle::{self, Vertex2D}; +use iced_graphics::triangle::{ColoredVertex2D, Vertex2D}; use glow::HasContext; use std::marker::PhantomData; #[derive(Debug)] pub(crate) struct Pipeline { - vertex_array: ::VertexArray, - vertices: Buffer, indices: Buffer, - programs: ProgramList, -} - -#[derive(Debug)] -struct ProgramList { solid: solid::Program, gradient: gradient::Program, } impl Pipeline { pub fn new(gl: &glow::Context, shader_version: &program::Version) -> Self { - let vertex_array = - unsafe { gl.create_vertex_array().expect("Create vertex array") }; - - unsafe { - gl.bind_vertex_array(Some(vertex_array)); - } - - let vertices = unsafe { - Buffer::new( - gl, - glow::ARRAY_BUFFER, - glow::DYNAMIC_DRAW, - std::mem::size_of::() as usize, - ) - }; - - let indices = unsafe { + let mut indices = unsafe { Buffer::new( gl, glow::ELEMENT_ARRAY_BUFFER, glow::DYNAMIC_DRAW, - std::mem::size_of::() as usize, + 1000, ) }; + let solid = solid::Program::new(gl, shader_version); + let gradient = gradient::Program::new(gl, shader_version); + unsafe { - let stride = std::mem::size_of::() as i32; + gl.bind_vertex_array(Some(solid.vertex_array)); + indices.bind(gl, 0); - gl.enable_vertex_attrib_array(0); - gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, stride, 0); + gl.bind_vertex_array(Some(gradient.vertex_array)); + indices.bind(gl, 0); gl.bind_vertex_array(None); - }; + } Self { - vertex_array, - vertices, indices, - programs: ProgramList { - solid: solid::Program::new(gl, shader_version), - gradient: gradient::Program::new(gl, shader_version), - }, + solid, + gradient, } } @@ -83,50 +58,83 @@ impl Pipeline { unsafe { gl.enable(glow::MULTISAMPLE); gl.enable(glow::SCISSOR_TEST); - gl.bind_vertex_array(Some(self.vertex_array)) } - //count the total amount of vertices & indices we need to handle - let (total_vertices, total_indices) = mesh::attribute_count_of(meshes); + // Count the total amount of vertices & indices we need to handle + let count = mesh::attribute_count_of(meshes); // 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); + self.indices.bind(gl, count.indices); } // We upload all the vertices and indices upfront - let mut vertex_offset = 0; + let mut solid_vertex_offset = 0; + let mut gradient_vertex_offset = 0; let mut index_offset = 0; for mesh in meshes { - unsafe { - gl.buffer_sub_data_u8_slice( - glow::ARRAY_BUFFER, - (vertex_offset * std::mem::size_of::()) as i32, - bytemuck::cast_slice(&mesh.buffers.vertices), - ); + let indices = mesh.indices(); + unsafe { gl.buffer_sub_data_u8_slice( glow::ELEMENT_ARRAY_BUFFER, (index_offset * std::mem::size_of::()) as i32, - bytemuck::cast_slice(&mesh.buffers.indices), + bytemuck::cast_slice(indices), ); - vertex_offset += mesh.buffers.vertices.len(); - index_offset += mesh.buffers.indices.len(); + index_offset += indices.len(); + } + + match mesh { + Mesh::Solid { buffers, .. } => { + unsafe { + self.solid.vertices.bind(gl, count.solid_vertices); + + gl.buffer_sub_data_u8_slice( + glow::ARRAY_BUFFER, + (solid_vertex_offset + * std::mem::size_of::()) + as i32, + bytemuck::cast_slice(&buffers.vertices), + ); + } + + solid_vertex_offset += buffers.vertices.len(); + } + Mesh::Gradient { buffers, .. } => { + unsafe { + self.gradient + .vertices + .bind(gl, count.gradient_vertices); + + gl.buffer_sub_data_u8_slice( + glow::ARRAY_BUFFER, + (gradient_vertex_offset + * std::mem::size_of::()) + as i32, + bytemuck::cast_slice(&buffers.vertices), + ); + } + + gradient_vertex_offset += buffers.vertices.len(); + } } } // Then we draw each mesh using offsets - let mut last_vertex = 0; + let mut last_solid_vertex = 0; + let mut last_gradient_vertex = 0; let mut last_index = 0; for mesh in meshes { - let transform = transformation - * Transformation::translate(mesh.origin.x, mesh.origin.y); + let indices = mesh.indices(); + let origin = mesh.origin(); - let clip_bounds = (mesh.clip_bounds * scale_factor).snap(); + let transform = + transformation * Transformation::translate(origin.x, origin.y); + + let clip_bounds = (mesh.clip_bounds() * scale_factor).snap(); unsafe { gl.scissor( @@ -136,30 +144,126 @@ impl Pipeline { clip_bounds.width as i32, clip_bounds.height as i32, ); + } + + match mesh { + Mesh::Solid { buffers, .. } => unsafe { + gl.use_program(Some(self.solid.program)); + gl.bind_vertex_array(Some(self.solid.vertex_array)); + + if transform != self.solid.uniforms.transform { + gl.uniform_matrix_4_f32_slice( + Some(&self.solid.uniforms.transform_location), + false, + transform.as_ref(), + ); - match mesh.style { - triangle::Style::Solid(color) => { - self.programs.solid.use_program(gl, color, &transform); + self.solid.uniforms.transform = transform; } - #[cfg(not(target_arch = "wasm32"))] - triangle::Style::Gradient(gradient) => { - self.programs - .gradient - .use_program(gl, gradient, &transform); + + gl.draw_elements_base_vertex( + glow::TRIANGLES, + indices.len() as i32, + glow::UNSIGNED_INT, + (last_index * std::mem::size_of::()) as i32, + last_solid_vertex as i32, + ); + + last_solid_vertex += buffers.vertices.len(); + }, + Mesh::Gradient { + buffers, gradient, .. + } => unsafe { + gl.use_program(Some(self.gradient.program)); + gl.bind_vertex_array(Some(self.gradient.vertex_array)); + + if transform != self.gradient.uniforms.transform { + gl.uniform_matrix_4_f32_slice( + Some(&self.gradient.uniforms.locations.transform), + false, + transform.as_ref(), + ); + + self.gradient.uniforms.transform = transform; } - } - gl.draw_elements_base_vertex( - glow::TRIANGLES, - mesh.buffers.indices.len() as i32, - glow::UNSIGNED_INT, - (last_index * std::mem::size_of::()) as i32, - last_vertex as i32, - ); + if &self.gradient.uniforms.gradient != *gradient { + match gradient { + Gradient::Linear(linear) => { + gl.uniform_4_f32( + Some( + &self + .gradient + .uniforms + .locations + .gradient_direction, + ), + linear.start.x, + linear.start.y, + linear.end.x, + linear.end.y, + ); + + gl.uniform_1_i32( + Some( + &self + .gradient + .uniforms + .locations + .color_stops_size, + ), + (linear.color_stops.len() * 2) as i32, + ); + + 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 + .gradient + .uniforms + .locations + .color_stops, + ), + &stops, + ); + } + } + + self.gradient.uniforms.gradient = (*gradient).clone(); + } - last_vertex += mesh.buffers.vertices.len(); - last_index += mesh.buffers.indices.len(); + gl.draw_elements_base_vertex( + glow::TRIANGLES, + indices.len() as i32, + glow::UNSIGNED_INT, + (last_index * std::mem::size_of::()) as i32, + last_gradient_vertex as i32, + ); + + last_gradient_vertex += buffers.vertices.len(); + }, } + + last_index += indices.len(); } unsafe { @@ -170,47 +274,8 @@ impl Pipeline { } } -/// A simple shader program. Uses [`triangle.vert`] for its vertex shader and only binds position -/// attribute location. -pub(super) fn program( - gl: &glow::Context, - shader_version: &program::Version, - fragment_shader: &'static str, -) -> ::Program { - unsafe { - let vertex_shader = program::Shader::vertex( - gl, - shader_version, - include_str!("shader/common/triangle.vert"), - ); - - let fragment_shader = - program::Shader::fragment(gl, shader_version, fragment_shader); - - program::create( - gl, - &[vertex_shader, fragment_shader], - &[(0, "i_Position")], - ) - } -} - -pub fn set_transform( - gl: &glow::Context, - location: ::UniformLocation, - transform: Transformation, -) { - unsafe { - gl.uniform_matrix_4_f32_slice( - Some(&location), - false, - transform.as_ref(), - ); - } -} - #[derive(Debug)] -struct Buffer { +pub struct Buffer { raw: ::Buffer, target: u32, usage: u32, @@ -254,3 +319,268 @@ impl Buffer { } } } + +mod solid { + use crate::program; + use crate::triangle; + use glow::{Context, HasContext, NativeProgram}; + use iced_graphics::triangle::ColoredVertex2D; + use iced_graphics::Transformation; + + #[derive(Debug)] + pub struct Program { + pub program: ::Program, + pub vertex_array: ::VertexArray, + pub vertices: triangle::Buffer, + pub uniforms: Uniforms, + } + + impl Program { + pub fn new(gl: &Context, shader_version: &program::Version) -> Self { + let program = unsafe { + let vertex_shader = program::Shader::vertex( + gl, + shader_version, + include_str!("shader/common/solid.vert"), + ); + + let fragment_shader = program::Shader::fragment( + gl, + shader_version, + include_str!("shader/common/solid.frag"), + ); + + program::create( + gl, + &[vertex_shader, fragment_shader], + &[(0, "i_Position"), (1, "i_Color")], + ) + }; + + let vertex_array = unsafe { + gl.create_vertex_array().expect("Create vertex array") + }; + + let vertices = unsafe { + triangle::Buffer::new( + gl, + glow::ARRAY_BUFFER, + glow::DYNAMIC_DRAW, + 1000, + ) + }; + + unsafe { + gl.bind_vertex_array(Some(vertex_array)); + + let stride = std::mem::size_of::() as i32; + + 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); + }; + + Self { + program, + vertex_array, + vertices, + uniforms: Uniforms::new(gl, program), + } + } + } + + #[derive(Debug)] + pub struct Uniforms { + pub transform: Transformation, + pub transform_location: ::UniformLocation, + } + + impl Uniforms { + fn new(gl: &Context, program: NativeProgram) -> Self { + let transform = Transformation::identity(); + let transform_location = + unsafe { gl.get_uniform_location(program, "u_Transform") } + .expect("Solid - Get u_Transform."); + + unsafe { + gl.use_program(Some(program)); + + gl.uniform_matrix_4_f32_slice( + Some(&transform_location), + false, + transform.as_ref(), + ); + + gl.use_program(None); + } + + Self { + transform, + transform_location, + } + } + } +} + +mod gradient { + use crate::program; + use crate::triangle; + use glow::{Context, HasContext, NativeProgram}; + use iced_graphics::gradient::{self, Gradient}; + use iced_graphics::triangle::Vertex2D; + use iced_graphics::Transformation; + + #[derive(Debug)] + pub struct Program { + pub program: ::Program, + pub vertex_array: ::VertexArray, + pub vertices: triangle::Buffer, + pub uniforms: Uniforms, + } + + impl Program { + pub fn new(gl: &Context, shader_version: &program::Version) -> Self { + let program = unsafe { + let vertex_shader = program::Shader::vertex( + gl, + shader_version, + include_str!("shader/common/gradient.vert"), + ); + + let fragment_shader = program::Shader::fragment( + gl, + shader_version, + include_str!("shader/common/gradient.frag"), + ); + + program::create( + gl, + &[vertex_shader, fragment_shader], + &[(0, "i_Position")], + ) + }; + + let vertex_array = unsafe { + gl.create_vertex_array().expect("Create vertex array") + }; + + let vertices = unsafe { + triangle::Buffer::new( + gl, + glow::ARRAY_BUFFER, + glow::DYNAMIC_DRAW, + 1000, + ) + }; + + unsafe { + gl.bind_vertex_array(Some(vertex_array)); + + let stride = std::mem::size_of::() as i32; + + gl.enable_vertex_attrib_array(0); + gl.vertex_attrib_pointer_f32( + 0, + 2, + glow::FLOAT, + false, + stride, + 0, + ); + + gl.bind_vertex_array(None); + }; + + Self { + program, + vertex_array, + vertices, + uniforms: Uniforms::new(gl, program), + } + } + } + + #[derive(Debug)] + pub struct Uniforms { + pub gradient: Gradient, + pub transform: Transformation, + pub locations: Locations, + } + + #[derive(Debug)] + pub struct Locations { + pub gradient_direction: ::UniformLocation, + pub color_stops_size: ::UniformLocation, + //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1 + pub color_stops: ::UniformLocation, + pub transform: ::UniformLocation, + } + + impl Uniforms { + fn new(gl: &Context, program: NativeProgram) -> Self { + let gradient_direction = unsafe { + gl.get_uniform_location(program, "gradient_direction") + } + .expect("Gradient - Get gradient_direction."); + + let color_stops_size = + unsafe { gl.get_uniform_location(program, "color_stops_size") } + .expect("Gradient - Get color_stops_size."); + + let color_stops = unsafe { + gl.get_uniform_location(program, "color_stops") + .expect("Gradient - Get color_stops.") + }; + + let transform = Transformation::identity(); + let transform_location = + unsafe { gl.get_uniform_location(program, "u_Transform") } + .expect("Solid - Get u_Transform."); + + unsafe { + gl.use_program(Some(program)); + + gl.uniform_matrix_4_f32_slice( + Some(&transform_location), + false, + transform.as_ref(), + ); + + gl.use_program(None); + } + + Self { + gradient: Gradient::Linear(gradient::Linear { + start: Default::default(), + end: Default::default(), + color_stops: vec![], + }), + transform: Transformation::identity(), + locations: Locations { + gradient_direction, + color_stops_size, + color_stops, + transform: transform_location, + }, + } + } + } +} diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs deleted file mode 100644 index d5f26877..00000000 --- a/glow/src/triangle/gradient.rs +++ /dev/null @@ -1,162 +0,0 @@ -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: ::Program, - pub uniform_data: UniformData, -} - -#[derive(Debug)] -pub struct UniformData { - gradient: Gradient, - transform: Transformation, - uniform_locations: UniformLocations, -} - -#[derive(Debug)] -struct UniformLocations { - gradient_direction_location: ::UniformLocation, - color_stops_size_location: ::UniformLocation, - //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1 - color_stops_location: ::UniformLocation, - transform_location: ::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_i32( - Some( - &self - .uniform_data - .uniform_locations - .color_stops_size_location, - ), - (linear.color_stops.len() * 2) as i32, - ); - - 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 deleted file mode 100644 index fb3d40c3..00000000 --- a/glow/src/triangle/solid.rs +++ /dev/null @@ -1,91 +0,0 @@ -use crate::program::Version; -use crate::{triangle, Color}; -use glow::{Context, HasContext, NativeProgram}; -use iced_graphics::Transformation; - -#[derive(Debug)] -pub struct Program { - program: ::Program, - uniform_data: UniformData, -} - -#[derive(Debug)] -struct UniformData { - pub color: Color, - pub color_location: ::UniformLocation, - pub transform: Transformation, - pub transform_location: ::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) - } -} -- cgit From c81eaf5f8d8db41e9bb96419bc39684a9978c232 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 16 Nov 2022 09:31:29 +0100 Subject: Replace magic constants in `glow::triangle` --- glow/src/triangle.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'glow') diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 849a7272..d0205e08 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -9,6 +9,9 @@ use iced_graphics::triangle::{ColoredVertex2D, Vertex2D}; use glow::HasContext; use std::marker::PhantomData; +const DEFAULT_VERTICES: usize = 1_000; +const DEFAULT_INDICES: usize = 1_000; + #[derive(Debug)] pub(crate) struct Pipeline { indices: Buffer, @@ -23,7 +26,7 @@ impl Pipeline { gl, glow::ELEMENT_ARRAY_BUFFER, glow::DYNAMIC_DRAW, - 1000, + DEFAULT_INDICES, ) }; @@ -366,7 +369,7 @@ mod solid { gl, glow::ARRAY_BUFFER, glow::DYNAMIC_DRAW, - 1000, + super::DEFAULT_VERTICES, ) }; @@ -487,7 +490,7 @@ mod gradient { gl, glow::ARRAY_BUFFER, glow::DYNAMIC_DRAW, - 1000, + super::DEFAULT_VERTICES, ) }; -- cgit From 751ffb590053d713ea376893a1d9050514b8ffe1 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Wed, 23 Nov 2022 13:37:59 -0500 Subject: fix: scissor layout bounds for images --- glow/src/backend.rs | 2 +- glow/src/image.rs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 1a41d540..c663869e 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -129,7 +129,7 @@ impl Backend { * Transformation::scale(scale_factor, scale_factor); self.image_pipeline - .draw(gl, scaled, scale_factor, &layer.images); + .draw(gl, scaled, scale_factor, &layer.images, bounds); } if !layer.text.is_empty() { diff --git a/glow/src/image.rs b/glow/src/image.rs index f906cd4c..234583e9 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -14,6 +14,7 @@ use iced_graphics::image::raster; use iced_graphics::image::vector; use iced_graphics::layer; +use iced_graphics::Rectangle; use iced_graphics::Size; use glow::HasContext; @@ -144,11 +145,13 @@ impl Pipeline { transformation: Transformation, _scale_factor: f32, images: &[layer::Image], + layer_bounds: Rectangle, ) { unsafe { gl.use_program(Some(self.program)); gl.bind_vertex_array(Some(self.vertex_array)); gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vertex_buffer)); + gl.enable(glow::SCISSOR_TEST); } #[cfg(feature = "image")] @@ -187,6 +190,13 @@ impl Pipeline { }; unsafe { + gl.scissor( + layer_bounds.x as i32, + layer_bounds.y as i32, + layer_bounds.width as i32, + layer_bounds.height as i32, + ); + if let Some(storage::Entry { texture, .. }) = entry { gl.bind_texture(glow::TEXTURE_2D, Some(*texture)) } else { @@ -213,6 +223,7 @@ impl Pipeline { gl.bind_buffer(glow::ARRAY_BUFFER, None); gl.bind_vertex_array(None); gl.use_program(None); + gl.disable(glow::SCISSOR_TEST); } } -- cgit From 84c5ee7fb2d716e1d3c35a53a2cd33fcc6fafc3a Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Wed, 23 Nov 2022 13:40:06 -0500 Subject: cargo fmt --- glow/src/backend.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index c663869e..645c5faf 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -128,8 +128,13 @@ impl Backend { let scaled = transformation * Transformation::scale(scale_factor, scale_factor); - self.image_pipeline - .draw(gl, scaled, scale_factor, &layer.images, bounds); + self.image_pipeline.draw( + gl, + scaled, + scale_factor, + &layer.images, + bounds, + ); } if !layer.text.is_empty() { -- cgit From efc00b2f412865b975088002cbe3c927ef662e10 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Wed, 23 Nov 2022 14:46:57 -0500 Subject: fix: adjust y position of scissor rectangle --- glow/src/backend.rs | 1 + glow/src/image.rs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/src/backend.rs b/glow/src/backend.rs index 645c5faf..416c3b94 100644 --- a/glow/src/backend.rs +++ b/glow/src/backend.rs @@ -130,6 +130,7 @@ impl Backend { self.image_pipeline.draw( gl, + target_height, scaled, scale_factor, &layer.images, diff --git a/glow/src/image.rs b/glow/src/image.rs index 234583e9..955fd1ab 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -142,6 +142,7 @@ impl Pipeline { pub fn draw( &mut self, mut gl: &glow::Context, + target_height: u32, transformation: Transformation, _scale_factor: f32, images: &[layer::Image], @@ -192,7 +193,8 @@ impl Pipeline { unsafe { gl.scissor( layer_bounds.x as i32, - layer_bounds.y as i32, + (target_height - (layer_bounds.y + layer_bounds.height)) + as i32, layer_bounds.width as i32, layer_bounds.height as i32, ); -- cgit From b205a663471a8170d7b30cc59894425c09bea563 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 6 Dec 2022 04:34:00 +0100 Subject: Remove `appearance` from `Handle` ... and pass it directly to `Renderer::draw` instead. --- glow/src/image.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/src/image.rs b/glow/src/image.rs index 955fd1ab..c32b2162 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -172,11 +172,16 @@ impl Pipeline { layer::Image::Raster { handle: _, bounds } => (None, bounds), #[cfg(feature = "svg")] - layer::Image::Vector { handle, bounds } => { + layer::Image::Vector { + handle, + color, + bounds, + } => { let size = [bounds.width, bounds.height]; ( vector_cache.upload( handle, + *color, size, _scale_factor, &mut gl, -- cgit From 4c61f12768cdbe728b1dd4a074e36fb6a69534ab Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 7 Dec 2022 04:38:00 +0100 Subject: Bump versions :tada: --- glow/Cargo.toml | 6 +++--- glow/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'glow') diff --git a/glow/Cargo.toml b/glow/Cargo.toml index 1977f4b6..f69ce48a 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_glow" -version = "0.4.1" +version = "0.5.0" authors = ["Héctor Ramón Jiménez "] edition = "2021" description = "A glow renderer for iced" @@ -34,11 +34,11 @@ bytemuck = "1.4" log = "0.4" [dependencies.iced_native] -version = "0.6" +version = "0.7" path = "../native" [dependencies.iced_graphics] -version = "0.4" +version = "0.5" path = "../graphics" features = ["font-fallback", "font-icons", "opengl"] diff --git a/glow/src/lib.rs b/glow/src/lib.rs index e6ca0562..710ac36d 100644 --- a/glow/src/lib.rs +++ b/glow/src/lib.rs @@ -3,7 +3,7 @@ //! ![The native path of the Iced ecosystem](https://github.com/iced-rs/iced/blob/0525d76ff94e828b7b21634fa94a747022001c83/docs/graphs/native.png?raw=true) //! //! [`glow`]: https://github.com/grovesNL/glow -//! [`iced_native`]: https://github.com/iced-rs/iced/tree/0.5/native +//! [`iced_native`]: https://github.com/iced-rs/iced/tree/0.6/native #![doc( html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" )] -- cgit From e9576edfef66e65dd939166fa277bde1f7151ee7 Mon Sep 17 00:00:00 2001 From: Ben Wallis Date: Sun, 11 Dec 2022 12:23:04 +0000 Subject: Fixed iced_glow crate compilation when image feature is enabled and the svg feature is disabled --- glow/src/image.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glow') diff --git a/glow/src/image.rs b/glow/src/image.rs index c32b2162..521a01e7 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -192,7 +192,7 @@ impl Pipeline { } #[cfg(not(feature = "svg"))] - layer::Image::Vector { handle: _, bounds } => (None, bounds), + layer::Image::Vector { bounds, .. } => (None, bounds), }; unsafe { -- cgit