wgpu: Made Multiply, Add and Subtract blend modes use bitmap+blend
This commit is contained in:
parent
e69d76fa41
commit
f253abdbd1
|
@ -26,9 +26,6 @@ fn main_vertex(in: VertexInput) -> VertexOutput {
|
||||||
|
|
||||||
fn blend_func(src: vec3<f32>, dst: vec3<f32>) -> vec3<f32> {
|
fn blend_func(src: vec3<f32>, dst: vec3<f32>) -> vec3<f32> {
|
||||||
switch (blend.mode) {
|
switch (blend.mode) {
|
||||||
case 1: { // Multiply
|
|
||||||
return src * dst;
|
|
||||||
}
|
|
||||||
case 2: { // Screen
|
case 2: { // Screen
|
||||||
return (dst + src) - (dst * src);
|
return (dst + src) - (dst * src);
|
||||||
}
|
}
|
||||||
|
@ -72,11 +69,7 @@ fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
var src: vec4<f32> = textureSample(current_texture, texture_sampler, in.uv);
|
var src: vec4<f32> = textureSample(current_texture, texture_sampler, in.uv);
|
||||||
|
|
||||||
if (src.a > 0.0) {
|
if (src.a > 0.0) {
|
||||||
if (blend.mode == 6) { // Add
|
if (blend.mode == 9) { // Alpha
|
||||||
return src + dst;
|
|
||||||
} else if (blend.mode == 7) { // Subtract
|
|
||||||
return vec4<f32>(dst.rgb - src.rgb, src.a + dst.a);
|
|
||||||
} else if (blend.mode == 9) { // Alpha
|
|
||||||
return vec4<f32>(dst.rgb * src.a, src.a * dst.a);
|
return vec4<f32>(dst.rgb * src.a, src.a * dst.a);
|
||||||
} else if (blend.mode == 10) { // Erase
|
} else if (blend.mode == 10) { // Erase
|
||||||
return vec4<f32>(dst.rgb * (1.0 - src.a), (1.0 - src.a) * dst.a);
|
return vec4<f32>(dst.rgb * (1.0 - src.a), (1.0 - src.a) * dst.a);
|
||||||
|
|
|
@ -761,7 +761,7 @@ fn chunk_blends<'a>(
|
||||||
wgpu::TextureFormat::Rgba8Unorm,
|
wgpu::TextureFormat::Rgba8Unorm,
|
||||||
);
|
);
|
||||||
let target = surface.draw_commands(
|
let target = surface.draw_commands(
|
||||||
Some(wgpu::Color::TRANSPARENT),
|
Some(BlendType::from(*blend_mode).default_color()),
|
||||||
&descriptors,
|
&descriptors,
|
||||||
&meshes,
|
&meshes,
|
||||||
commands,
|
commands,
|
||||||
|
|
|
@ -30,13 +30,10 @@ impl Descriptors {
|
||||||
let quad = Quad::new(&device);
|
let quad = Quad::new(&device);
|
||||||
|
|
||||||
let blend_buffers = enum_map! {
|
let blend_buffers = enum_map! {
|
||||||
ComplexBlend::Multiply => 1,
|
|
||||||
ComplexBlend::Screen => 2,
|
ComplexBlend::Screen => 2,
|
||||||
ComplexBlend::Lighten => 3,
|
ComplexBlend::Lighten => 3,
|
||||||
ComplexBlend::Darken => 4,
|
ComplexBlend::Darken => 4,
|
||||||
ComplexBlend::Difference => 5,
|
ComplexBlend::Difference => 5,
|
||||||
ComplexBlend::Add => 6,
|
|
||||||
ComplexBlend::Subtract => 7,
|
|
||||||
ComplexBlend::Invert => 8,
|
ComplexBlend::Invert => 8,
|
||||||
ComplexBlend::Alpha => 9,
|
ComplexBlend::Alpha => 9,
|
||||||
ComplexBlend::Erase => 10,
|
ComplexBlend::Erase => 10,
|
||||||
|
|
|
@ -23,34 +23,31 @@ pub struct ShapePipeline {
|
||||||
#[derive(Enum, Debug, Copy, Clone)]
|
#[derive(Enum, Debug, Copy, Clone)]
|
||||||
pub enum TrivialBlend {
|
pub enum TrivialBlend {
|
||||||
Normal,
|
Normal,
|
||||||
|
Multiply,
|
||||||
|
Add,
|
||||||
|
Subtract,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Enum, Debug, Copy, Clone)]
|
#[derive(Enum, Debug, Copy, Clone)]
|
||||||
pub enum ComplexBlend {
|
pub enum ComplexBlend {
|
||||||
Multiply,
|
Screen, // Can't be trivial. (dst + src) - (dst * src)
|
||||||
Screen,
|
Lighten, // Might be trivial but I can't reproduce the right colors
|
||||||
Lighten,
|
Darken, // Might be trivial but I can't reproduce the right colors
|
||||||
Darken,
|
Difference, // Can't be trivial, relies on abs operation
|
||||||
Difference,
|
Invert, // May be trivial using a constant? Hard because it's without premultiplied alpha
|
||||||
Add,
|
Alpha, // Can't be trivial, requires layer tracking
|
||||||
Subtract,
|
Erase, // Can't be trivial, requires layer tracking
|
||||||
Invert,
|
Overlay, // Can't be trivial, big math expression
|
||||||
Alpha,
|
HardLight, // Can't be trivial, big math expression
|
||||||
Erase,
|
|
||||||
Overlay,
|
|
||||||
HardLight,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComplexBlend {
|
impl ComplexBlend {
|
||||||
pub fn id(&self) -> i32 {
|
pub fn id(&self) -> i32 {
|
||||||
match self {
|
match self {
|
||||||
ComplexBlend::Multiply => 1,
|
|
||||||
ComplexBlend::Screen => 2,
|
ComplexBlend::Screen => 2,
|
||||||
ComplexBlend::Lighten => 3,
|
ComplexBlend::Lighten => 3,
|
||||||
ComplexBlend::Darken => 4,
|
ComplexBlend::Darken => 4,
|
||||||
ComplexBlend::Difference => 5,
|
ComplexBlend::Difference => 5,
|
||||||
ComplexBlend::Add => 6,
|
|
||||||
ComplexBlend::Subtract => 7,
|
|
||||||
ComplexBlend::Invert => 8,
|
ComplexBlend::Invert => 8,
|
||||||
ComplexBlend::Alpha => 9,
|
ComplexBlend::Alpha => 9,
|
||||||
ComplexBlend::Erase => 10,
|
ComplexBlend::Erase => 10,
|
||||||
|
@ -62,7 +59,10 @@ impl ComplexBlend {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum BlendType {
|
pub enum BlendType {
|
||||||
|
/// Trivial blends can be expressed with just a "draw bitmap" with blend states
|
||||||
Trivial(TrivialBlend),
|
Trivial(TrivialBlend),
|
||||||
|
|
||||||
|
/// Complex blends require a shader to express, so they are separated out into their own render
|
||||||
Complex(ComplexBlend),
|
Complex(ComplexBlend),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +71,13 @@ impl BlendType {
|
||||||
match mode {
|
match mode {
|
||||||
BlendMode::Normal => BlendType::Trivial(TrivialBlend::Normal),
|
BlendMode::Normal => BlendType::Trivial(TrivialBlend::Normal),
|
||||||
BlendMode::Layer => BlendType::Trivial(TrivialBlend::Normal),
|
BlendMode::Layer => BlendType::Trivial(TrivialBlend::Normal),
|
||||||
BlendMode::Multiply => BlendType::Complex(ComplexBlend::Multiply),
|
BlendMode::Multiply => BlendType::Trivial(TrivialBlend::Multiply),
|
||||||
BlendMode::Screen => BlendType::Complex(ComplexBlend::Screen),
|
BlendMode::Screen => BlendType::Complex(ComplexBlend::Screen),
|
||||||
BlendMode::Lighten => BlendType::Complex(ComplexBlend::Lighten),
|
BlendMode::Lighten => BlendType::Complex(ComplexBlend::Lighten),
|
||||||
BlendMode::Darken => BlendType::Complex(ComplexBlend::Darken),
|
BlendMode::Darken => BlendType::Complex(ComplexBlend::Darken),
|
||||||
BlendMode::Difference => BlendType::Complex(ComplexBlend::Difference),
|
BlendMode::Difference => BlendType::Complex(ComplexBlend::Difference),
|
||||||
BlendMode::Add => BlendType::Complex(ComplexBlend::Add),
|
BlendMode::Add => BlendType::Trivial(TrivialBlend::Add),
|
||||||
BlendMode::Subtract => BlendType::Complex(ComplexBlend::Subtract),
|
BlendMode::Subtract => BlendType::Trivial(TrivialBlend::Subtract),
|
||||||
BlendMode::Invert => BlendType::Complex(ComplexBlend::Invert),
|
BlendMode::Invert => BlendType::Complex(ComplexBlend::Invert),
|
||||||
BlendMode::Alpha => BlendType::Complex(ComplexBlend::Alpha),
|
BlendMode::Alpha => BlendType::Complex(ComplexBlend::Alpha),
|
||||||
BlendMode::Erase => BlendType::Complex(ComplexBlend::Erase),
|
BlendMode::Erase => BlendType::Complex(ComplexBlend::Erase),
|
||||||
|
@ -85,6 +85,13 @@ impl BlendType {
|
||||||
BlendMode::HardLight => BlendType::Complex(ComplexBlend::HardLight),
|
BlendMode::HardLight => BlendType::Complex(ComplexBlend::HardLight),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_color(&self) -> wgpu::Color {
|
||||||
|
match self {
|
||||||
|
BlendType::Trivial(TrivialBlend::Multiply) => wgpu::Color::WHITE,
|
||||||
|
_ => wgpu::Color::TRANSPARENT,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -178,7 +185,32 @@ impl Pipelines {
|
||||||
let bitmap_pipelines: [ShapePipeline; TrivialBlend::LENGTH] = (0..TrivialBlend::LENGTH)
|
let bitmap_pipelines: [ShapePipeline; TrivialBlend::LENGTH] = (0..TrivialBlend::LENGTH)
|
||||||
.map(|blend| {
|
.map(|blend| {
|
||||||
let blend = match TrivialBlend::from_usize(blend) {
|
let blend = match TrivialBlend::from_usize(blend) {
|
||||||
|
// out = <src_factor> * src <operation> <dst_factor> * dst
|
||||||
TrivialBlend::Normal => wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
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,
|
||||||
|
},
|
||||||
|
TrivialBlend::Multiply => wgpu::BlendState {
|
||||||
|
color: wgpu::BlendComponent {
|
||||||
|
src_factor: wgpu::BlendFactor::Dst,
|
||||||
|
dst_factor: wgpu::BlendFactor::Zero,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
alpha: wgpu::BlendComponent::OVER,
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let name = format!("Bitmap ({blend:?})");
|
let name = format!("Bitmap ({blend:?})");
|
||||||
create_shape_pipeline(
|
create_shape_pipeline(
|
||||||
|
|
Loading…
Reference in New Issue