Implement a few more blend modes and switch to premultiplied alpha for layer

compositing
This commit is contained in:
Patrick Walton 2020-02-20 22:22:15 -08:00
parent 4933efb513
commit 36538d5748
12 changed files with 106 additions and 27 deletions

View File

@ -524,6 +524,11 @@ pub enum LineJoin {
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum CompositeOperation { pub enum CompositeOperation {
SourceOver, SourceOver,
DestinationOver,
DestinationOut,
SourceAtop,
Xor,
Lighter,
Lighten, Lighten,
Darken, Darken,
} }
@ -531,7 +536,12 @@ pub enum CompositeOperation {
impl CompositeOperation { impl CompositeOperation {
fn to_blend_mode(self) -> BlendMode { fn to_blend_mode(self) -> BlendMode {
match self { match self {
CompositeOperation::SourceOver => BlendMode::SourceOver, CompositeOperation::SourceOver => BlendMode::SrcOver,
CompositeOperation::DestinationOver => BlendMode::DestOver,
CompositeOperation::DestinationOut => BlendMode::DestOut,
CompositeOperation::SourceAtop => BlendMode::SrcAtop,
CompositeOperation::Xor => BlendMode::Xor,
CompositeOperation::Lighter => BlendMode::Lighter,
CompositeOperation::Lighten => BlendMode::Lighten, CompositeOperation::Lighten => BlendMode::Lighten,
CompositeOperation::Darken => BlendMode::Darken, CompositeOperation::Darken => BlendMode::Darken,
} }

View File

@ -58,14 +58,19 @@ pub enum Filter {
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum CompositeOp { pub enum CompositeOp {
/// The default. /// The default.
SourceOver, SrcOver,
} }
/// Blend modes that can be applied to individual paths without creating layers for them. /// Blend modes that can be applied to individual paths without creating layers for them.
#[derive(Clone, Copy, PartialEq, Debug)] #[derive(Clone, Copy, PartialEq, Debug)]
pub enum BlendMode { pub enum BlendMode {
SourceOver,
Clear, Clear,
SrcOver,
DestOver,
DestOut,
SrcAtop,
Xor,
Lighter,
Lighten, Lighten,
Darken, Darken,
} }
@ -76,25 +81,31 @@ pub struct DefringingKernel(pub [f32; 4]);
impl Default for CompositeOp { impl Default for CompositeOp {
#[inline] #[inline]
fn default() -> CompositeOp { fn default() -> CompositeOp {
CompositeOp::SourceOver CompositeOp::SrcOver
} }
} }
impl Default for BlendMode { impl Default for BlendMode {
#[inline] #[inline]
fn default() -> BlendMode { fn default() -> BlendMode {
BlendMode::SourceOver BlendMode::SrcOver
} }
} }
impl BlendMode { impl BlendMode {
/// Whether the backdrop is irrelevant when applying this blend mode (i.e. destination blend /// Whether the backdrop is irrelevant when applying this blend mode (i.e. destination blend
/// factor is zero). /// factor is zero when source alpha is one).
#[inline] #[inline]
pub fn occludes_backdrop(self) -> bool { pub fn occludes_backdrop(self) -> bool {
match self { match self {
BlendMode::SourceOver | BlendMode::Clear => true, BlendMode::SrcOver | BlendMode::Clear => true,
BlendMode::Lighten | BlendMode::Darken => false, BlendMode::DestOver |
BlendMode::DestOut |
BlendMode::SrcAtop |
BlendMode::Xor |
BlendMode::Lighter |
BlendMode::Lighten |
BlendMode::Darken => false,
} }
} }
} }

View File

@ -965,6 +965,8 @@ impl BlendFactorExt for BlendFactor {
BlendFactor::One => gl::ONE, BlendFactor::One => gl::ONE,
BlendFactor::SrcAlpha => gl::SRC_ALPHA, BlendFactor::SrcAlpha => gl::SRC_ALPHA,
BlendFactor::OneMinusSrcAlpha => gl::ONE_MINUS_SRC_ALPHA, BlendFactor::OneMinusSrcAlpha => gl::ONE_MINUS_SRC_ALPHA,
BlendFactor::DestAlpha => gl::DST_ALPHA,
BlendFactor::OneMinusDestAlpha => gl::ONE_MINUS_DST_ALPHA,
BlendFactor::DestColor => gl::DST_COLOR, BlendFactor::DestColor => gl::DST_COLOR,
} }
} }

View File

@ -226,6 +226,8 @@ pub enum BlendFactor {
One, One,
SrcAlpha, SrcAlpha,
OneMinusSrcAlpha, OneMinusSrcAlpha,
DestAlpha,
OneMinusDestAlpha,
DestColor, DestColor,
} }

View File

@ -1170,6 +1170,8 @@ impl BlendFactorExt for BlendFactor {
BlendFactor::One => MTLBlendFactor::One, BlendFactor::One => MTLBlendFactor::One,
BlendFactor::SrcAlpha => MTLBlendFactor::SourceAlpha, BlendFactor::SrcAlpha => MTLBlendFactor::SourceAlpha,
BlendFactor::OneMinusSrcAlpha => MTLBlendFactor::OneMinusSourceAlpha, BlendFactor::OneMinusSrcAlpha => MTLBlendFactor::OneMinusSourceAlpha,
BlendFactor::DestAlpha => MTLBlendFactor::DestinationAlpha,
BlendFactor::OneMinusDestAlpha => MTLBlendFactor::OneMinusDestinationAlpha,
BlendFactor::DestColor => MTLBlendFactor::DestinationColor, BlendFactor::DestColor => MTLBlendFactor::DestinationColor,
} }
} }

View File

@ -762,7 +762,7 @@ where
], ],
viewport: self.draw_viewport(), viewport: self.draw_viewport(),
options: RenderOptions { options: RenderOptions {
blend: Some(BlendMode::SourceOver.to_blend_state()), blend: Some(BlendMode::SrcOver.to_blend_state()),
depth: Some(DepthState { func: DepthFunc::Less, write: false, }), depth: Some(DepthState { func: DepthFunc::Less, write: false, }),
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() }, clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
..RenderOptions::default() ..RenderOptions::default()
@ -848,7 +848,7 @@ where
]; ];
let blend_state = match composite_op { let blend_state = match composite_op {
CompositeOp::SourceOver => BlendMode::SourceOver.to_blend_state(), CompositeOp::SrcOver => BlendMode::SrcOver.to_blend_state(),
}; };
self.device.draw_elements(6, &RenderState { self.device.draw_elements(6, &RenderState {
@ -1133,15 +1133,6 @@ trait BlendModeExt {
impl BlendModeExt for BlendMode { impl BlendModeExt for BlendMode {
fn to_blend_state(self) -> BlendState { fn to_blend_state(self) -> BlendState {
match self { match self {
BlendMode::SourceOver => {
BlendState {
src_rgb_factor: BlendFactor::SrcAlpha,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::One,
..BlendState::default()
}
}
BlendMode::Clear => { BlendMode::Clear => {
BlendState { BlendState {
src_rgb_factor: BlendFactor::Zero, src_rgb_factor: BlendFactor::Zero,
@ -1151,9 +1142,63 @@ impl BlendModeExt for BlendMode {
..BlendState::default() ..BlendState::default()
} }
} }
BlendMode::SrcOver => {
BlendState {
src_rgb_factor: BlendFactor::One,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::OneMinusSrcAlpha,
..BlendState::default()
}
}
BlendMode::DestOver => {
BlendState {
src_rgb_factor: BlendFactor::OneMinusDestAlpha,
dest_rgb_factor: BlendFactor::DestAlpha,
src_alpha_factor: BlendFactor::OneMinusDestAlpha,
dest_alpha_factor: BlendFactor::One,
..BlendState::default()
}
}
BlendMode::DestOut => {
BlendState {
src_rgb_factor: BlendFactor::Zero,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::Zero,
dest_alpha_factor: BlendFactor::OneMinusSrcAlpha,
..BlendState::default()
}
}
BlendMode::SrcAtop => {
BlendState {
src_rgb_factor: BlendFactor::DestAlpha,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::DestAlpha,
dest_alpha_factor: BlendFactor::OneMinusSrcAlpha,
..BlendState::default()
}
}
BlendMode::Xor => {
BlendState {
src_rgb_factor: BlendFactor::OneMinusDestAlpha,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::OneMinusDestAlpha,
dest_alpha_factor: BlendFactor::OneMinusSrcAlpha,
..BlendState::default()
}
}
BlendMode::Lighter => {
BlendState {
src_rgb_factor: BlendFactor::One,
dest_rgb_factor: BlendFactor::One,
src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::One,
..BlendState::default()
}
}
BlendMode::Lighten => { BlendMode::Lighten => {
BlendState { BlendState {
src_rgb_factor: BlendFactor::SrcAlpha, src_rgb_factor: BlendFactor::One,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::One, src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::One, dest_alpha_factor: BlendFactor::One,
@ -1162,7 +1207,7 @@ impl BlendModeExt for BlendMode {
} }
BlendMode::Darken => { BlendMode::Darken => {
BlendState { BlendState {
src_rgb_factor: BlendFactor::SrcAlpha, src_rgb_factor: BlendFactor::One,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha, dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::One, src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::One, dest_alpha_factor: BlendFactor::One,

View File

@ -27,6 +27,8 @@ out vec4 oFragColor;
void main(){ void main(){
float coverage = texture(uStencilTexture, vMaskTexCoord). r; float coverage = texture(uStencilTexture, vMaskTexCoord). r;
vec4 color = texture(uPaintTexture, vColorTexCoord); vec4 color = texture(uPaintTexture, vColorTexCoord);
oFragColor = vec4(color . rgb, color . a * coverage); color . a *= coverage;
color . rgb *= color . a;
oFragColor = color;
} }

View File

@ -28,7 +28,10 @@ fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuff
main0_out out = {}; main0_out out = {};
float coverage = spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x; float coverage = spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x;
float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord); float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord);
out.oFragColor = float4(color.xyz, color.w * coverage); color.w *= coverage;
float3 _41 = color.xyz * color.w;
color = float4(_41.x, _41.y, _41.z, color.w);
out.oFragColor = color;
return out; return out;
} }

View File

@ -25,5 +25,7 @@ out vec4 oFragColor;
void main() { void main() {
float coverage = texture(uStencilTexture, vMaskTexCoord).r; float coverage = texture(uStencilTexture, vMaskTexCoord).r;
vec4 color = texture(uPaintTexture, vColorTexCoord); vec4 color = texture(uPaintTexture, vColorTexCoord);
oFragColor = vec4(color.rgb, color.a * coverage); color.a *= coverage;
color.rgb *= color.a;
oFragColor = color;
} }

View File

@ -240,7 +240,7 @@ impl BuiltSVG {
style, style,
state.clip_path, state.clip_path,
fill_rule, fill_rule,
BlendMode::SourceOver, BlendMode::SrcOver,
name)); name));
} }
} }

View File

@ -201,7 +201,7 @@ pub fn draw_paths_into_scene(library: &SymbolLibrary, scene: &mut Scene) {
paint_id, paint_id,
None, None,
FillRule::EvenOdd, FillRule::EvenOdd,
BlendMode::SourceOver, BlendMode::SrcOver,
String::new() String::new()
)); ));
} }

View File

@ -82,7 +82,7 @@ impl SceneExt for Scene {
paint_id, paint_id,
None, None,
FillRule::Winding, FillRule::Winding,
BlendMode::SourceOver, BlendMode::SrcOver,
String::new())); String::new()));
Ok(()) Ok(())