From 77b3555828bbad20f98def5638917cb02f2091e4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 26 Feb 2020 12:43:07 -0800 Subject: [PATCH] Separate opacity out from paint. This allows `globalAlpha` to work on render targets. --- canvas/src/lib.rs | 42 ++++++------- content/src/gradient.rs | 6 -- content/src/pattern.rs | 23 ------- metal/src/lib.rs | 3 + renderer/src/builder.rs | 8 +++ renderer/src/gpu/shaders.rs | 10 +++ renderer/src/gpu_data.rs | 3 +- renderer/src/paint.rs | 12 ---- renderer/src/scene.rs | 63 ++++++++++++++++--- renderer/src/tiles.rs | 10 +-- resources/shaders/gl3/tile_alpha.fs.glsl | 3 +- resources/shaders/gl3/tile_alpha.vs.glsl | 3 + .../shaders/gl3/tile_alpha_difference.fs.glsl | 3 +- .../shaders/gl3/tile_alpha_dodgeburn.fs.glsl | 3 +- .../shaders/gl3/tile_alpha_exclusion.fs.glsl | 3 +- resources/shaders/gl3/tile_alpha_hsl.fs.glsl | 3 +- .../shaders/gl3/tile_alpha_overlay.fs.glsl | 3 +- .../shaders/gl3/tile_alpha_softlight.fs.glsl | 3 +- resources/shaders/metal/tile_alpha.fs.metal | 7 ++- resources/shaders/metal/tile_alpha.vs.metal | 3 + .../metal/tile_alpha_difference.fs.metal | 7 ++- .../metal/tile_alpha_dodgeburn.fs.metal | 43 ++++++------- .../metal/tile_alpha_exclusion.fs.metal | 7 ++- .../shaders/metal/tile_alpha_hsl.fs.metal | 27 ++++---- .../shaders/metal/tile_alpha_overlay.fs.metal | 43 ++++++------- .../metal/tile_alpha_softlight.fs.metal | 27 ++++---- shaders/tile_alpha.vs.glsl | 3 + shaders/tile_alpha_sample.inc.glsl | 3 +- svg/src/lib.rs | 40 +++++------- swf/src/lib.rs | 12 +--- text/src/lib.rs | 10 +-- 31 files changed, 230 insertions(+), 206 deletions(-) diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 16c24143..9c4b5b2f 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -103,12 +103,9 @@ impl CanvasRenderingContext2D { let paint = self.current_state.resolve_paint(&paint); let paint_id = self.scene.push_paint(&paint); - self.scene.push_path(DrawPath::new(outline, - paint_id, - None, - FillRule::Winding, - BlendMode::Clear, - String::new())) + let mut path = DrawPath::new(outline, paint_id); + path.set_blend_mode(BlendMode::Clear); + self.scene.push_path(path); } // Line styles @@ -224,8 +221,9 @@ impl CanvasRenderingContext2D { let mut outline = path.into_outline(); outline.transform(&self.current_state.transform); - let clip_path_id = self.scene - .push_clip_path(ClipPath::new(outline, fill_rule, String::new())); + let mut clip_path = ClipPath::new(outline); + clip_path.set_fill_rule(fill_rule); + let clip_path_id = self.scene.push_clip_path(clip_path); self.current_state.clip_path = Some(clip_path_id); } @@ -234,6 +232,7 @@ impl CanvasRenderingContext2D { 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(); + let opacity = (self.current_state.global_alpha * 255.0) as u8; if !self.current_state.shadow_paint.is_fully_transparent() { let render_target_id = self.push_render_target_if_needed(composite_op); @@ -243,24 +242,24 @@ impl CanvasRenderingContext2D { let mut outline = outline.clone(); outline.transform(&Transform2F::from_translation(self.current_state.shadow_offset)); - self.scene.push_path(DrawPath::new(outline, - paint_id, - clip_path, - fill_rule, - blend_mode, - String::new())); + let mut path = DrawPath::new(outline, paint_id); + path.set_clip_path(clip_path); + path.set_fill_rule(fill_rule); + path.set_blend_mode(blend_mode); + path.set_opacity(opacity); + self.scene.push_path(path); 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())); + let mut path = DrawPath::new(outline, paint_id); + path.set_clip_path(clip_path); + path.set_fill_rule(fill_rule); + path.set_blend_mode(blend_mode); + path.set_opacity(opacity); + self.scene.push_path(path); self.composite_render_target_if_needed(composite_op, render_target_id); } @@ -387,12 +386,11 @@ impl State { } fn resolve_paint<'a>(&self, paint: &'a Paint) -> Cow<'a, Paint> { - if self.global_alpha == 1.0 && (paint.is_color() || self.transform.is_identity()) { + if self.transform.is_identity() { return Cow::Borrowed(paint); } let mut paint = (*paint).clone(); - paint.set_opacity(self.global_alpha); paint.apply_transform(&self.transform); Cow::Owned(paint) } diff --git a/content/src/gradient.rs b/content/src/gradient.rs index 5b54df38..d9a16e21 100644 --- a/content/src/gradient.rs +++ b/content/src/gradient.rs @@ -148,12 +148,6 @@ impl Gradient { .lerp(upper_stop.color.to_f32(), (t - lower_stop.offset) / denom) .to_u8() } - - pub fn set_opacity(&mut self, alpha: f32) { - for stop in &mut self.stops.array { - stop.color.a = (stop.color.a as f32 * alpha).round() as u8; - } - } } impl ColorStop { diff --git a/content/src/pattern.rs b/content/src/pattern.rs index de6eebe8..75108e97 100644 --- a/content/src/pattern.rs +++ b/content/src/pattern.rs @@ -86,17 +86,6 @@ impl Image { pub fn is_opaque(&self) -> bool { self.is_opaque } - - pub fn set_opacity(&mut self, alpha: f32) { - debug_assert!(alpha >= 0.0 && alpha <= 1.0); - if alpha == 1.0 { - return; - } - - // TODO(pcwalton): Go four pixels at a time with SIMD. - self.pixels.iter_mut().for_each(|pixel| pixel.a = (pixel.a as f32 * alpha).round() as u8); - self.is_opaque = false; - } } impl PatternSource { @@ -110,18 +99,6 @@ impl PatternSource { } } } - - #[inline] - pub fn set_opacity(&mut self, alpha: f32) { - match *self { - PatternSource::Image(ref mut image) => image.set_opacity(alpha), - PatternSource::RenderTarget(_) => { - // TODO(pcwalton): We'll probably have to introduce and use an Opacity filter for - // this. - unimplemented!() - } - } - } } impl Debug for Image { diff --git a/metal/src/lib.rs b/metal/src/lib.rs index 192b2304..1bf06dfa 100644 --- a/metal/src/lib.rs +++ b/metal/src/lib.rs @@ -365,6 +365,9 @@ impl Device for MetalDevice { (VertexAttrClass::Int, VertexAttrType::I8, 1) => MTLVertexFormat::Char, (VertexAttrClass::Int, VertexAttrType::U8, 1) => MTLVertexFormat::UChar, (VertexAttrClass::FloatNorm, VertexAttrType::I8, 1) => MTLVertexFormat::CharNormalized, + (VertexAttrClass::FloatNorm, VertexAttrType::U8, 1) => { + MTLVertexFormat::UCharNormalized + } (VertexAttrClass::Int, VertexAttrType::I16, 1) => MTLVertexFormat::Short, (VertexAttrClass::Int, VertexAttrType::U16, 1) => MTLVertexFormat::UShort, (VertexAttrClass::FloatNorm, VertexAttrType::U16, 1) => { diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index de6fdb82..e3882b7f 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -180,6 +180,7 @@ impl<'a> SceneBuilder<'a> { TilingPathInfo::Draw { paint_metadata, blend_mode: path_object.blend_mode(), + opacity: path_object.opacity(), built_clip_path, }); @@ -670,27 +671,32 @@ impl ObjectBuilder { mask_tile_index: u16, tile_coords: Vector2I, object_index: u16, + opacity: u8, paint_metadata: &PaintMetadata) { alpha_tiles.push(AlphaTile { upper_left: AlphaTileVertex::new(tile_coords, mask_tile_index, Vector2I::default(), object_index, + opacity, paint_metadata), upper_right: AlphaTileVertex::new(tile_coords, mask_tile_index, Vector2I::new(1, 0), object_index, + opacity, paint_metadata), lower_left: AlphaTileVertex::new(tile_coords, mask_tile_index, Vector2I::new(0, 1), object_index, + opacity, paint_metadata), lower_right: AlphaTileVertex::new(tile_coords, mask_tile_index, Vector2I::splat(1), object_index, + opacity, paint_metadata), }); } @@ -723,6 +729,7 @@ impl AlphaTileVertex { tile_index: u16, tile_offset: Vector2I, object_index: u16, + opacity: u8, paint_metadata: &PaintMetadata) -> AlphaTileVertex { let tile_position = tile_origin + tile_offset; @@ -737,6 +744,7 @@ impl AlphaTileVertex { mask_u: mask_uv.x() as u16, mask_v: mask_uv.y() as u16, object_index, + opacity, pad: 0, } } diff --git a/renderer/src/gpu/shaders.rs b/renderer/src/gpu/shaders.rs index 3ac090b8..2a0c8bbd 100644 --- a/renderer/src/gpu/shaders.rs +++ b/renderer/src/gpu/shaders.rs @@ -193,6 +193,7 @@ impl AlphaTileVertexArray where D: Device { "ColorTexCoord").unwrap(); let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "MaskTexCoord").unwrap(); + let opacity_attr = device.get_vertex_attr(&alpha_tile_program.program, "Opacity").unwrap(); device.bind_buffer(&vertex_array, alpha_tile_vertex_buffer, BufferTarget::Vertex); device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor { @@ -222,6 +223,15 @@ impl AlphaTileVertexArray where D: Device { divisor: 0, buffer_index: 0, }); + device.configure_vertex_attr(&vertex_array, &opacity_attr, &VertexAttrDescriptor { + size: 1, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U8, + stride: ALPHA_TILE_VERTEX_SIZE, + offset: 14, + divisor: 0, + buffer_index: 0, + }); device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index); AlphaTileVertexArray { vertex_array } diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 54597639..c54c3853 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -173,7 +173,8 @@ pub struct AlphaTileVertex { pub color_u: u16, pub color_v: u16, pub object_index: u16, - pub pad: u16, + pub opacity: u8, + pub pad: u8, } impl Debug for RenderCommand { diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index c29ea237..084f1849 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -113,18 +113,6 @@ impl Paint { } } - pub fn set_opacity(&mut self, alpha: f32) { - if alpha == 1.0 { - return; - } - - match *self { - Paint::Color(ref mut color) => color.a = (color.a as f32 * alpha).round() as u8, - Paint::Gradient(ref mut gradient) => gradient.set_opacity(alpha), - Paint::Pattern(ref mut pattern) => pattern.source.set_opacity(alpha), - } - } - pub fn apply_transform(&mut self, transform: &Transform2F) { if transform.is_identity() { return; diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index dc38968a..9ab2204a 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -226,6 +226,7 @@ pub struct DrawPath { clip_path: Option, fill_rule: FillRule, blend_mode: BlendMode, + opacity: u8, name: String, } @@ -267,14 +268,16 @@ pub enum DisplayItem { impl DrawPath { #[inline] - pub fn new(outline: Outline, - paint: PaintId, - clip_path: Option, - fill_rule: FillRule, - blend_mode: BlendMode, - name: String) - -> DrawPath { - DrawPath { outline, paint, clip_path, fill_rule, blend_mode, name } + pub fn new(outline: Outline, paint: PaintId) -> DrawPath { + DrawPath { + outline, + paint, + clip_path: None, + fill_rule: FillRule::Winding, + blend_mode: BlendMode::SrcOver, + opacity: !0, + name: String::new(), + } } #[inline] @@ -287,6 +290,11 @@ impl DrawPath { self.clip_path } + #[inline] + pub fn set_clip_path(&mut self, new_clip_path: Option) { + self.clip_path = new_clip_path + } + #[inline] pub(crate) fn paint(&self) -> PaintId { self.paint @@ -297,16 +305,41 @@ impl DrawPath { self.fill_rule } + #[inline] + pub fn set_fill_rule(&mut self, new_fill_rule: FillRule) { + self.fill_rule = new_fill_rule + } + #[inline] pub(crate) fn blend_mode(&self) -> BlendMode { self.blend_mode } + + #[inline] + pub fn set_blend_mode(&mut self, new_blend_mode: BlendMode) { + self.blend_mode = new_blend_mode + } + + #[inline] + pub(crate) fn opacity(&self) -> u8 { + self.opacity + } + + #[inline] + pub fn set_opacity(&mut self, new_opacity: u8) { + self.opacity = new_opacity + } + + #[inline] + pub fn set_name(&mut self, new_name: String) { + self.name = new_name + } } impl ClipPath { #[inline] - pub fn new(outline: Outline, fill_rule: FillRule, name: String) -> ClipPath { - ClipPath { outline, fill_rule, name } + pub fn new(outline: Outline) -> ClipPath { + ClipPath { outline, fill_rule: FillRule::Winding, name: String::new() } } #[inline] @@ -318,6 +351,16 @@ impl ClipPath { pub(crate) fn fill_rule(&self) -> FillRule { self.fill_rule } + + #[inline] + pub fn set_fill_rule(&mut self, new_fill_rule: FillRule) { + self.fill_rule = new_fill_rule + } + + #[inline] + pub fn set_name(&mut self, new_name: String) { + self.name = new_name + } } impl RenderTarget { diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 6a16ad92..44423dab 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -46,6 +46,7 @@ pub(crate) enum TilingPathInfo<'a> { Draw { paint_metadata: &'a PaintMetadata, blend_mode: BlendMode, + opacity: u8, built_clip_path: Option<&'a BuiltPath>, }, } @@ -127,10 +128,10 @@ impl<'a> Tiler<'a> { } fn pack_and_cull_draw_path(&mut self) { - let (paint_metadata, blend_mode, built_clip_path) = match self.path_info { + let (paint_metadata, blend_mode, opacity, built_clip_path) = match self.path_info { TilingPathInfo::Clip => unreachable!(), - TilingPathInfo::Draw { paint_metadata, blend_mode, built_clip_path } => { - (paint_metadata, blend_mode, built_clip_path) + TilingPathInfo::Draw { paint_metadata, blend_mode, opacity, built_clip_path } => { + (paint_metadata, blend_mode, opacity, built_clip_path) } }; @@ -181,7 +182,7 @@ impl<'a> Tiler<'a> { // Next, if this is a solid tile that completely occludes the background, record // that fact and stop here. - if paint_metadata.is_opaque && blend_mode.occludes_backdrop() { + if paint_metadata.is_opaque && blend_mode.occludes_backdrop() && opacity == !0 { self.object_builder.built_path.solid_tiles.push(SolidTile::new(tile_coords)); continue; } @@ -209,6 +210,7 @@ impl<'a> Tiler<'a> { mask_tile_index, tile_coords, self.object_index, + opacity, paint_metadata); } diff --git a/resources/shaders/gl3/tile_alpha.fs.glsl b/resources/shaders/gl3/tile_alpha.fs.glsl index 1715cc27..af6cae62 100644 --- a/resources/shaders/gl3/tile_alpha.fs.glsl +++ b/resources/shaders/gl3/tile_alpha.fs.glsl @@ -36,12 +36,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/gl3/tile_alpha.vs.glsl b/resources/shaders/gl3/tile_alpha.vs.glsl index 9db80121..83d33a48 100644 --- a/resources/shaders/gl3/tile_alpha.vs.glsl +++ b/resources/shaders/gl3/tile_alpha.vs.glsl @@ -20,15 +20,18 @@ uniform vec2 uTileSize; in ivec2 aTilePosition; in vec2 aColorTexCoord; in vec2 aMaskTexCoord; +in float aOpacity; out vec2 vColorTexCoord; out vec2 vMaskTexCoord; +out float vOpacity; void main(){ vec2 position = aTilePosition * uTileSize; vMaskTexCoord = aMaskTexCoord; vColorTexCoord = aColorTexCoord; + vOpacity = aOpacity; gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/gl3/tile_alpha_difference.fs.glsl b/resources/shaders/gl3/tile_alpha_difference.fs.glsl index 686c90e9..1c61a8b6 100644 --- a/resources/shaders/gl3/tile_alpha_difference.fs.glsl +++ b/resources/shaders/gl3/tile_alpha_difference.fs.glsl @@ -38,12 +38,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/gl3/tile_alpha_dodgeburn.fs.glsl b/resources/shaders/gl3/tile_alpha_dodgeburn.fs.glsl index d8501bde..7b501af2 100644 --- a/resources/shaders/gl3/tile_alpha_dodgeburn.fs.glsl +++ b/resources/shaders/gl3/tile_alpha_dodgeburn.fs.glsl @@ -40,12 +40,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/gl3/tile_alpha_exclusion.fs.glsl b/resources/shaders/gl3/tile_alpha_exclusion.fs.glsl index c830f88e..dc6e8fae 100644 --- a/resources/shaders/gl3/tile_alpha_exclusion.fs.glsl +++ b/resources/shaders/gl3/tile_alpha_exclusion.fs.glsl @@ -38,12 +38,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/gl3/tile_alpha_hsl.fs.glsl b/resources/shaders/gl3/tile_alpha_hsl.fs.glsl index fb794256..278cccf6 100644 --- a/resources/shaders/gl3/tile_alpha_hsl.fs.glsl +++ b/resources/shaders/gl3/tile_alpha_hsl.fs.glsl @@ -38,12 +38,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/gl3/tile_alpha_overlay.fs.glsl b/resources/shaders/gl3/tile_alpha_overlay.fs.glsl index 5c49a17d..4d352986 100644 --- a/resources/shaders/gl3/tile_alpha_overlay.fs.glsl +++ b/resources/shaders/gl3/tile_alpha_overlay.fs.glsl @@ -45,12 +45,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/gl3/tile_alpha_softlight.fs.glsl b/resources/shaders/gl3/tile_alpha_softlight.fs.glsl index 8299c6ae..e1a00f65 100644 --- a/resources/shaders/gl3/tile_alpha_softlight.fs.glsl +++ b/resources/shaders/gl3/tile_alpha_softlight.fs.glsl @@ -38,12 +38,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; vec4 sampleSrcColor(){ float coverage = texture(uStencilTexture, vMaskTexCoord). r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA . rgb, srcRGBA . a * coverage); + return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity); } vec4 sampleDestColor(){ diff --git a/resources/shaders/metal/tile_alpha.fs.metal b/resources/shaders/metal/tile_alpha.fs.metal index 600fa493..3281ab94 100644 --- a/resources/shaders/metal/tile_alpha.fs.metal +++ b/resources/shaders/metal/tile_alpha.fs.metal @@ -23,19 +23,20 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) { main0_out out = {}; - float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); + float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); out.oFragColor = float4(srcRGBA.xyz * srcRGBA.w, srcRGBA.w); return out; } diff --git a/resources/shaders/metal/tile_alpha.vs.metal b/resources/shaders/metal/tile_alpha.vs.metal index 1102b8c2..d999eb0f 100644 --- a/resources/shaders/metal/tile_alpha.vs.metal +++ b/resources/shaders/metal/tile_alpha.vs.metal @@ -14,6 +14,7 @@ struct main0_out { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; float4 gl_Position [[position]]; }; @@ -22,6 +23,7 @@ struct main0_in int2 aTilePosition [[attribute(0)]]; float2 aColorTexCoord [[attribute(1)]]; float2 aMaskTexCoord [[attribute(2)]]; + float aOpacity [[attribute(3)]]; }; vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) @@ -30,6 +32,7 @@ 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.vOpacity = in.aOpacity; out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0); return out; } diff --git a/resources/shaders/metal/tile_alpha_difference.fs.metal b/resources/shaders/metal/tile_alpha_difference.fs.metal index a16905fb..8d32de9e 100644 --- a/resources/shaders/metal/tile_alpha_difference.fs.metal +++ b/resources/shaders/metal/tile_alpha_difference.fs.metal @@ -26,13 +26,14 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) @@ -49,7 +50,7 @@ float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, 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 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); float3 blended = abs(destRGBA.xyz - srcRGBA.xyz); float4 param = destRGBA; diff --git a/resources/shaders/metal/tile_alpha_dodgeburn.fs.metal b/resources/shaders/metal/tile_alpha_dodgeburn.fs.metal index b165485e..5a8f4c0b 100644 --- a/resources/shaders/metal/tile_alpha_dodgeburn.fs.metal +++ b/resources/shaders/metal/tile_alpha_dodgeburn.fs.metal @@ -27,13 +27,14 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) @@ -50,57 +51,57 @@ float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, 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 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); - float3 _118; + float3 _122; if ((*spvDescriptorSet0.uBurn) == 0) { - _118 = destRGBA.xyz; + _122 = destRGBA.xyz; } else { - _118 = float3(1.0) - destRGBA.xyz; + _122 = float3(1.0) - destRGBA.xyz; } - float3 dest = _118; - float3 _132; + float3 dest = _122; + float3 _136; if ((*spvDescriptorSet0.uBurn) == 0) { - _132 = float3(1.0) - srcRGBA.xyz; + _136 = float3(1.0) - srcRGBA.xyz; } else { - _132 = srcRGBA.xyz; + _136 = srcRGBA.xyz; } - float3 src = _132; + float3 src = _136; bool3 srcNonzero = src != float3(0.0); - float _153; + float _157; if (srcNonzero.x) { - _153 = dest.x / src.x; + _157 = dest.x / src.x; } else { - _153 = 1.0; + _157 = 1.0; } - float _166; + float _170; if (srcNonzero.y) { - _166 = dest.y / src.y; + _170 = dest.y / src.y; } else { - _166 = 1.0; + _170 = 1.0; } - float _179; + float _183; if (srcNonzero.z) { - _179 = dest.z / src.z; + _183 = dest.z / src.z; } else { - _179 = 1.0; + _183 = 1.0; } - float3 blended = fast::min(float3(_153, _166, _179), float3(1.0)); + float3 blended = fast::min(float3(_157, _170, _183), float3(1.0)); if ((*spvDescriptorSet0.uBurn) != 0) { blended = float3(1.0) - blended; diff --git a/resources/shaders/metal/tile_alpha_exclusion.fs.metal b/resources/shaders/metal/tile_alpha_exclusion.fs.metal index 63514ee9..a5b8415d 100644 --- a/resources/shaders/metal/tile_alpha_exclusion.fs.metal +++ b/resources/shaders/metal/tile_alpha_exclusion.fs.metal @@ -26,13 +26,14 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) @@ -49,7 +50,7 @@ float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, 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 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); float3 dest = destRGBA.xyz; float3 src = srcRGBA.xyz; diff --git a/resources/shaders/metal/tile_alpha_hsl.fs.metal b/resources/shaders/metal/tile_alpha_hsl.fs.metal index ff61ce4c..7b2072c0 100644 --- a/resources/shaders/metal/tile_alpha_hsl.fs.metal +++ b/resources/shaders/metal/tile_alpha_hsl.fs.metal @@ -27,6 +27,7 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; // Implementation of the GLSL mod() function, which is slightly different than Metal fmod() @@ -36,11 +37,11 @@ Tx mod(Tx x, Ty y) return x - y * floor(x / y); } -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) @@ -85,34 +86,34 @@ float3 convertRGBToHSL(thread const float3& rgb) float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b) { - float _125; + float _129; if (cond.x) { - _125 = a.x; + _129 = a.x; } else { - _125 = b.x; + _129 = b.x; } - float _137; + float _141; if (cond.y) { - _137 = a.y; + _141 = a.y; } else { - _137 = b.y; + _141 = b.y; } - float _149; + float _153; if (cond.z) { - _149 = a.z; + _153 = a.z; } else { - _149 = b.z; + _153 = b.z; } - return float3(_125, _137, _149); + return float3(_129, _141, _153); } float3 convertHSLToRGB(thread const float3& hsl) @@ -130,7 +131,7 @@ float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, 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 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); float3 param = destRGBA.xyz; float3 destHSL = convertRGBToHSL(param); diff --git a/resources/shaders/metal/tile_alpha_overlay.fs.metal b/resources/shaders/metal/tile_alpha_overlay.fs.metal index 689487e0..0c5ebd53 100644 --- a/resources/shaders/metal/tile_alpha_overlay.fs.metal +++ b/resources/shaders/metal/tile_alpha_overlay.fs.metal @@ -27,13 +27,14 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) @@ -44,34 +45,34 @@ float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSi float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b) { - float _118; + float _122; if (cond.x) { - _118 = a.x; + _122 = a.x; } else { - _118 = b.x; + _122 = b.x; } - float _130; + float _134; if (cond.y) { - _130 = a.y; + _134 = a.y; } else { - _130 = b.y; + _134 = b.y; } - float _142; + float _146; if (cond.z) { - _142 = a.z; + _146 = a.z; } else { - _142 = b.z; + _146 = b.z; } - return float3(_118, _130, _142); + return float3(_122, _134, _146); } float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB) @@ -82,29 +83,29 @@ float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, 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 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); bool reversed = (*spvDescriptorSet0.uBlendMode) == 3; - float3 _167; + float3 _171; if (reversed) { - _167 = srcRGBA.xyz; + _171 = srcRGBA.xyz; } else { - _167 = destRGBA.xyz; + _171 = destRGBA.xyz; } - float3 src = _167; - float3 _178; + float3 src = _171; + float3 _182; if (reversed) { - _178 = destRGBA.xyz; + _182 = destRGBA.xyz; } else { - _178 = srcRGBA.xyz; + _182 = srcRGBA.xyz; } - float3 dest = _178; + float3 dest = _182; float3 multiply = src * dest; float3 blended; if ((*spvDescriptorSet0.uBlendMode) == 0) diff --git a/resources/shaders/metal/tile_alpha_softlight.fs.metal b/resources/shaders/metal/tile_alpha_softlight.fs.metal index 9e059bd2..3d356a2b 100644 --- a/resources/shaders/metal/tile_alpha_softlight.fs.metal +++ b/resources/shaders/metal/tile_alpha_softlight.fs.metal @@ -26,13 +26,14 @@ struct main0_in { float2 vColorTexCoord [[user(locn0)]]; float2 vMaskTexCoord [[user(locn1)]]; + float vOpacity [[user(locn2)]]; }; -float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord) +float4 sampleSrcColor(thread texture2d uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity) { float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x; float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord); - return float4(srcRGBA.xyz, srcRGBA.w * coverage); + return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity); } float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d uDest, thread const sampler uDestSmplr) @@ -43,34 +44,34 @@ float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSi float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b) { - float _118; + float _122; if (cond.x) { - _118 = a.x; + _122 = a.x; } else { - _118 = b.x; + _122 = b.x; } - float _130; + float _134; if (cond.y) { - _130 = a.y; + _134 = a.y; } else { - _130 = b.y; + _134 = b.y; } - float _142; + float _146; if (cond.z) { - _142 = a.z; + _146 = a.z; } else { - _142 = b.z; + _146 = b.z; } - return float3(_118, _130, _142); + return float3(_122, _134, _146); } float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB) @@ -81,7 +82,7 @@ float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, 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 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity); float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr); float3 dest = destRGBA.xyz; float3 src = srcRGBA.xyz; diff --git a/shaders/tile_alpha.vs.glsl b/shaders/tile_alpha.vs.glsl index e1b2d31e..46d7bb08 100644 --- a/shaders/tile_alpha.vs.glsl +++ b/shaders/tile_alpha.vs.glsl @@ -18,14 +18,17 @@ uniform vec2 uTileSize; in ivec2 aTilePosition; in vec2 aColorTexCoord; in vec2 aMaskTexCoord; +in float aOpacity; out vec2 vColorTexCoord; out vec2 vMaskTexCoord; +out float vOpacity; void main() { vec2 position = aTilePosition * uTileSize; vMaskTexCoord = aMaskTexCoord; vColorTexCoord = aColorTexCoord; + vOpacity = aOpacity; gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/shaders/tile_alpha_sample.inc.glsl b/shaders/tile_alpha_sample.inc.glsl index 820937ee..b1858f1f 100644 --- a/shaders/tile_alpha_sample.inc.glsl +++ b/shaders/tile_alpha_sample.inc.glsl @@ -15,12 +15,13 @@ uniform vec2 uFramebufferSize; in vec2 vColorTexCoord; in vec2 vMaskTexCoord; +in float vOpacity; // NB: This does not premultiply. vec4 sampleSrcColor() { float coverage = texture(uStencilTexture, vMaskTexCoord).r; vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord); - return vec4(srcRGBA.rgb, srcRGBA.a * coverage); + return vec4(srcRGBA.rgb, srcRGBA.a * coverage * vOpacity); } vec4 sampleDestColor() { diff --git a/svg/src/lib.rs b/svg/src/lib.rs index e954e0cd..4866af5d 100644 --- a/svg/src/lib.rs +++ b/svg/src/lib.rs @@ -15,7 +15,6 @@ extern crate bitflags; use hashbrown::HashMap; use pathfinder_color::ColorU; -use pathfinder_content::effects::BlendMode; use pathfinder_content::fill::FillRule; use pathfinder_content::outline::Outline; use pathfinder_content::segment::{Segment, SegmentFlags}; @@ -180,9 +179,9 @@ impl BuiltSVG { } if let Some(clip_outline) = clip_outline { - let name = format!("ClipPath({})", node.id()); // FIXME(pcwalton): Is the winding fill rule correct to use? - let clip_path = ClipPath::new(clip_outline, FillRule::Winding, name); + let mut clip_path = ClipPath::new(clip_outline); + clip_path.set_name(format!("ClipPath({})", node.id())); let clip_path_id = self.scene.push_clip_path(clip_path); self.clip_paths.insert(node.id().to_owned(), clip_path_id); } @@ -232,16 +231,14 @@ impl BuiltSVG { paint: &UsvgPaint, opacity: Opacity, fill_rule: UsvgFillRule) { - let style = self.scene.push_paint(&Paint::from_svg_paint(paint, - opacity, - &mut self.result_flags)); + let style = self.scene.push_paint(&Paint::from_svg_paint(paint, &mut self.result_flags)); let fill_rule = FillRule::from_usvg_fill_rule(fill_rule); - self.scene.push_path(DrawPath::new(outline, - style, - state.clip_path, - fill_rule, - BlendMode::SrcOver, - name)); + let mut path = DrawPath::new(outline, style); + path.set_clip_path(state.clip_path); + path.set_fill_rule(fill_rule); + path.set_name(name); + path.set_opacity((opacity.value() * 255.0) as u8); + self.scene.push_path(path); } } @@ -288,17 +285,15 @@ impl Display for BuildResultFlags { } trait PaintExt { - fn from_svg_paint(svg_paint: &UsvgPaint, opacity: Opacity, result_flags: &mut BuildResultFlags) - -> Self; + fn from_svg_paint(svg_paint: &UsvgPaint, result_flags: &mut BuildResultFlags) -> Self; } impl PaintExt for Paint { #[inline] - fn from_svg_paint(svg_paint: &UsvgPaint, opacity: Opacity, result_flags: &mut BuildResultFlags) - -> Paint { + fn from_svg_paint(svg_paint: &UsvgPaint, result_flags: &mut BuildResultFlags) -> Paint { // TODO(pcwalton): Support gradients. Paint::Color(match *svg_paint { - UsvgPaint::Color(color) => ColorU::from_svg_color(color, opacity), + UsvgPaint::Color(color) => ColorU::from_svg_color(color), UsvgPaint::Link(_) => { // TODO(pcwalton) result_flags.insert(BuildResultFlags::UNSUPPORTED_LINK_PAINT); @@ -412,18 +407,13 @@ where } trait ColorUExt { - fn from_svg_color(svg_color: SvgColor, opacity: Opacity) -> Self; + fn from_svg_color(svg_color: SvgColor) -> Self; } impl ColorUExt for ColorU { #[inline] - fn from_svg_color(svg_color: SvgColor, opacity: Opacity) -> ColorU { - ColorU { - r: svg_color.red, - g: svg_color.green, - b: svg_color.blue, - a: (opacity.value() * 255.0).round() as u8, - } + fn from_svg_color(svg_color: SvgColor) -> ColorU { + ColorU { r: svg_color.red, g: svg_color.green, b: svg_color.blue, a: !0 } } } diff --git a/swf/src/lib.rs b/swf/src/lib.rs index 1ab03e2e..0120a167 100644 --- a/swf/src/lib.rs +++ b/swf/src/lib.rs @@ -10,7 +10,6 @@ use std::ops::Add; use pathfinder_color::{ColorF, ColorU}; -use pathfinder_content::effects::BlendMode; use pathfinder_content::fill::FillRule; use pathfinder_content::outline::{Outline, Contour}; use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; @@ -196,14 +195,9 @@ pub fn draw_paths_into_scene(library: &SymbolLibrary, scene: &mut Scene) { path = stroke_to_fill.into_outline(); } - scene.push_path(DrawPath::new( - path, - paint_id, - None, - FillRule::EvenOdd, - BlendMode::SrcOver, - String::new() - )); + let mut path = DrawPath::new(path, paint_id); + path.set_fill_rule(FillRule::EvenOdd); + scene.push_path(path); } } } diff --git a/text/src/lib.rs b/text/src/lib.rs index 443a6439..d8472e73 100644 --- a/text/src/lib.rs +++ b/text/src/lib.rs @@ -14,8 +14,6 @@ use font_kit::error::GlyphLoadingError; use font_kit::hinting::HintingOptions; use font_kit::loader::Loader; use lyon_path::builder::{FlatPathBuilder, PathBuilder, Build}; -use pathfinder_content::effects::BlendMode; -use pathfinder_content::fill::FillRule; use pathfinder_content::outline::{Contour, Outline}; use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; use pathfinder_geometry::transform2d::Transform2F; @@ -78,13 +76,7 @@ impl SceneExt for Scene { outline = stroke_to_fill.into_outline(); } - self.push_path(DrawPath::new(outline, - paint_id, - None, - FillRule::Winding, - BlendMode::SrcOver, - String::new())); - + self.push_path(DrawPath::new(outline, paint_id)); Ok(()) }