From 1deb53fa9cd08b43fb2b77f5866aa9056ffd8a77 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 25 Feb 2020 18:37:23 -0800 Subject: [PATCH] Implement the remaining Porter-Duff compositing operators --- canvas/src/lib.rs | 85 +++++++-- content/src/effects.rs | 40 +++-- renderer/src/gpu/renderer.rs | 162 +++++++++--------- renderer/src/gpu/shaders.rs | 24 --- resources/shaders/gl3/filter_basic.fs.glsl | 3 +- .../shaders/gl3/tile_alpha_porterduff.fs.glsl | 96 ----------- resources/shaders/gl3/tile_solid.fs.glsl | 3 +- resources/shaders/metal/filter_basic.fs.metal | 3 +- .../metal/tile_alpha_porterduff.fs.metal | 80 --------- resources/shaders/metal/tile_solid.fs.metal | 3 +- shaders/Makefile | 1 - shaders/filter_basic.fs.glsl | 3 +- shaders/tile_alpha_porterduff.fs.glsl | 51 ------ shaders/tile_solid.fs.glsl | 3 +- 14 files changed, 195 insertions(+), 362 deletions(-) delete mode 100644 resources/shaders/gl3/tile_alpha_porterduff.fs.glsl delete mode 100644 resources/shaders/metal/tile_alpha_porterduff.fs.metal delete mode 100644 shaders/tile_alpha_porterduff.fs.glsl diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 161b12e2..16c24143 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -12,11 +12,11 @@ use pathfinder_color::ColorU; use pathfinder_content::dash::OutlineDash; -use pathfinder_content::effects::BlendMode; +use pathfinder_content::effects::{BlendMode, CompositeOp, Effects, Filter}; use pathfinder_content::fill::FillRule; use pathfinder_content::gradient::Gradient; use pathfinder_content::outline::{ArcDirection, Contour, Outline}; -use pathfinder_content::pattern::Pattern; +use pathfinder_content::pattern::{Pattern, RenderTargetId}; use pathfinder_content::stroke::{LineCap, LineJoin as StrokeLineJoin}; use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; use pathfinder_geometry::line_segment::LineSegment2F; @@ -24,7 +24,7 @@ use pathfinder_geometry::vector::Vector2F; use pathfinder_geometry::rect::RectF; use pathfinder_geometry::transform2d::Transform2F; use pathfinder_renderer::paint::{Paint, PaintId}; -use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, Scene}; +use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, RenderTarget, Scene}; use std::borrow::Cow; use std::default::Default; use std::f32::consts::PI; @@ -233,8 +233,11 @@ impl CanvasRenderingContext2D { fn push_path(&mut self, outline: Outline, paint_id: PaintId, fill_rule: FillRule) { let clip_path = self.current_state.clip_path; let blend_mode = self.current_state.global_composite_operation.to_blend_mode(); + let composite_op = self.current_state.global_composite_operation.to_composite_op(); if !self.current_state.shadow_paint.is_fully_transparent() { + let render_target_id = self.push_render_target_if_needed(composite_op); + let paint = self.current_state.resolve_paint(&self.current_state.shadow_paint); let paint_id = self.scene.push_paint(&paint); @@ -245,15 +248,44 @@ impl CanvasRenderingContext2D { clip_path, fill_rule, blend_mode, - String::new())) + String::new())); + + self.composite_render_target_if_needed(composite_op, render_target_id); } + let render_target_id = self.push_render_target_if_needed(composite_op); + self.scene.push_path(DrawPath::new(outline, paint_id, clip_path, fill_rule, blend_mode, - String::new())) + String::new())); + + self.composite_render_target_if_needed(composite_op, render_target_id); + } + + fn push_render_target_if_needed(&mut self, composite_op: Option) + -> Option { + if composite_op.is_none() { + return None; + } + + let render_target_size = self.scene.view_box().size().ceil().to_i32(); + Some(self.scene.push_render_target(RenderTarget::new(render_target_size, String::new()))) + } + + fn composite_render_target_if_needed(&mut self, + composite_op: Option, + render_target_id: Option) { + let composite_op = match composite_op { + None => return, + Some(composite_op) => composite_op, + }; + + self.scene.pop_render_target(); + self.scene.draw_render_target(render_target_id.unwrap(), + Effects::new(Filter::Composite(composite_op))); } // Transformations @@ -532,6 +564,7 @@ pub enum CompositeOperation { DestinationOut, DestinationAtop, Lighter, + Copy, Xor, Multiply, Screen, @@ -553,14 +586,9 @@ pub enum CompositeOperation { impl CompositeOperation { fn to_blend_mode(self) -> BlendMode { match self { - CompositeOperation::SourceOver => BlendMode::SrcOver, - CompositeOperation::SourceIn => BlendMode::SrcIn, - CompositeOperation::SourceOut => BlendMode::SrcOut, CompositeOperation::SourceAtop => BlendMode::SrcAtop, CompositeOperation::DestinationOver => BlendMode::DestOver, - CompositeOperation::DestinationIn => BlendMode::DestIn, CompositeOperation::DestinationOut => BlendMode::DestOut, - CompositeOperation::DestinationAtop => BlendMode::DestAtop, CompositeOperation::Xor => BlendMode::Xor, CompositeOperation::Lighter => BlendMode::Lighter, CompositeOperation::Multiply => BlendMode::Multiply, @@ -578,6 +606,43 @@ impl CompositeOperation { CompositeOperation::Saturation => BlendMode::Saturation, CompositeOperation::Color => BlendMode::Color, CompositeOperation::Luminosity => BlendMode::Luminosity, + CompositeOperation::SourceOver | + CompositeOperation::SourceIn | + CompositeOperation::SourceOut | + CompositeOperation::DestinationIn | + CompositeOperation::DestinationAtop | + CompositeOperation::Copy => BlendMode::SrcOver, + } + } + + fn to_composite_op(self) -> Option { + match self { + CompositeOperation::SourceIn => Some(CompositeOp::SrcIn), + CompositeOperation::SourceOut => Some(CompositeOp::SrcOut), + CompositeOperation::DestinationIn => Some(CompositeOp::DestIn), + CompositeOperation::DestinationAtop => Some(CompositeOp::DestAtop), + CompositeOperation::Copy => Some(CompositeOp::Copy), + CompositeOperation::SourceOver | + CompositeOperation::SourceAtop | + CompositeOperation::DestinationOver | + CompositeOperation::DestinationOut | + CompositeOperation::Xor | + CompositeOperation::Lighter | + CompositeOperation::Multiply | + CompositeOperation::Screen | + CompositeOperation::Overlay | + CompositeOperation::Darken | + CompositeOperation::Lighten | + CompositeOperation::ColorDodge | + CompositeOperation::ColorBurn | + CompositeOperation::HardLight | + CompositeOperation::SoftLight | + CompositeOperation::Difference | + CompositeOperation::Exclusion | + CompositeOperation::Hue | + CompositeOperation::Saturation | + CompositeOperation::Color | + CompositeOperation::Luminosity => None, } } } diff --git a/content/src/effects.rs b/content/src/effects.rs index b7d00845..db900795 100644 --- a/content/src/effects.rs +++ b/content/src/effects.rs @@ -38,8 +38,12 @@ pub struct Effects { /// The shader that should be used when compositing this layer onto its destination. #[derive(Clone, Copy, Debug)] pub enum Filter { - /// A compositing operation. - Composite(CompositeOp), + /// A Porter-Duff compositing operation. + /// + /// The compositing operations here are the ones that can't be blend modes because they can + /// clear parts of the destination not overlapped by the source, plus the regular source-over. + Composite(CompositeOp), + /// Performs postprocessing operations useful for monochrome text. Text { /// The foreground color of the text. @@ -59,9 +63,24 @@ pub enum Filter { pub enum CompositeOp { /// The default. SrcOver, + /// No regions are enabled. + Clear, + /// Only the source will be present. + Copy, + /// The source that overlaps the destination replaces the destination. + SrcIn, + /// Destination which overlaps the source replaces the source. + DestIn, + /// Source is placed where it falls outside of the destination. + SrcOut, + /// Destination which overlaps the source replaces the source. Source is placed elsewhere. + DestAtop, } /// Blend modes that can be applied to individual paths. +/// +/// All blend modes preserve parts of the destination that are not overlapped by the source path. +/// Other Porter-Duff compositing operations are `CompositeOp`s. #[derive(Clone, Copy, PartialEq, Debug)] pub enum BlendMode { // Supported by GPU blender @@ -75,12 +94,6 @@ pub enum BlendMode { Lighten, Darken, - // Porter-Duff - SrcIn, - DestIn, - SrcOut, - DestAtop, - // Overlay Multiply, Screen, @@ -124,6 +137,13 @@ impl Default for BlendMode { } } +impl Effects { + #[inline] + pub fn new(filter: Filter) -> Effects { + Effects { filter } + } +} + impl BlendMode { /// Whether the backdrop is irrelevant when applying this blend mode (i.e. destination blend /// factor is zero when source alpha is one). @@ -138,10 +158,6 @@ impl BlendMode { BlendMode::Lighter | BlendMode::Lighten | BlendMode::Darken | - BlendMode::SrcIn | - BlendMode::DestIn | - BlendMode::SrcOut | - BlendMode::DestAtop | BlendMode::Multiply | BlendMode::Screen | BlendMode::HardLight | diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index dd3374b6..8c5250c7 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -12,13 +12,12 @@ use crate::gpu::debug::DebugUIPresenter; use crate::gpu::options::{DestFramebuffer, RendererOptions}; use crate::gpu::shaders::{AlphaTileBlendModeProgram, AlphaTileDodgeBurnProgram}; use crate::gpu::shaders::{AlphaTileHSLProgram, AlphaTileOverlayProgram}; -use crate::gpu::shaders::{AlphaTilePorterDuffProgram, AlphaTileProgram, AlphaTileVertexArray}; -use crate::gpu::shaders::{CopyTileProgram, CopyTileVertexArray, FillProgram, FillVertexArray}; -use crate::gpu::shaders::{FilterBasicProgram, FilterBasicVertexArray, FilterTextProgram}; -use crate::gpu::shaders::{FilterTextVertexArray, MAX_FILLS_PER_BATCH, MaskTileProgram}; -use crate::gpu::shaders::{MaskTileVertexArray, ReprojectionProgram, ReprojectionVertexArray}; -use crate::gpu::shaders::{SolidTileProgram, SolidTileVertexArray}; -use crate::gpu::shaders::{StencilProgram, StencilVertexArray}; +use crate::gpu::shaders::{AlphaTileProgram, AlphaTileVertexArray, CopyTileProgram}; +use crate::gpu::shaders::{CopyTileVertexArray, FillProgram, FillVertexArray, FilterBasicProgram}; +use crate::gpu::shaders::{FilterBasicVertexArray, FilterTextProgram, FilterTextVertexArray}; +use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MaskTileProgram, MaskTileVertexArray}; +use crate::gpu::shaders::{ReprojectionProgram, ReprojectionVertexArray, SolidTileProgram}; +use crate::gpu::shaders::{SolidTileVertexArray, StencilProgram, StencilVertexArray}; use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData, PaintPageContents}; use crate::gpu_data::{PaintPageId, RenderCommand, SolidTileVertex}; use crate::options::BoundingQuad; @@ -63,11 +62,6 @@ const OVERLAY_BLEND_MODE_SCREEN: i32 = 1; const OVERLAY_BLEND_MODE_HARD_LIGHT: i32 = 2; const OVERLAY_BLEND_MODE_OVERLAY: i32 = 3; -const PORTER_DUFF_FACTOR_ZERO: i32 = 0; -const PORTER_DUFF_FACTOR_DEST_ALPHA: i32 = 1; -const PORTER_DUFF_FACTOR_SRC_ALPHA: i32 = 2; -const PORTER_DUFF_FACTOR_ONE_MINUS_DEST_ALPHA: i32 = 3; - pub struct Renderer where D: Device, @@ -84,7 +78,6 @@ where copy_tile_program: CopyTileProgram, solid_tile_program: SolidTileProgram, alpha_tile_program: AlphaTileProgram, - alpha_tile_porterduff_program: AlphaTilePorterDuffProgram, alpha_tile_overlay_program: AlphaTileOverlayProgram, alpha_tile_dodgeburn_program: AlphaTileDodgeBurnProgram, alpha_tile_softlight_program: AlphaTileBlendModeProgram, @@ -96,7 +89,6 @@ where copy_tile_vertex_array: CopyTileVertexArray, solid_tile_vertex_array: SolidTileVertexArray, alpha_tile_vertex_array: AlphaTileVertexArray, - alpha_tile_porterduff_vertex_array: AlphaTileVertexArray, alpha_tile_overlay_vertex_array: AlphaTileVertexArray, alpha_tile_dodgeburn_vertex_array: AlphaTileVertexArray, alpha_tile_softlight_vertex_array: AlphaTileVertexArray, @@ -173,7 +165,6 @@ where let copy_tile_program = CopyTileProgram::new(&device, resources); let solid_tile_program = SolidTileProgram::new(&device, resources); let alpha_tile_program = AlphaTileProgram::new(&device, resources); - let alpha_tile_porterduff_program = AlphaTilePorterDuffProgram::new(&device, resources); let alpha_tile_overlay_program = AlphaTileOverlayProgram::new(&device, resources); let alpha_tile_dodgeburn_program = AlphaTileDodgeBurnProgram::new(&device, resources); let alpha_tile_softlight_program = AlphaTileBlendModeProgram::new(&device, @@ -238,12 +229,6 @@ where &alpha_tile_vertex_buffer, &quads_vertex_indices_buffer, ); - let alpha_tile_porterduff_vertex_array = AlphaTileVertexArray::new( - &device, - &alpha_tile_porterduff_program.alpha_tile_blend_mode_program.alpha_tile_program, - &alpha_tile_vertex_buffer, - &quads_vertex_indices_buffer, - ); let alpha_tile_overlay_vertex_array = AlphaTileVertexArray::new( &device, &alpha_tile_overlay_program.alpha_tile_blend_mode_program.alpha_tile_program, @@ -341,7 +326,6 @@ where copy_tile_program, solid_tile_program, alpha_tile_program, - alpha_tile_porterduff_program, alpha_tile_overlay_program, alpha_tile_dodgeburn_program, alpha_tile_softlight_program, @@ -353,7 +337,6 @@ where copy_tile_vertex_array, solid_tile_vertex_array, alpha_tile_vertex_array, - alpha_tile_porterduff_vertex_array, alpha_tile_overlay_vertex_array, alpha_tile_dodgeburn_vertex_array, alpha_tile_softlight_vertex_array, @@ -791,12 +774,6 @@ where let (alpha_tile_program, alpha_tile_vertex_array) = match blend_mode_program { BlendModeProgram::Regular => (&self.alpha_tile_program, &self.alpha_tile_vertex_array), - BlendModeProgram::PorterDuff => { - (&self.alpha_tile_porterduff_program - .alpha_tile_blend_mode_program - .alpha_tile_program, - &self.alpha_tile_porterduff_vertex_array) - } BlendModeProgram::Overlay => { (&self.alpha_tile_overlay_program.alpha_tile_blend_mode_program.alpha_tile_program, &self.alpha_tile_overlay_vertex_array) @@ -853,11 +830,6 @@ where match blend_mode_program { BlendModeProgram::Regular => {} - BlendModeProgram::PorterDuff => { - self.set_uniforms_for_porter_duff_blend_mode(&mut textures, - &mut uniforms, - blend_mode); - } BlendModeProgram::Overlay => { self.set_uniforms_for_overlay_blend_mode(&mut textures, &mut uniforms, blend_mode); } @@ -915,38 +887,6 @@ where UniformData::TextureUnit(textures.len() as u32 - 1))); } - fn set_uniforms_for_porter_duff_blend_mode<'a>( - &'a self, - textures: &mut Vec<&'a D::Texture>, - uniforms: &mut Vec<(&'a D::Uniform, UniformData)>, - blend_mode: BlendMode) { - let (src_factor, dest_factor) = match blend_mode { - BlendMode::SrcIn => { - (PORTER_DUFF_FACTOR_DEST_ALPHA, PORTER_DUFF_FACTOR_ZERO) - } - BlendMode::DestIn => { - (PORTER_DUFF_FACTOR_ZERO, PORTER_DUFF_FACTOR_SRC_ALPHA) - } - BlendMode::SrcOut => { - (PORTER_DUFF_FACTOR_ONE_MINUS_DEST_ALPHA, PORTER_DUFF_FACTOR_ZERO) - } - BlendMode::DestAtop => { - (PORTER_DUFF_FACTOR_ONE_MINUS_DEST_ALPHA, PORTER_DUFF_FACTOR_SRC_ALPHA) - } - _ => unreachable!(), - }; - - uniforms.push((&self.alpha_tile_porterduff_program.src_factor_uniform, - UniformData::Int(src_factor))); - uniforms.push((&self.alpha_tile_porterduff_program.dest_factor_uniform, - UniformData::Int(dest_factor))); - - self.set_uniforms_for_blend_mode(textures, - uniforms, - &self.alpha_tile_porterduff_program - .alpha_tile_blend_mode_program); - } - fn set_uniforms_for_overlay_blend_mode<'a>(&'a self, textures: &mut Vec<&'a D::Texture>, uniforms: &mut Vec<(&'a D::Uniform, UniformData)>, @@ -1057,7 +997,7 @@ where let paint_texture = self.paint_texture(paint_page); textures.push(paint_texture); uniforms.push((&self.solid_tile_program.paint_texture_uniform, - UniformData::TextureUnit(0))); + UniformData::TextureUnit(0))); self.device.draw_elements(6 * tile_count, &RenderState { target: &self.draw_render_target(), @@ -1216,9 +1156,7 @@ where (&self.filter_basic_program.source_uniform, UniformData::TextureUnit(0)), ]; - let blend_state = match composite_op { - CompositeOp::SrcOver => BlendMode::SrcOver.to_blend_state(), - }; + let blend_state = composite_op.to_blend_state(); self.device.draw_elements(6, &RenderState { target: &self.draw_render_target(), @@ -1530,11 +1468,11 @@ struct RenderTargetInfo where D: Device { must_preserve_contents: bool, } -trait BlendModeExt { +trait ToBlendState { fn to_blend_state(self) -> Option; } -impl BlendModeExt for BlendMode { +impl ToBlendState for BlendMode { fn to_blend_state(self) -> Option { match self { BlendMode::Clear => { @@ -1618,10 +1556,6 @@ impl BlendModeExt for BlendMode { op: BlendOp::Min, }) } - BlendMode::SrcIn | - BlendMode::DestIn | - BlendMode::SrcOut | - BlendMode::DestAtop | BlendMode::Multiply | BlendMode::Screen | BlendMode::HardLight | @@ -1642,10 +1576,79 @@ impl BlendModeExt for BlendMode { } } +impl ToBlendState for CompositeOp { + fn to_blend_state(self) -> Option { + match self { + CompositeOp::Clear => { + Some(BlendState { + src_rgb_factor: BlendFactor::Zero, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::Zero, + dest_alpha_factor: BlendFactor::OneMinusSrcAlpha, + ..BlendState::default() + }) + } + CompositeOp::Copy => { + Some(BlendState { + src_rgb_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::Zero, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::Zero, + ..BlendState::default() + }) + } + CompositeOp::SrcOver => { + Some(BlendState { + src_rgb_factor: BlendFactor::One, + dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, + src_alpha_factor: BlendFactor::One, + dest_alpha_factor: BlendFactor::OneMinusSrcAlpha, + ..BlendState::default() + }) + } + CompositeOp::SrcIn => { + Some(BlendState { + src_rgb_factor: BlendFactor::DestAlpha, + dest_rgb_factor: BlendFactor::Zero, + src_alpha_factor: BlendFactor::DestAlpha, + dest_alpha_factor: BlendFactor::Zero, + ..BlendState::default() + }) + } + CompositeOp::DestIn => { + Some(BlendState { + src_rgb_factor: BlendFactor::Zero, + dest_rgb_factor: BlendFactor::SrcAlpha, + src_alpha_factor: BlendFactor::Zero, + dest_alpha_factor: BlendFactor::SrcAlpha, + ..BlendState::default() + }) + } + CompositeOp::SrcOut => { + Some(BlendState { + src_rgb_factor: BlendFactor::OneMinusDestAlpha, + dest_rgb_factor: BlendFactor::Zero, + src_alpha_factor: BlendFactor::OneMinusDestAlpha, + dest_alpha_factor: BlendFactor::Zero, + ..BlendState::default() + }) + } + CompositeOp::DestAtop => { + Some(BlendState { + src_rgb_factor: BlendFactor::OneMinusDestAlpha, + dest_rgb_factor: BlendFactor::SrcAlpha, + src_alpha_factor: BlendFactor::OneMinusDestAlpha, + dest_alpha_factor: BlendFactor::SrcAlpha, + ..BlendState::default() + }) + } + } + } +} + #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) enum BlendModeProgram { Regular, - PorterDuff, Overlay, DodgeBurn, SoftLight, @@ -1666,10 +1669,6 @@ impl BlendModeProgram { BlendMode::Lighter | BlendMode::Lighten | BlendMode::Darken => BlendModeProgram::Regular, - BlendMode::SrcIn | - BlendMode::DestIn | - BlendMode::SrcOut | - BlendMode::DestAtop => BlendModeProgram::PorterDuff, BlendMode::Multiply | BlendMode::Screen | BlendMode::HardLight | @@ -1689,7 +1688,6 @@ impl BlendModeProgram { pub(crate) fn needs_readable_framebuffer(self) -> bool { match self { BlendModeProgram::Regular => false, - BlendModeProgram::PorterDuff | BlendModeProgram::Overlay | BlendModeProgram::DodgeBurn | BlendModeProgram::SoftLight | diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index ee6504f8..3ac090b8 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -465,30 +465,6 @@ impl AlphaTileBlendModeProgram where D: Device { } } -pub struct AlphaTilePorterDuffProgram where D: Device { - pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram, - pub dest_factor_uniform: D::Uniform, - pub src_factor_uniform: D::Uniform, -} - -impl AlphaTilePorterDuffProgram where D: Device { - pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTilePorterDuffProgram { - let alpha_tile_blend_mode_program = - AlphaTileBlendModeProgram::new(device, resources, "tile_alpha_porterduff"); - let dest_factor_uniform = - device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, - "DestFactor"); - let src_factor_uniform = - device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, - "SrcFactor"); - AlphaTilePorterDuffProgram { - alpha_tile_blend_mode_program, - dest_factor_uniform, - src_factor_uniform, - } - } -} - pub struct AlphaTileHSLProgram where D: Device { pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram, pub blend_hsl_uniform: D::Uniform, diff --git a/resources/shaders/gl3/filter_basic.fs.glsl b/resources/shaders/gl3/filter_basic.fs.glsl index eb653f42..c0c14856 100644 --- a/resources/shaders/gl3/filter_basic.fs.glsl +++ b/resources/shaders/gl3/filter_basic.fs.glsl @@ -26,6 +26,7 @@ in vec2 vTexCoord; out vec4 oFragColor; void main(){ - oFragColor = texture(uSource, vTexCoord); + vec4 color = texture(uSource, vTexCoord); + oFragColor = vec4(color . rgb * color . a, color . a); } diff --git a/resources/shaders/gl3/tile_alpha_porterduff.fs.glsl b/resources/shaders/gl3/tile_alpha_porterduff.fs.glsl deleted file mode 100644 index d44ae323..00000000 --- a/resources/shaders/gl3/tile_alpha_porterduff.fs.glsl +++ /dev/null @@ -1,96 +0,0 @@ -#version {{version}} -// Automatically generated from files in pathfinder/shaders/. Do not edit! - - - - - - - - - - - - - - -#extension GL_GOOGLE_include_directive : enable - - - - - - -precision highp float; - -uniform int uDestFactor; -uniform int uSrcFactor; - -out vec4 oFragColor; - - - - - - - - - - - - -uniform sampler2D uStencilTexture; -uniform sampler2D uPaintTexture; -uniform sampler2D uDest; -uniform vec2 uFramebufferSize; - -in vec2 vColorTexCoord; -in vec2 vMaskTexCoord; - - -vec4 sampleSrcColor(){ - float coverage = texture(uStencilTexture, vMaskTexCoord). r; - vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); -} - -vec4 sampleDestColor(){ - vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize; - return texture(uDest, destTexCoord); -} - - -vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){ - return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb + - srcRGBA . a * destRGBA . a * blendedRGB + - (1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb, - 1.0); -} - -vec3 select3(bvec3 cond, vec3 a, vec3 b){ - return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z); -} - - -vec4 getFactor(int factor, vec4 destRGBA, vec4 srcRGBA){ - if(factor == 0) - return vec4(0.0); - if(factor == 1) - return vec4(destRGBA . a); - if(factor == 2) - return vec4(srcRGBA . a); - return vec4(1.0 - destRGBA . a); -} - -void main(){ - vec4 srcRGBA = sampleSrcColor(); - vec4 destRGBA = sampleDestColor(); - - vec4 destFactor = getFactor(uDestFactor, destRGBA, srcRGBA); - vec4 srcFactor = getFactor(uSrcFactor, destRGBA, srcRGBA); - - vec4 blended = destFactor * destRGBA * vec4(destRGBA . aaa, 1.0)+ - srcFactor * srcRGBA * vec4(srcRGBA . aaa, 1.0); - oFragColor = blended; -} - diff --git a/resources/shaders/gl3/tile_solid.fs.glsl b/resources/shaders/gl3/tile_solid.fs.glsl index c4a548a3..09dd8db2 100644 --- a/resources/shaders/gl3/tile_solid.fs.glsl +++ b/resources/shaders/gl3/tile_solid.fs.glsl @@ -21,6 +21,7 @@ in vec2 vColorTexCoord; out vec4 oFragColor; void main(){ - oFragColor = texture(uPaintTexture, vColorTexCoord); + vec4 color = texture(uPaintTexture, vColorTexCoord); + oFragColor = vec4(color . rgb * color . a, color . a); } diff --git a/resources/shaders/metal/filter_basic.fs.metal b/resources/shaders/metal/filter_basic.fs.metal index a5f680a1..721dcf38 100644 --- a/resources/shaders/metal/filter_basic.fs.metal +++ b/resources/shaders/metal/filter_basic.fs.metal @@ -23,7 +23,8 @@ struct main0_in fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) { main0_out out = {}; - out.oFragColor = spvDescriptorSet0.uSource.sample(spvDescriptorSet0.uSourceSmplr, in.vTexCoord); + float4 color = spvDescriptorSet0.uSource.sample(spvDescriptorSet0.uSourceSmplr, in.vTexCoord); + out.oFragColor = float4(color.xyz * color.w, color.w); return out; } diff --git a/resources/shaders/metal/tile_alpha_porterduff.fs.metal b/resources/shaders/metal/tile_alpha_porterduff.fs.metal deleted file mode 100644 index cd414300..00000000 --- a/resources/shaders/metal/tile_alpha_porterduff.fs.metal +++ /dev/null @@ -1,80 +0,0 @@ -// Automatically generated from files in pathfinder/shaders/. Do not edit! -#pragma clang diagnostic ignored "-Wmissing-prototypes" - -#include -#include - -using namespace metal; - -struct spvDescriptorSetBuffer0 -{ - texture2d uStencilTexture [[id(0)]]; - sampler uStencilTextureSmplr [[id(1)]]; - texture2d uPaintTexture [[id(2)]]; - sampler uPaintTextureSmplr [[id(3)]]; - constant float2* uFramebufferSize [[id(4)]]; - texture2d uDest [[id(5)]]; - sampler uDestSmplr [[id(6)]]; - constant int* uDestFactor [[id(7)]]; - constant int* uSrcFactor [[id(8)]]; -}; - -struct main0_out -{ - float4 oFragColor [[color(0)]]; -}; - -struct main0_in -{ - float2 vColorTexCoord [[user(locn0)]]; - float2 vMaskTexCoord [[user(locn1)]]; -}; - -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) -{ - float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; - float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); -} - -float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) -{ - float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize; - return uDest.sample(uDestSmplr, destTexCoord); -} - -float4 getFactor(thread const int& factor, thread const float4& destRGBA, thread const float4& srcRGBA) -{ - if (factor == 0) - { - return float4(0.0); - } - if (factor == 1) - { - return float4(destRGBA.w); - } - if (factor == 2) - { - return float4(srcRGBA.w); - } - return float4(1.0 - destRGBA.w); -} - -fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]]) -{ - main0_out out = {}; - float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); - float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); - int param = (*spvDescriptorSet0.uDestFactor); - float4 param_1 = destRGBA; - float4 param_2 = srcRGBA; - float4 destFactor = getFactor(param, param_1, param_2); - int param_3 = (*spvDescriptorSet0.uSrcFactor); - float4 param_4 = destRGBA; - float4 param_5 = srcRGBA; - float4 srcFactor = getFactor(param_3, param_4, param_5); - float4 blended = ((destFactor * destRGBA) * float4(destRGBA.www, 1.0)) + ((srcFactor * srcRGBA) * float4(srcRGBA.www, 1.0)); - out.oFragColor = blended; - return out; -} - diff --git a/resources/shaders/metal/tile_solid.fs.metal b/resources/shaders/metal/tile_solid.fs.metal index 6e961080..f7800819 100644 --- a/resources/shaders/metal/tile_solid.fs.metal +++ b/resources/shaders/metal/tile_solid.fs.metal @@ -23,7 +23,8 @@ struct main0_in fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) { main0_out out = {}; - out.oFragColor = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); + float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); + out.oFragColor = float4(color.xyz * color.w, color.w); return out; } diff --git a/shaders/Makefile b/shaders/Makefile index ceb6b138..f224ab14 100644 --- a/shaders/Makefile +++ b/shaders/Makefile @@ -28,7 +28,6 @@ SHADERS=\ tile_alpha_exclusion.fs.glsl \ tile_alpha_hsl.fs.glsl \ tile_alpha_overlay.fs.glsl \ - tile_alpha_porterduff.fs.glsl \ tile_alpha_softlight.fs.glsl \ tile_copy.fs.glsl \ tile_copy.vs.glsl \ diff --git a/shaders/filter_basic.fs.glsl b/shaders/filter_basic.fs.glsl index ef776b5d..28faf163 100644 --- a/shaders/filter_basic.fs.glsl +++ b/shaders/filter_basic.fs.glsl @@ -24,5 +24,6 @@ in vec2 vTexCoord; out vec4 oFragColor; void main() { - oFragColor = texture(uSource, vTexCoord); + vec4 color = texture(uSource, vTexCoord); + oFragColor = vec4(color.rgb * color.a, color.a); } diff --git a/shaders/tile_alpha_porterduff.fs.glsl b/shaders/tile_alpha_porterduff.fs.glsl deleted file mode 100644 index a5011b67..00000000 --- a/shaders/tile_alpha_porterduff.fs.glsl +++ /dev/null @@ -1,51 +0,0 @@ -#version 330 - -// pathfinder/shaders/tile_alpha_porterduff.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. - -// Porter-Duff blend modes not supported by the standard GPU blender. - -#extension GL_GOOGLE_include_directive : enable - -#define PORTER_DUFF_FACTOR_ZERO 0 -#define PORTER_DUFF_FACTOR_DEST_ALPHA 1 -#define PORTER_DUFF_FACTOR_SRC_ALPHA 2 -#define PORTER_DUFF_FACTOR_ONE_MINUS_DEST_ALPHA 3 - -precision highp float; - -uniform int uDestFactor; -uniform int uSrcFactor; - -out vec4 oFragColor; - -#include "tile_alpha_sample.inc.glsl" - -vec4 getFactor(int factor, vec4 destRGBA, vec4 srcRGBA) { - if (factor == PORTER_DUFF_FACTOR_ZERO) - return vec4(0.0); - if (factor == PORTER_DUFF_FACTOR_DEST_ALPHA) - return vec4(destRGBA.a); - if (factor == PORTER_DUFF_FACTOR_SRC_ALPHA) - return vec4(srcRGBA.a); - return vec4(1.0 - destRGBA.a); -} - -void main() { - vec4 srcRGBA = sampleSrcColor(); - vec4 destRGBA = sampleDestColor(); - - vec4 destFactor = getFactor(uDestFactor, destRGBA, srcRGBA); - vec4 srcFactor = getFactor(uSrcFactor, destRGBA, srcRGBA); - - vec4 blended = destFactor * destRGBA * vec4(destRGBA.aaa, 1.0) + - srcFactor * srcRGBA * vec4(srcRGBA.aaa, 1.0); - oFragColor = blended; -} diff --git a/shaders/tile_solid.fs.glsl b/shaders/tile_solid.fs.glsl index 724b68eb..e3e09f35 100644 --- a/shaders/tile_solid.fs.glsl +++ b/shaders/tile_solid.fs.glsl @@ -19,5 +19,6 @@ in vec2 vColorTexCoord; out vec4 oFragColor; void main() { - oFragColor = texture(uPaintTexture, vColorTexCoord); + vec4 color = texture(uPaintTexture, vColorTexCoord); + oFragColor = vec4(color.rgb * color.a, color.a); }