Implement a few more blend modes and switch to premultiplied alpha for layer
compositing
This commit is contained in:
parent
4933efb513
commit
36538d5748
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,6 +226,8 @@ pub enum BlendFactor {
|
||||||
One,
|
One,
|
||||||
SrcAlpha,
|
SrcAlpha,
|
||||||
OneMinusSrcAlpha,
|
OneMinusSrcAlpha,
|
||||||
|
DestAlpha,
|
||||||
|
OneMinusDestAlpha,
|
||||||
DestColor,
|
DestColor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ impl BuiltSVG {
|
||||||
style,
|
style,
|
||||||
state.clip_path,
|
state.clip_path,
|
||||||
fill_rule,
|
fill_rule,
|
||||||
BlendMode::SourceOver,
|
BlendMode::SrcOver,
|
||||||
name));
|
name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
Loading…
Reference in New Issue