wgpu: Implement Screen blend mode as a trivial blend

This commit is contained in:
Nathan Adams 2023-01-09 18:21:16 +01:00 committed by Aaron Hill
parent b7986406a8
commit 09608c2abc
5 changed files with 10 additions and 51 deletions

View File

@ -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 (dst + src) - (dst * src);
}
@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;
}
}

View File

@ -5,7 +5,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 Multiply, // Can't be trivial, 0 alpha is special case
Screen, // Can't be trivial. (dst + src) - (dst * src)
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
@ -31,7 +30,7 @@ impl BlendType {
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::Complex(ComplexBlend::Multiply),
BlendMode::Screen => BlendType::Complex(ComplexBlend::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),
BlendMode::Difference => BlendType::Complex(ComplexBlend::Difference), BlendMode::Difference => BlendType::Complex(ComplexBlend::Difference),
@ -55,6 +54,7 @@ pub enum TrivialBlend {
Normal, Normal,
Add, Add,
Subtract, Subtract,
Screen,
} }
impl TrivialBlend { impl TrivialBlend {
@ -70,6 +70,14 @@ impl TrivialBlend {
}, },
alpha: wgpu::BlendComponent::OVER, alpha: wgpu::BlendComponent::OVER,
}, },
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,
},
TrivialBlend::Subtract => wgpu::BlendState { TrivialBlend::Subtract => wgpu::BlendState {
color: wgpu::BlendComponent { color: wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::One, src_factor: wgpu::BlendFactor::One,

View File

@ -61,7 +61,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::Multiply => make_shader(device, &mut composer, &shader_defs, "blend/multiply.wgsl", include_str!("../shaders/blend/multiply.wgsl")),
ComplexBlend::Screen => make_shader(device, &mut composer, &shader_defs, "blend/screen.wgsl", include_str!("../shaders/blend/screen.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