diff --git a/render/wgpu/src/pipelines.rs b/render/wgpu/src/pipelines.rs index d08d29f78..764522fc4 100644 --- a/render/wgpu/src/pipelines.rs +++ b/render/wgpu/src/pipelines.rs @@ -59,23 +59,131 @@ impl ShapePipeline { } fn blend_mode_to_state(mode: BlendMode) -> Option { + // Use the GPU blend modes to roughly approximate Flash's blend modes. + // This should look reasonable for the most common cases, but full support requires + // rendering to an intermediate texture and custom shaders for the complex blend modes. match mode { BlendMode::Normal => Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING), - BlendMode::Add => { + + // TODO: Needs intermediate buffer. + BlendMode::Layer => Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING), + + // dst * src + BlendMode::Multiply => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::Dst, + dst_factor: wgpu::BlendFactor::Zero, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // 1 - (1 - dst) * (1 - src) + // TODO: Needs shader. Rendererd as additive for now. + BlendMode::Screen => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // max(dst, src) + BlendMode::Lighten => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Max, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // min(dst, src) + BlendMode::Darken => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Min, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // abs(dst - src) + // TODO: Needs shader. Rendererd as subtract for now. + BlendMode::Difference => { Some(wgpu::BlendState { // Add src and dst RGB values together color: wgpu::BlendComponent { src_factor: wgpu::BlendFactor::One, dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, + operation: wgpu::BlendOperation::ReverseSubtract, }, alpha: wgpu::BlendComponent::OVER, }) } - _ => { - log::warn!("Webgpu backend does not yet support blend mode {:?}", mode); - Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING) - } + + // dst + src + BlendMode::Add => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // dst - src + BlendMode::Subtract => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::ReverseSubtract, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // 1 - dst + BlendMode::Invert => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::Zero, + dst_factor: wgpu::BlendFactor::OneMinusDst, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // TODO: Requires intermediate buffer. + // dst.alpha = src.alpha + // Parent display object needs to have Layer blend mode. + BlendMode::Alpha => Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING), + + // TODO: Requires intermediate buffer. + // dst.alpha = 1 - src.alpha + // Parent display object needs to have Layer blend mode. + BlendMode::Erase => Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING), + + // if src > .5 { 1 - (1 - dst) * (1 - src) } else { dst * src } + // TODO: Needs shader, rendered as multiply for now. + BlendMode::HardLight => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::Dst, + dst_factor: wgpu::BlendFactor::Zero, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent::OVER, + }), + + // if dst > .5 { 1 - (1 - dst) * (1 - src) } else { dst * src } + // TODO: Needs shader, rendered as multiply for now. + BlendMode::Overlay => Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::Dst, + dst_factor: wgpu::BlendFactor::Zero, + operation: wgpu::BlendOperation::Add, + }, + alpha: wgpu::BlendComponent::OVER, + }), } }