From 0883f54e2d2bc2c8c991d6326d48bbe61d740647 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 14 Feb 2020 21:55:37 -0800 Subject: [PATCH] Add a separate mask blit step, in preparation for supporting clips. We can elide this in the future if there are no clips, but it isn't a huge performance regression right now, so let's just unconditionally do it. --- renderer/src/builder.rs | 21 ++-- renderer/src/gpu/renderer.rs | 92 ++++++++++++--- renderer/src/gpu/shaders.rs | 119 ++++++++++++++------ renderer/src/gpu_data.rs | 26 ++++- renderer/src/tiles.rs | 48 ++++++-- resources/shaders/gl3/tile_alpha.fs.glsl | 3 +- resources/shaders/gl3/tile_alpha.vs.glsl | 3 - resources/shaders/metal/tile_alpha.fs.metal | 3 +- resources/shaders/metal/tile_alpha.vs.metal | 3 - shaders/Makefile | 2 + shaders/mask_winding.fs.glsl | 24 ++++ shaders/mask_winding.vs.glsl | 26 +++++ shaders/tile_alpha.fs.glsl | 3 +- shaders/tile_alpha.vs.glsl | 3 - 14 files changed, 297 insertions(+), 79 deletions(-) create mode 100644 shaders/mask_winding.fs.glsl create mode 100644 shaders/mask_winding.vs.glsl diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 467bd372..c6183f23 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -11,7 +11,7 @@ //! Packs data onto the GPU. use crate::concurrent::executor::Executor; -use crate::gpu_data::{AlphaTile, FillBatchPrimitive, RenderCommand, TileObjectPrimitive}; +use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, RenderCommand, TileObjectPrimitive}; use crate::options::{PreparedBuildOptions, RenderCommandListener}; use crate::paint::{PaintInfo, PaintMetadata}; use crate::scene::Scene; @@ -106,9 +106,11 @@ impl<'a> SceneBuilder<'a> { } fn cull_tiles(&self, built_objects: Vec) -> CulledTiles { - let mut culled_tiles = CulledTiles { alpha_tiles: vec![] }; + let mut culled_tiles = CulledTiles { mask_tiles: vec![], alpha_tiles: vec![] }; for built_object in built_objects { + culled_tiles.mask_tiles.extend_from_slice(&built_object.mask_tiles); + for alpha_tile in built_object.alpha_tiles { let alpha_tile_coords = alpha_tile.upper_left.tile_position(); if self.z_buffer.test(alpha_tile_coords, @@ -126,6 +128,9 @@ impl<'a> SceneBuilder<'a> { let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths, paint_metadata, 0..path_count); + if !culled_tiles.mask_tiles.is_empty() { + self.listener.send(RenderCommand::RenderMaskTiles(culled_tiles.mask_tiles)); + } if !solid_tiles.is_empty() { self.listener.send(RenderCommand::DrawSolidTiles(solid_tiles)); } @@ -143,6 +148,11 @@ impl<'a> SceneBuilder<'a> { } } +struct CulledTiles { + mask_tiles: Vec, + alpha_tiles: Vec, +} + #[derive(Clone, Copy, Debug, Default)] pub struct TileStats { pub solid_tile_count: u32, @@ -156,7 +166,7 @@ impl ObjectBuilder { let tile_rect = tiles::round_rect_out_to_tile_bounds(bounds); let tiles = DenseTileMap::new(tile_rect); ObjectBuilder { - built_object: BuiltObject { alpha_tiles: vec![] }, + built_object: BuiltObject { mask_tiles: vec![], alpha_tiles: vec![] }, bounds, fills: vec![], tiles, @@ -341,6 +351,7 @@ impl ObjectBuilder { #[derive(Debug)] pub(crate) struct BuiltObject { + pub mask_tiles: Vec, pub alpha_tiles: Vec, } @@ -351,7 +362,3 @@ pub(crate) struct ObjectBuilder { pub tiles: DenseTileMap, pub bounds: RectF, } - -struct CulledTiles { - alpha_tiles: Vec, -} diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 583c681e..b32d890e 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -11,10 +11,12 @@ use crate::gpu::debug::DebugUIPresenter; use crate::gpu::options::{DestFramebuffer, RendererOptions}; use crate::gpu::shaders::{FillProgram, AlphaTileProgram, AlphaTileVertexArray, FillVertexArray}; -use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, PostprocessProgram, PostprocessVertexArray}; -use crate::gpu::shaders::{ReprojectionProgram, ReprojectionVertexArray, SolidTileProgram}; -use crate::gpu::shaders::{SolidTileVertexArray, StencilProgram, StencilVertexArray}; -use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex}; +use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MaskWindingTileProgram, MaskWindingTileVertexArray}; +use crate::gpu::shaders::{PostprocessProgram, PostprocessVertexArray, ReprojectionProgram}; +use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray}; +use crate::gpu::shaders::{StencilProgram, StencilVertexArray}; +use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData}; +use crate::gpu_data::{RenderCommand, SolidTileVertex}; use crate::post::DefringingKernel; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_color::{self as color, ColorF, ColorU}; @@ -55,8 +57,10 @@ where dest_framebuffer: DestFramebuffer, options: RendererOptions, fill_program: FillProgram, + mask_winding_tile_program: MaskWindingTileProgram, solid_tile_program: SolidTileProgram, alpha_tile_program: AlphaTileProgram, + mask_winding_tile_vertex_array: MaskWindingTileVertexArray, solid_tile_vertex_array: SolidTileVertexArray, alpha_tile_vertex_array: AlphaTileVertexArray, area_lut_texture: D::Texture, @@ -65,6 +69,7 @@ where quads_vertex_indices_buffer: D::Buffer, quads_vertex_indices_length: usize, fill_vertex_array: FillVertexArray, + fill_framebuffer: D::Framebuffer, mask_framebuffer: D::Framebuffer, paint_texture: Option, @@ -108,10 +113,9 @@ where options: RendererOptions) -> Renderer { let fill_program = FillProgram::new(&device, resources); - + let mask_winding_tile_program = MaskWindingTileProgram::new(&device, resources); let solid_tile_program = SolidTileProgram::new(&device, resources); let alpha_tile_program = AlphaTileProgram::new(&device, resources); - let postprocess_program = PostprocessProgram::new(&device, resources); let stencil_program = StencilProgram::new(&device, resources); let reprojection_program = ReprojectionProgram::new(&device, resources); @@ -141,6 +145,11 @@ where &quad_vertex_positions_buffer, &quad_vertex_indices_buffer, ); + let mask_winding_tile_vertex_array = MaskWindingTileVertexArray::new( + &device, + &mask_winding_tile_program, + &quads_vertex_indices_buffer, + ); let alpha_tile_vertex_array = AlphaTileVertexArray::new( &device, &alpha_tile_program, @@ -165,10 +174,16 @@ where &quad_vertex_indices_buffer, ); + let fill_framebuffer_size = + Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT); + let fill_framebuffer_texture = + device.create_texture(TextureFormat::R16F, fill_framebuffer_size); + let fill_framebuffer = device.create_framebuffer(fill_framebuffer_texture); + let mask_framebuffer_size = Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT); let mask_framebuffer_texture = - device.create_texture(TextureFormat::R16F, mask_framebuffer_size); + device.create_texture(TextureFormat::R8, mask_framebuffer_size); let mask_framebuffer = device.create_framebuffer(mask_framebuffer_texture); let window_size = dest_framebuffer.window_size(&device); @@ -180,8 +195,10 @@ where dest_framebuffer, options, fill_program, + mask_winding_tile_program, solid_tile_program, alpha_tile_program, + mask_winding_tile_vertex_array, solid_tile_vertex_array, alpha_tile_vertex_array, area_lut_texture, @@ -190,6 +207,7 @@ where quads_vertex_indices_buffer, quads_vertex_indices_length: 0, fill_vertex_array, + fill_framebuffer, mask_framebuffer, paint_texture: None, @@ -239,6 +257,11 @@ where self.draw_buffered_fills(); self.begin_composite_timer_query(); } + RenderCommand::RenderMaskTiles(ref mask_tiles) => { + let count = mask_tiles.len(); + self.upload_mask_tiles(mask_tiles); + self.draw_mask_tiles(count as u32); + } RenderCommand::DrawSolidTiles(ref solid_tile_vertices) => { let count = solid_tile_vertices.len() / 4; self.stats.solid_tile_count += count; @@ -374,6 +397,16 @@ where TextureDataRef::U8(texels)); } + fn upload_mask_tiles(&mut self, mask_tiles: &[MaskTile]) { + self.device.allocate_buffer( + &self.mask_winding_tile_vertex_array.vertex_buffer, + BufferData::Memory(&mask_tiles), + BufferTarget::Vertex, + BufferUploadMode::Dynamic, + ); + self.ensure_index_buffer(mask_tiles.len()); + } + fn upload_solid_tiles(&mut self, solid_tile_vertices: &[SolidTileVertex]) { self.device.allocate_buffer( &self.solid_tile_vertex_array.vertex_buffer, @@ -450,7 +483,7 @@ where let mut clear_color = None; if !self.framebuffer_flags.contains( - FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS) { + FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS) { clear_color = Some(ColorF::default()); }; @@ -459,7 +492,7 @@ where debug_assert!(self.buffered_fills.len() <= u32::MAX as usize); self.device.draw_elements_instanced(6, self.buffered_fills.len() as u32, &RenderState { - target: &RenderTarget::Framebuffer(&self.mask_framebuffer), + target: &RenderTarget::Framebuffer(&self.fill_framebuffer), program: &self.fill_program.program, vertex_array: &self.fill_vertex_array.vertex_array, primitive: Primitive::Triangles, @@ -486,7 +519,7 @@ where self.device.end_timer_query(&timer_query); self.current_timers.stage_0.push(timer_query); - self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS); + self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS); self.buffered_fills.clear(); } @@ -496,6 +529,38 @@ where Transform4F::from_scale(scale).translate(Vector4F::new(-1.0, 1.0, 0.0, 1.0)) } + fn draw_mask_tiles(&mut self, tile_count: u32) { + let clear_color = + if self.framebuffer_flags + .contains(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS) { + None + } else { + Some(ColorF::new(1.0, 1.0, 1.0, 1.0)) + }; + + let textures = vec![self.device.framebuffer_texture(&self.fill_framebuffer)]; + let uniforms = vec![ + (&self.mask_winding_tile_program.mask_texture_uniform, UniformData::TextureUnit(0)), + ]; + + self.device.draw_elements(tile_count * 6, &RenderState { + target: &RenderTarget::Framebuffer(&self.mask_framebuffer), + program: &self.mask_winding_tile_program.program, + vertex_array: &self.mask_winding_tile_vertex_array.vertex_array, + primitive: Primitive::Triangles, + textures: &textures, + uniforms: &uniforms, + viewport: self.mask_viewport(), + options: RenderOptions { + // TODO(pcwalton): MIN blending for masks. + clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, + ..RenderOptions::default() + }, + }); + + self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS); + } + fn draw_alpha_tiles(&mut self, tile_count: u32) { let clear_color = self.clear_color_for_draw_operation(); @@ -937,8 +1002,9 @@ impl Add for RenderTime { bitflags! { struct FramebufferFlags: u8 { - const MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS = 0x01; - const MUST_PRESERVE_POSTPROCESS_FRAMEBUFFER_CONTENTS = 0x02; - const MUST_PRESERVE_DEST_FRAMEBUFFER_CONTENTS = 0x04; + const MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS = 0x01; + const MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS = 0x02; + const MUST_PRESERVE_POSTPROCESS_FRAMEBUFFER_CONTENTS = 0x04; + const MUST_PRESERVE_DEST_FRAMEBUFFER_CONTENTS = 0x08; } } diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index 83ac7e39..f5031326 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -9,13 +9,15 @@ // except according to those terms. use crate::gpu_data::FillBatchPrimitive; -use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType}; +use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass}; +use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType}; use pathfinder_gpu::resources::ResourceLoader; // TODO(pcwalton): Replace with `mem::size_of` calls? const FILL_INSTANCE_SIZE: usize = 8; const SOLID_TILE_VERTEX_SIZE: usize = 12; -const MASK_TILE_VERTEX_SIZE: usize = 16; +const ALPHA_TILE_VERTEX_SIZE: usize = 16; +const MASK_TILE_VERTEX_SIZE: usize = 12; pub const MAX_FILLS_PER_BATCH: usize = 0x4000; @@ -118,39 +120,30 @@ where } } -pub struct AlphaTileVertexArray -where - D: Device, -{ +pub struct MaskWindingTileVertexArray where D: Device { pub vertex_array: D::VertexArray, pub vertex_buffer: D::Buffer, } -impl AlphaTileVertexArray -where - D: Device, -{ - pub fn new( - device: &D, - alpha_tile_program: &AlphaTileProgram, - quads_vertex_indices_buffer: &D::Buffer, - ) -> AlphaTileVertexArray { +impl MaskWindingTileVertexArray where D: Device { + pub fn new(device: &D, + mask_winding_tile_program: &MaskWindingTileProgram, + quads_vertex_indices_buffer: &D::Buffer) + -> MaskWindingTileVertexArray { let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); - let tile_position_attr = - device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap(); - let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, - "ColorTexCoord").unwrap(); - let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, + let position_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "Position") + .unwrap(); + let mask_tex_coord_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "MaskTexCoord").unwrap(); - let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop") + let backdrop_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "Backdrop") .unwrap(); device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor { + device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor { size: 2, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I16, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, stride: MASK_TILE_VERTEX_SIZE, offset: 0, divisor: 0, @@ -165,21 +158,66 @@ where divisor: 0, buffer_index: 0, }); - device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor { - size: 2, - class: VertexAttrClass::FloatNorm, - attr_type: VertexAttrType::U16, - stride: MASK_TILE_VERTEX_SIZE, - offset: 8, - divisor: 0, - buffer_index: 0, - }); device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor { size: 1, class: VertexAttrClass::Int, attr_type: VertexAttrType::I16, stride: MASK_TILE_VERTEX_SIZE, - offset: 12, + offset: 8, + divisor: 0, + buffer_index: 0, + }); + device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index); + + MaskWindingTileVertexArray { vertex_array, vertex_buffer } + } +} + +pub struct AlphaTileVertexArray where D: Device { + pub vertex_array: D::VertexArray, + pub vertex_buffer: D::Buffer, +} + +impl AlphaTileVertexArray where D: Device { + pub fn new( + device: &D, + alpha_tile_program: &AlphaTileProgram, + quads_vertex_indices_buffer: &D::Buffer, + ) -> AlphaTileVertexArray { + let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); + + let tile_position_attr = + device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap(); + let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, + "ColorTexCoord").unwrap(); + let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, + "MaskTexCoord").unwrap(); + + device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex); + device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::Int, + attr_type: VertexAttrType::I16, + stride: ALPHA_TILE_VERTEX_SIZE, + offset: 0, + divisor: 0, + buffer_index: 0, + }); + device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, + stride: ALPHA_TILE_VERTEX_SIZE, + offset: 4, + divisor: 0, + buffer_index: 0, + }); + device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, + stride: ALPHA_TILE_VERTEX_SIZE, + offset: 8, divisor: 0, buffer_index: 0, }); @@ -270,6 +308,19 @@ where } } +pub struct MaskWindingTileProgram where D: Device { + pub program: D::Program, + pub mask_texture_uniform: D::Uniform, +} + +impl MaskWindingTileProgram where D: Device { + pub fn new(device: &D, resources: &dyn ResourceLoader) -> MaskWindingTileProgram { + let program = device.create_program(resources, "mask_winding"); + let mask_texture_uniform = device.get_uniform(&program, "MaskTexture"); + MaskWindingTileProgram { program, mask_texture_uniform } + } +} + pub struct SolidTileProgram where D: Device { pub program: D::Program, pub transform_uniform: D::Uniform, diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 1e1eb221..cd63a8aa 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -22,6 +22,7 @@ pub enum RenderCommand { AddPaintData(PaintData), AddFills(Vec), FlushFills, + RenderMaskTiles(Vec), DrawAlphaTiles(Vec), DrawSolidTiles(Vec), Finish { build_time: Duration }, @@ -69,6 +70,15 @@ pub struct SolidTileVertex { pub pad: u16, } +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct MaskTile { + pub upper_left: MaskTileVertex, + pub upper_right: MaskTileVertex, + pub lower_left: MaskTileVertex, + pub lower_right: MaskTileVertex, +} + #[derive(Clone, Copy, Debug, Default)] #[repr(C)] pub struct AlphaTile { @@ -78,6 +88,17 @@ pub struct AlphaTile { pub lower_right: AlphaTileVertex, } +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct MaskTileVertex { + pub tile_x: u16, + pub tile_y: u16, + pub mask_u: u16, + pub mask_v: u16, + pub backdrop: i16, + pub object_index: u16, +} + #[derive(Clone, Copy, Debug, Default)] #[repr(C)] pub struct AlphaTileVertex { @@ -87,8 +108,8 @@ pub struct AlphaTileVertex { pub mask_v: u16, pub color_u: u16, pub color_v: u16, - pub backdrop: i16, pub object_index: u16, + pub pad: u16, } impl Debug for RenderCommand { @@ -100,6 +121,9 @@ impl Debug for RenderCommand { } RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()), RenderCommand::FlushFills => write!(formatter, "FlushFills"), + RenderCommand::RenderMaskTiles(ref tiles) => { + write!(formatter, "RenderMaskTiles(x{})", tiles.len()) + } RenderCommand::DrawAlphaTiles(ref tiles) => { write!(formatter, "DrawAlphaTiles(x{})", tiles.len()) } diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 09854df9..aea248b9 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -10,7 +10,7 @@ use crate::builder::{ObjectBuilder, SceneBuilder}; use crate::gpu::renderer::MASK_TILES_ACROSS; -use crate::gpu_data::{AlphaTile, AlphaTileVertex, TileObjectPrimitive}; +use crate::gpu_data::{AlphaTile, AlphaTileVertex, MaskTile, MaskTileVertex, TileObjectPrimitive}; use crate::paint::PaintMetadata; use pathfinder_content::outline::{Contour, Outline, PointIndex}; use pathfinder_content::segment::Segment; @@ -124,30 +124,45 @@ impl<'a> Tiler<'a> { } } + self.object_builder.built_object.mask_tiles.push(MaskTile { + upper_left: MaskTileVertex::new(tile.alpha_tile_index as u16, + Vector2I::default(), + self.object_index, + tile.backdrop as i16), + upper_right: MaskTileVertex::new(tile.alpha_tile_index as u16, + Vector2I::new(1, 0), + self.object_index, + tile.backdrop as i16), + lower_left: MaskTileVertex::new(tile.alpha_tile_index as u16, + Vector2I::new(0, 1), + self.object_index, + tile.backdrop as i16), + lower_right: MaskTileVertex::new(tile.alpha_tile_index as u16, + Vector2I::splat(1), + self.object_index, + tile.backdrop as i16), + }); + self.object_builder.built_object.alpha_tiles.push(AlphaTile { upper_left: AlphaTileVertex::new(tile_coords, tile.alpha_tile_index as u16, Vector2I::default(), self.object_index, - tile.backdrop as i16, &self.paint_metadata), upper_right: AlphaTileVertex::new(tile_coords, tile.alpha_tile_index as u16, - Vector2I::new(1, 0), + Vector2I::new(1, 0), self.object_index, - tile.backdrop as i16, &self.paint_metadata), lower_left: AlphaTileVertex::new(tile_coords, tile.alpha_tile_index as u16, Vector2I::new(0, 1), self.object_index, - tile.backdrop as i16, &self.paint_metadata), lower_right: AlphaTileVertex::new(tile_coords, tile.alpha_tile_index as u16, Vector2I::splat(1), self.object_index, - tile.backdrop as i16, &self.paint_metadata), }); } @@ -540,18 +555,33 @@ impl PartialOrd for ActiveEdge { } } +impl MaskTileVertex { + #[inline] + fn new(tile_index: u16, tile_offset: Vector2I, object_index: u16, backdrop: i16) + -> MaskTileVertex { + let mask_uv = calculate_mask_uv(tile_index, tile_offset); + MaskTileVertex { + tile_x: mask_uv.x() as u16, + tile_y: mask_uv.y() as u16, + mask_u: mask_uv.x() as u16, + mask_v: mask_uv.y() as u16, + backdrop, + object_index, + } + } +} + impl AlphaTileVertex { #[inline] fn new(tile_origin: Vector2I, tile_index: u16, tile_offset: Vector2I, object_index: u16, - backdrop: i16, paint_metadata: &PaintMetadata) -> AlphaTileVertex { let tile_position = tile_origin + tile_offset; let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32(); - let mask_uv = calculate_mask_uv(tile_index as u16, tile_offset); + let mask_uv = calculate_mask_uv(tile_index, tile_offset); AlphaTileVertex { tile_x: tile_position.x() as i16, @@ -561,7 +591,7 @@ impl AlphaTileVertex { mask_u: mask_uv.x() as u16, mask_v: mask_uv.y() as u16, object_index, - backdrop, + pad: 0, } } diff --git a/resources/shaders/gl3/tile_alpha.fs.glsl b/resources/shaders/gl3/tile_alpha.fs.glsl index 20a5db4e..ee552817 100644 --- a/resources/shaders/gl3/tile_alpha.fs.glsl +++ b/resources/shaders/gl3/tile_alpha.fs.glsl @@ -20,13 +20,12 @@ uniform vec2 uPaintTextureSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; -in float vBackdrop; in vec4 vColor; out vec4 oFragColor; void main(){ - float coverage = abs(texture(uStencilTexture, vMaskTexCoord). r + vBackdrop); + float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 color = texture(uPaintTexture, vColorTexCoord); oFragColor = vec4(color . rgb, color . a * coverage); } diff --git a/resources/shaders/gl3/tile_alpha.vs.glsl b/resources/shaders/gl3/tile_alpha.vs.glsl index 369895c0..a5ff0ad0 100644 --- a/resources/shaders/gl3/tile_alpha.vs.glsl +++ b/resources/shaders/gl3/tile_alpha.vs.glsl @@ -21,18 +21,15 @@ uniform vec2 uStencilTextureSize; in ivec2 aTilePosition; in vec2 aColorTexCoord; in vec2 aMaskTexCoord; -in int aBackdrop; out vec2 vColorTexCoord; out vec2 vMaskTexCoord; -out float vBackdrop; void main(){ vec2 position = aTilePosition * uTileSize; vMaskTexCoord = aMaskTexCoord; vColorTexCoord = aColorTexCoord; - vBackdrop = float(aBackdrop); gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/metal/tile_alpha.fs.metal b/resources/shaders/metal/tile_alpha.fs.metal index 0d9b7126..8bef5f84 100644 --- a/resources/shaders/metal/tile_alpha.fs.metal +++ b/resources/shaders/metal/tile_alpha.fs.metal @@ -21,13 +21,12 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; - float vBackdrop [[user(locn2)]]; }; fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) { main0_out out = {}; - float coverage = abs(spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x + in.vBackdrop); + float coverage = spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x; float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); out.oFragColor = float4(color.xyz, color.w * coverage); return out; diff --git a/resources/shaders/metal/tile_alpha.vs.metal b/resources/shaders/metal/tile_alpha.vs.metal index df55ea91..1102b8c2 100644 --- a/resources/shaders/metal/tile_alpha.vs.metal +++ b/resources/shaders/metal/tile_alpha.vs.metal @@ -14,7 +14,6 @@ struct main0_out { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; - float vBackdrop [[user(locn2)]]; float4 gl_Position [[position]]; }; @@ -23,7 +22,6 @@ struct main0_in int2 aTilePosition [[attribute(0)]]; float2 aColorTexCoord [[attribute(1)]]; float2 aMaskTexCoord [[attribute(2)]]; - int aBackdrop [[attribute(3)]]; }; vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) @@ -32,7 +30,6 @@ vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize); out.vMaskTexCoord = in.aMaskTexCoord; out.vColorTexCoord = in.aColorTexCoord; - out.vBackdrop = float(in.aBackdrop); out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0); return out; } diff --git a/shaders/Makefile b/shaders/Makefile index b5e8ad4c..3d6c883f 100644 --- a/shaders/Makefile +++ b/shaders/Makefile @@ -11,6 +11,8 @@ SHADERS=\ demo_ground.vs.glsl \ fill.fs.glsl \ fill.vs.glsl \ + mask_winding.fs.glsl \ + mask_winding.vs.glsl \ post.fs.glsl \ post.vs.glsl \ reproject.fs.glsl \ diff --git a/shaders/mask_winding.fs.glsl b/shaders/mask_winding.fs.glsl new file mode 100644 index 00000000..3a72d794 --- /dev/null +++ b/shaders/mask_winding.fs.glsl @@ -0,0 +1,24 @@ +#version 330 + +// pathfinder/shaders/mask_winding.fs.glsl +// +// Copyright © 2020 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +uniform sampler2D uMaskTexture; + +in vec2 vMaskTexCoord; +in float vBackdrop; + +out vec4 oFragColor; + +void main() { + oFragColor = vec4(abs(texture(uMaskTexture, vMaskTexCoord).r + vBackdrop)); +} diff --git a/shaders/mask_winding.vs.glsl b/shaders/mask_winding.vs.glsl new file mode 100644 index 00000000..495df8e1 --- /dev/null +++ b/shaders/mask_winding.vs.glsl @@ -0,0 +1,26 @@ +#version 330 + +// pathfinder/shaders/mask_winding.vs.glsl +// +// Copyright © 2020 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +in vec2 aPosition; +in vec2 aMaskTexCoord; +in int aBackdrop; + +out vec2 vMaskTexCoord; +out float vBackdrop; + +void main() { + vMaskTexCoord = aMaskTexCoord; + vBackdrop = float(aBackdrop); + gl_Position = vec4(mix(vec2(-1.0, -1.0), vec2(1.0, 1.0), aPosition), 0.0, 1.0); +} diff --git a/shaders/tile_alpha.fs.glsl b/shaders/tile_alpha.fs.glsl index ed6f08b0..a1bddfd5 100644 --- a/shaders/tile_alpha.fs.glsl +++ b/shaders/tile_alpha.fs.glsl @@ -18,13 +18,12 @@ uniform vec2 uPaintTextureSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; -in float vBackdrop; in vec4 vColor; out vec4 oFragColor; void main() { - float coverage = abs(texture(uStencilTexture, vMaskTexCoord).r + vBackdrop); + float coverage = texture(uStencilTexture, vMaskTexCoord).r; vec4 color = texture(uPaintTexture, vColorTexCoord); oFragColor = vec4(color.rgb, color.a * coverage); } diff --git a/shaders/tile_alpha.vs.glsl b/shaders/tile_alpha.vs.glsl index 79c0e346..4dc64704 100644 --- a/shaders/tile_alpha.vs.glsl +++ b/shaders/tile_alpha.vs.glsl @@ -19,17 +19,14 @@ uniform vec2 uStencilTextureSize; in ivec2 aTilePosition; in vec2 aColorTexCoord; in vec2 aMaskTexCoord; -in int aBackdrop; out vec2 vColorTexCoord; out vec2 vMaskTexCoord; -out float vBackdrop; void main() { vec2 position = aTilePosition * uTileSize; vMaskTexCoord = aMaskTexCoord; vColorTexCoord = aColorTexCoord; - vBackdrop = float(aBackdrop); gl_Position = uTransform * vec4(position, 0.0, 1.0); }