wgpu: Implement Multiply blend mode as a trivial blend
This commit is contained in:
parent
09608c2abc
commit
8db8e4669a
|
@ -1,48 +0,0 @@
|
||||||
#import common
|
|
||||||
|
|
||||||
struct VertexOutput {
|
|
||||||
@builtin(position) position: vec4<f32>,
|
|
||||||
@location(0) uv: vec2<f32>,
|
|
||||||
};
|
|
||||||
|
|
||||||
#if use_push_constants == true
|
|
||||||
var<push_constant> transforms: common::Transforms;
|
|
||||||
@group(1) @binding(0) var parent_texture: texture_2d<f32>;
|
|
||||||
@group(1) @binding(1) var current_texture: texture_2d<f32>;
|
|
||||||
@group(1) @binding(2) var texture_sampler: sampler;
|
|
||||||
#else
|
|
||||||
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
|
|
||||||
@group(2) @binding(0) var parent_texture: texture_2d<f32>;
|
|
||||||
@group(2) @binding(1) var current_texture: texture_2d<f32>;
|
|
||||||
@group(2) @binding(2) var texture_sampler: sampler;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@vertex
|
|
||||||
fn main_vertex(in: common::VertexInput) -> VertexOutput {
|
|
||||||
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 1.0, 1.0);
|
|
||||||
let uv = vec2<f32>((pos.x + 1.0) / 2.0, -((pos.y - 1.0) / 2.0));
|
|
||||||
return VertexOutput(pos, uv);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn blend_func(src: vec3<f32>, dst: vec3<f32>) -> vec3<f32> {
|
|
||||||
return src * dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
@fragment
|
|
||||||
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
|
||||||
// dst is the parent pixel we're blending onto
|
|
||||||
var dst: vec4<f32> = textureSample(parent_texture, texture_sampler, in.uv);
|
|
||||||
// src is the pixel that we want to apply
|
|
||||||
var src: vec4<f32> = textureSample(current_texture, texture_sampler, in.uv);
|
|
||||||
|
|
||||||
if (src.a > 0.0) {
|
|
||||||
return vec4<f32>(src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a) + src.a * dst.a * blend_func(src.rgb / src.a, dst.rgb / dst.a), src.a + dst.a * (1.0 - src.a));
|
|
||||||
} else {
|
|
||||||
if (true) {
|
|
||||||
// This needs to be in a branch because... reasons. Bug in naga.
|
|
||||||
// https://github.com/gfx-rs/naga/issues/2168
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ use swf::BlendMode;
|
||||||
|
|
||||||
#[derive(Enum, Debug, Copy, Clone)]
|
#[derive(Enum, Debug, Copy, Clone)]
|
||||||
pub enum ComplexBlend {
|
pub enum ComplexBlend {
|
||||||
Multiply, // Can't be trivial, 0 alpha is special case
|
|
||||||
Lighten, // Might be trivial but I can't reproduce the right colors
|
Lighten, // Might be trivial but I can't reproduce the right colors
|
||||||
Darken, // 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
|
Difference, // Can't be trivial, relies on abs operation
|
||||||
|
@ -29,7 +28,7 @@ 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::Trivial(TrivialBlend::Screen),
|
BlendMode::Screen => BlendType::Trivial(TrivialBlend::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),
|
||||||
|
@ -45,7 +44,10 @@ impl BlendType {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_color(&self) -> wgpu::Color {
|
pub fn default_color(&self) -> wgpu::Color {
|
||||||
wgpu::Color::TRANSPARENT
|
match self {
|
||||||
|
BlendType::Trivial(TrivialBlend::Multiply) => wgpu::Color::WHITE,
|
||||||
|
_ => wgpu::Color::TRANSPARENT,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +57,7 @@ pub enum TrivialBlend {
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
Screen,
|
Screen,
|
||||||
|
Multiply,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrivialBlend {
|
impl TrivialBlend {
|
||||||
|
@ -62,6 +65,14 @@ impl TrivialBlend {
|
||||||
// out = <src_factor> * src <operation> <dst_factor> * dst
|
// out = <src_factor> * src <operation> <dst_factor> * dst
|
||||||
match self {
|
match self {
|
||||||
TrivialBlend::Normal => wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
TrivialBlend::Normal => wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
||||||
|
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::Add => wgpu::BlendState {
|
TrivialBlend::Add => wgpu::BlendState {
|
||||||
color: wgpu::BlendComponent {
|
color: wgpu::BlendComponent {
|
||||||
src_factor: wgpu::BlendFactor::One,
|
src_factor: wgpu::BlendFactor::One,
|
||||||
|
|
|
@ -60,7 +60,6 @@ impl Shaders {
|
||||||
);
|
);
|
||||||
|
|
||||||
let blend_shaders = enum_map! {
|
let blend_shaders = enum_map! {
|
||||||
ComplexBlend::Multiply => make_shader(device, &mut composer, &shader_defs, "blend/multiply.wgsl", include_str!("../shaders/blend/multiply.wgsl")),
|
|
||||||
ComplexBlend::Lighten => make_shader(device, &mut composer, &shader_defs, "blend/lighten.wgsl", include_str!("../shaders/blend/lighten.wgsl")),
|
ComplexBlend::Lighten => make_shader(device, &mut composer, &shader_defs, "blend/lighten.wgsl", include_str!("../shaders/blend/lighten.wgsl")),
|
||||||
ComplexBlend::Darken => make_shader(device, &mut composer, &shader_defs, "blend/darken.wgsl", include_str!("../shaders/blend/darken.wgsl")),
|
ComplexBlend::Darken => make_shader(device, &mut composer, &shader_defs, "blend/darken.wgsl", include_str!("../shaders/blend/darken.wgsl")),
|
||||||
ComplexBlend::Difference => make_shader(device, &mut composer, &shader_defs, "blend/difference.wgsl", include_str!("../shaders/blend/difference.wgsl")),
|
ComplexBlend::Difference => make_shader(device, &mut composer, &shader_defs, "blend/difference.wgsl", include_str!("../shaders/blend/difference.wgsl")),
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Loading…
Reference in New Issue