2022-12-23 22:06:19 +00:00
|
|
|
use enum_map::Enum;
|
|
|
|
|
2023-07-26 23:25:26 +00:00
|
|
|
use ruffle_render::{commands::RenderBlendMode, pixel_bender::PixelBenderShaderHandle};
|
2022-12-23 22:06:19 +00:00
|
|
|
use swf::BlendMode;
|
|
|
|
|
|
|
|
#[derive(Enum, Debug, Copy, Clone)]
|
|
|
|
pub enum ComplexBlend {
|
2023-06-21 23:59:06 +00:00
|
|
|
Multiply, // Can't be trivial, 0 alpha is special case
|
2022-12-23 22:06:19 +00:00
|
|
|
Lighten, // Might be trivial but I can't reproduce the right colors
|
|
|
|
Darken, // Might be trivial but I can't reproduce the right colors
|
|
|
|
Difference, // Can't be trivial, relies on abs operation
|
|
|
|
Invert, // May be trivial using a constant? Hard because it's without premultiplied alpha
|
|
|
|
Alpha, // Can't be trivial, requires layer tracking
|
|
|
|
Erase, // Can't be trivial, requires layer tracking
|
|
|
|
Overlay, // Can't be trivial, big math expression
|
|
|
|
HardLight, // Can't be trivial, big math expression
|
|
|
|
}
|
|
|
|
|
2023-07-26 23:25:26 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2022-12-23 22:06:19 +00:00
|
|
|
pub enum BlendType {
|
|
|
|
/// Trivial blends can be expressed with just a "draw bitmap" with blend states
|
|
|
|
Trivial(TrivialBlend),
|
|
|
|
|
|
|
|
/// Complex blends require a shader to express, so they are separated out into their own render
|
|
|
|
Complex(ComplexBlend),
|
2023-07-26 23:25:26 +00:00
|
|
|
|
|
|
|
/// Invoke a custom `PixelBender` shader.
|
|
|
|
Shader(PixelBenderShaderHandle),
|
2022-12-23 22:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BlendType {
|
2023-07-26 23:25:26 +00:00
|
|
|
pub fn from(mode: RenderBlendMode) -> BlendType {
|
2022-12-23 22:06:19 +00:00
|
|
|
match mode {
|
2023-07-26 23:25:26 +00:00
|
|
|
RenderBlendMode::Builtin(BlendMode::Normal) => BlendType::Trivial(TrivialBlend::Normal),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Layer) => BlendType::Trivial(TrivialBlend::Normal),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Multiply) => {
|
|
|
|
BlendType::Complex(ComplexBlend::Multiply)
|
|
|
|
}
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Screen) => BlendType::Trivial(TrivialBlend::Screen),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Lighten) => {
|
|
|
|
BlendType::Complex(ComplexBlend::Lighten)
|
|
|
|
}
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Darken) => BlendType::Complex(ComplexBlend::Darken),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Difference) => {
|
|
|
|
BlendType::Complex(ComplexBlend::Difference)
|
|
|
|
}
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Add) => BlendType::Trivial(TrivialBlend::Add),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Subtract) => {
|
|
|
|
BlendType::Trivial(TrivialBlend::Subtract)
|
|
|
|
}
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Invert) => BlendType::Complex(ComplexBlend::Invert),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Alpha) => BlendType::Complex(ComplexBlend::Alpha),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Erase) => BlendType::Complex(ComplexBlend::Erase),
|
|
|
|
RenderBlendMode::Builtin(BlendMode::Overlay) => {
|
|
|
|
BlendType::Complex(ComplexBlend::Overlay)
|
|
|
|
}
|
|
|
|
RenderBlendMode::Builtin(BlendMode::HardLight) => {
|
|
|
|
BlendType::Complex(ComplexBlend::HardLight)
|
|
|
|
}
|
|
|
|
RenderBlendMode::Shader(shader) => BlendType::Shader(shader),
|
2022-12-23 22:06:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn default_color(&self) -> wgpu::Color {
|
2023-06-21 23:59:06 +00:00
|
|
|
wgpu::Color::TRANSPARENT
|
2022-12-23 22:06:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Enum, Debug, Copy, Clone)]
|
|
|
|
pub enum TrivialBlend {
|
|
|
|
Normal,
|
|
|
|
Add,
|
|
|
|
Subtract,
|
2023-01-09 17:21:16 +00:00
|
|
|
Screen,
|
2022-12-23 22:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TrivialBlend {
|
|
|
|
pub fn blend_state(self) -> wgpu::BlendState {
|
|
|
|
// out = <src_factor> * src <operation> <dst_factor> * dst
|
|
|
|
match self {
|
|
|
|
TrivialBlend::Normal => wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
|
|
|
TrivialBlend::Add => wgpu::BlendState {
|
|
|
|
color: wgpu::BlendComponent {
|
|
|
|
src_factor: wgpu::BlendFactor::One,
|
|
|
|
dst_factor: wgpu::BlendFactor::One,
|
|
|
|
operation: wgpu::BlendOperation::Add,
|
|
|
|
},
|
|
|
|
alpha: wgpu::BlendComponent::OVER,
|
|
|
|
},
|
2023-01-09 17:21:16 +00:00
|
|
|
TrivialBlend::Screen => wgpu::BlendState {
|
|
|
|
color: wgpu::BlendComponent {
|
|
|
|
src_factor: wgpu::BlendFactor::One,
|
|
|
|
dst_factor: wgpu::BlendFactor::OneMinusSrc,
|
|
|
|
operation: wgpu::BlendOperation::Add,
|
|
|
|
},
|
|
|
|
alpha: wgpu::BlendComponent::OVER,
|
|
|
|
},
|
2022-12-23 22:06:19 +00:00
|
|
|
TrivialBlend::Subtract => wgpu::BlendState {
|
|
|
|
color: wgpu::BlendComponent {
|
|
|
|
src_factor: wgpu::BlendFactor::One,
|
|
|
|
dst_factor: wgpu::BlendFactor::One,
|
|
|
|
operation: wgpu::BlendOperation::ReverseSubtract,
|
|
|
|
},
|
|
|
|
alpha: wgpu::BlendComponent::OVER,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|