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)]
pub enum CompositeOperation {
SourceOver,
DestinationOver,
DestinationOut,
SourceAtop,
Xor,
Lighter,
Lighten,
Darken,
}
@ -531,7 +536,12 @@ pub enum CompositeOperation {
impl CompositeOperation {
fn to_blend_mode(self) -> BlendMode {
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::Darken => BlendMode::Darken,
}

View File

@ -58,14 +58,19 @@ pub enum Filter {
#[derive(Clone, Copy, Debug)]
pub enum CompositeOp {
/// The default.
SourceOver,
SrcOver,
}
/// Blend modes that can be applied to individual paths without creating layers for them.
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum BlendMode {
SourceOver,
Clear,
SrcOver,
DestOver,
DestOut,
SrcAtop,
Xor,
Lighter,
Lighten,
Darken,
}
@ -76,25 +81,31 @@ pub struct DefringingKernel(pub [f32; 4]);
impl Default for CompositeOp {
#[inline]
fn default() -> CompositeOp {
CompositeOp::SourceOver
CompositeOp::SrcOver
}
}
impl Default for BlendMode {
#[inline]
fn default() -> BlendMode {
BlendMode::SourceOver
BlendMode::SrcOver
}
}
impl BlendMode {
/// 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]
pub fn occludes_backdrop(self) -> bool {
match self {
BlendMode::SourceOver | BlendMode::Clear => true,
BlendMode::Lighten | BlendMode::Darken => false,
BlendMode::SrcOver | BlendMode::Clear => true,
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::SrcAlpha => gl::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,
}
}

View File

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

View File

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

View File

@ -762,7 +762,7 @@ where
],
viewport: self.draw_viewport(),
options: RenderOptions {
blend: Some(BlendMode::SourceOver.to_blend_state()),
blend: Some(BlendMode::SrcOver.to_blend_state()),
depth: Some(DepthState { func: DepthFunc::Less, write: false, }),
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
..RenderOptions::default()
@ -848,7 +848,7 @@ where
];
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 {
@ -1133,15 +1133,6 @@ trait BlendModeExt {
impl BlendModeExt for BlendMode {
fn to_blend_state(self) -> BlendState {
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 => {
BlendState {
src_rgb_factor: BlendFactor::Zero,
@ -1151,9 +1142,63 @@ impl BlendModeExt for BlendMode {
..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 => {
BlendState {
src_rgb_factor: BlendFactor::SrcAlpha,
src_rgb_factor: BlendFactor::One,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::One,
@ -1162,7 +1207,7 @@ impl BlendModeExt for BlendMode {
}
BlendMode::Darken => {
BlendState {
src_rgb_factor: BlendFactor::SrcAlpha,
src_rgb_factor: BlendFactor::One,
dest_rgb_factor: BlendFactor::OneMinusSrcAlpha,
src_alpha_factor: BlendFactor::One,
dest_alpha_factor: BlendFactor::One,

View File

@ -27,6 +27,8 @@ out vec4 oFragColor;
void main(){
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
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 = {};
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);
color.w *= coverage;
float3 _41 = color.xyz * color.w;
color = float4(_41.x, _41.y, _41.z, color.w);
out.oFragColor = color;
return out;
}

View File

@ -25,5 +25,7 @@ out vec4 oFragColor;
void main() {
float coverage = texture(uStencilTexture, vMaskTexCoord).r;
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,
state.clip_path,
fill_rule,
BlendMode::SourceOver,
BlendMode::SrcOver,
name));
}
}

View File

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

View File

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