diff options
author | 2022-11-14 00:02:42 +0100 | |
---|---|---|
committer | 2022-11-16 09:24:16 +0100 | |
commit | 33c3c0c0aa774bb7462e3c42aa04c591a66376a7 (patch) | |
tree | 08ea046e6ac8a9ad43a7ef1f56256a056a4a4d6c /glow | |
parent | 5b0dfcd0b0a9f25a3004dbc2cad3dea8220a76a1 (diff) | |
download | iced-33c3c0c0aa774bb7462e3c42aa04c591a66376a7.tar.gz iced-33c3c0c0aa774bb7462e3c42aa04c591a66376a7.tar.bz2 iced-33c3c0c0aa774bb7462e3c42aa04c591a66376a7.zip |
Group all solid triangles independently of color
Diffstat (limited to 'glow')
-rw-r--r-- | glow/src/shader/common/gradient.vert (renamed from glow/src/shader/common/triangle.vert) | 0 | ||||
-rw-r--r-- | glow/src/shader/common/solid.frag (renamed from glow/src/shader/common/triangle.frag) | 4 | ||||
-rw-r--r-- | glow/src/shader/common/solid.vert | 11 | ||||
-rw-r--r-- | glow/src/triangle.rs | 562 | ||||
-rw-r--r-- | glow/src/triangle/gradient.rs | 162 | ||||
-rw-r--r-- | glow/src/triangle/solid.rs | 91 |
6 files changed, 459 insertions, 371 deletions
diff --git a/glow/src/shader/common/triangle.vert b/glow/src/shader/common/gradient.vert index fe505997..fe505997 100644 --- a/glow/src/shader/common/triangle.vert +++ b/glow/src/shader/common/gradient.vert diff --git a/glow/src/shader/common/triangle.frag b/glow/src/shader/common/solid.frag index 8260f6a6..174ffdd3 100644 --- a/glow/src/shader/common/triangle.frag +++ b/glow/src/shader/common/solid.frag @@ -11,8 +11,8 @@ out vec4 fragColor; #define gl_FragColor fragColor #endif -uniform vec4 color; +in vec4 v_Color; void main() { - gl_FragColor = color; + 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/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: <glow::Context as HasContext>::VertexArray, - vertices: Buffer<Vertex2D>, indices: Buffer<u32>, - 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::<Vertex2D>() as usize, - ) - }; - - let indices = unsafe { + let mut indices = unsafe { Buffer::new( gl, glow::ELEMENT_ARRAY_BUFFER, glow::DYNAMIC_DRAW, - std::mem::size_of::<u32>() 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::<Vertex2D>() 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::<Vertex2D>()) 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::<u32>()) 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::<ColoredVertex2D>()) + 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::<Vertex2D>()) + 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::<u32>()) 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::<u32>()) 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::<u32>()) 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, -) -> <glow::Context as HasContext>::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: <glow::Context as HasContext>::UniformLocation, - transform: Transformation, -) { - unsafe { - gl.uniform_matrix_4_f32_slice( - Some(&location), - false, - transform.as_ref(), - ); - } -} - #[derive(Debug)] -struct Buffer<T> { +pub struct Buffer<T> { raw: <glow::Context as HasContext>::Buffer, target: u32, usage: u32, @@ -254,3 +319,268 @@ impl<T> Buffer<T> { } } } + +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: <Context as HasContext>::Program, + pub vertex_array: <glow::Context as HasContext>::VertexArray, + pub vertices: triangle::Buffer<ColoredVertex2D>, + 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::<ColoredVertex2D>() 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: <Context as HasContext>::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: <Context as HasContext>::Program, + pub vertex_array: <glow::Context as HasContext>::VertexArray, + pub vertices: triangle::Buffer<Vertex2D>, + 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::<Vertex2D>() 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: <Context as HasContext>::UniformLocation, + pub color_stops_size: <Context as HasContext>::UniformLocation, + //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1 + pub color_stops: <Context as HasContext>::UniformLocation, + pub transform: <Context as HasContext>::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: <Context as HasContext>::Program, - pub uniform_data: UniformData, -} - -#[derive(Debug)] -pub struct UniformData { - gradient: Gradient, - transform: Transformation, - uniform_locations: UniformLocations, -} - -#[derive(Debug)] -struct UniformLocations { - gradient_direction_location: <Context as HasContext>::UniformLocation, - color_stops_size_location: <Context as HasContext>::UniformLocation, - //currently the maximum number of stops is 16 due to lack of SSBO in GL2.1 - color_stops_location: <Context as HasContext>::UniformLocation, - transform_location: <Context as HasContext>::UniformLocation, -} - -impl Program { - pub fn new(gl: &Context, shader_version: &Version) -> Self { - let program = triangle::program( - gl, - shader_version, - include_str!("../shader/common/gradient.frag"), - ); - - Self { - program, - uniform_data: UniformData::new(gl, program), - } - } - - pub fn write_uniforms( - &mut self, - gl: &Context, - gradient: &Gradient, - transform: &Transformation, - ) { - if transform != &self.uniform_data.transform { - triangle::set_transform( - gl, - self.uniform_data.uniform_locations.transform_location, - *transform, - ); - } - - if &self.uniform_data.gradient != gradient { - match gradient { - Gradient::Linear(linear) => unsafe { - gl.uniform_4_f32( - Some( - &self - .uniform_data - .uniform_locations - .gradient_direction_location, - ), - linear.start.x, - linear.start.y, - linear.end.x, - linear.end.y, - ); - - gl.uniform_1_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: <Context as HasContext>::Program, - uniform_data: UniformData, -} - -#[derive(Debug)] -struct UniformData { - pub color: Color, - pub color_location: <Context as HasContext>::UniformLocation, - pub transform: Transformation, - pub transform_location: <Context as HasContext>::UniformLocation, -} - -impl UniformData { - fn new(gl: &Context, program: NativeProgram) -> Self { - Self { - color: Color::TRANSPARENT, - color_location: unsafe { - gl.get_uniform_location(program, "color") - } - .expect("Solid - Get color."), - transform: Transformation::identity(), - transform_location: unsafe { - gl.get_uniform_location(program, "u_Transform") - } - .expect("Solid - Get u_Transform."), - } - } -} - -impl Program { - pub fn new(gl: &Context, shader_version: &Version) -> Self { - let program = triangle::program( - gl, - shader_version, - include_str!("../shader/common/triangle.frag"), - ); - - Self { - program, - uniform_data: UniformData::new(gl, program), - } - } - - pub fn write_uniforms( - &mut self, - gl: &Context, - color: &Color, - transform: &Transformation, - ) { - if transform != &self.uniform_data.transform { - triangle::set_transform( - gl, - self.uniform_data.transform_location, - *transform, - ) - } - - if color != &self.uniform_data.color { - let [r, g, b, a] = color.into_linear(); - - unsafe { - gl.uniform_4_f32( - Some(&self.uniform_data.color_location), - r, - g, - b, - a, - ); - } - - self.uniform_data.color = *color; - } - } - - pub fn use_program( - &mut self, - gl: &Context, - color: &Color, - transform: &Transformation, - ) { - unsafe { gl.use_program(Some(self.program)) } - self.write_uniforms(gl, color, transform) - } -} |