wgpu: Implement Bevel filter
This commit is contained in:
parent
771f568509
commit
b1ba144166
|
@ -0,0 +1,84 @@
|
|||
struct Filter {
|
||||
highlight_color: vec4<f32>,
|
||||
shadow_color: vec4<f32>,
|
||||
strength: f32,
|
||||
bevel_type: u32,
|
||||
knockout: u32,
|
||||
composite_source: u32,
|
||||
}
|
||||
|
||||
@group(0) @binding(0) var texture: texture_2d<f32>;
|
||||
@group(0) @binding(1) var texture_sampler: sampler;
|
||||
@group(0) @binding(2) var<uniform> filter_args: Filter;
|
||||
@group(0) @binding(3) var blurred: texture_2d<f32>;
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) position: vec4<f32>,
|
||||
@location(0) source_uv: vec2<f32>,
|
||||
@location(1) blur_uv_left: vec2<f32>,
|
||||
@location(2) blur_uv_right: vec2<f32>,
|
||||
};
|
||||
|
||||
struct VertexInput {
|
||||
/// The position of the vertex in texture space (topleft 0,0, bottomright 1,1)
|
||||
@location(0) position: vec2<f32>,
|
||||
|
||||
/// The coordinate of the source texture to sample in texture space (topleft 0,0, bottomright 1,1)
|
||||
@location(1) source_uv: vec2<f32>,
|
||||
|
||||
/// The coordinate of the blur texture to sample in texture space (topleft 0,0, bottomright 1,1)
|
||||
@location(2) blur_uv_left: vec2<f32>,
|
||||
|
||||
/// The coordinate of the blur texture to sample in texture space (topleft 0,0, bottomright 1,1)
|
||||
@location(3) blur_uv_right: vec2<f32>,
|
||||
};
|
||||
|
||||
@vertex
|
||||
fn main_vertex(in: VertexInput) -> VertexOutput {
|
||||
// Convert texture space (topleft 0,0 to bottomright 1,1) to render space (topleft -1,1 to bottomright 1,-1)
|
||||
let pos = vec4<f32>((in.position.x * 2.0 - 1.0), (1.0 - in.position.y * 2.0), 0.0, 1.0);
|
||||
return VertexOutput(pos, in.source_uv, in.blur_uv_left, in.blur_uv_right);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
let knockout = filter_args.knockout > 0u;
|
||||
let composite_source = filter_args.composite_source > 0u;
|
||||
var blur_left = textureSample(blurred, texture_sampler, in.blur_uv_left).a;
|
||||
var blur_right = textureSample(blurred, texture_sampler, in.blur_uv_right).a;
|
||||
var dest = textureSample(texture, texture_sampler, in.source_uv);
|
||||
|
||||
let outer = filter_args.bevel_type == 0u || filter_args.bevel_type == 2u;
|
||||
let inner = filter_args.bevel_type == 1u || filter_args.bevel_type == 2u;
|
||||
|
||||
if (in.blur_uv_left.x < 0.0 || in.blur_uv_left.x > 1.0 || in.blur_uv_left.y < 0.0 || in.blur_uv_left.y > 1.0) {
|
||||
blur_left = 0.0;
|
||||
}
|
||||
if (in.blur_uv_right.x < 0.0 || in.blur_uv_right.x > 1.0 || in.blur_uv_right.y < 0.0 || in.blur_uv_right.y > 1.0) {
|
||||
blur_right = 0.0;
|
||||
}
|
||||
|
||||
let highlight_alpha = saturate((blur_left - blur_right) * filter_args.strength);
|
||||
let shadow_alpha = saturate((blur_right - blur_left) * filter_args.strength);
|
||||
let glow = filter_args.highlight_color * highlight_alpha + filter_args.shadow_color * shadow_alpha;
|
||||
|
||||
if (inner && outer) {
|
||||
if (knockout) {
|
||||
return glow;
|
||||
} else {
|
||||
return dest - dest * glow.a + glow;
|
||||
}
|
||||
} else if (inner) {
|
||||
if (knockout) {
|
||||
return glow * dest.a;
|
||||
} else {
|
||||
return glow * dest.a + dest * (1.0 - glow.a);
|
||||
}
|
||||
} else {
|
||||
if (knockout) {
|
||||
return glow - glow * dest.a;
|
||||
} else {
|
||||
return dest + glow - glow * dest.a;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -810,6 +810,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
| Filter::DropShadowFilter(_)
|
||||
| Filter::ColorMatrixFilter(_)
|
||||
| Filter::ShaderFilter(_)
|
||||
| Filter::BevelFilter(_)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod bevel;
|
||||
mod blur;
|
||||
mod color_matrix;
|
||||
mod drop_shadow;
|
||||
|
@ -9,6 +10,7 @@ use std::sync::{Mutex, OnceLock};
|
|||
|
||||
use crate::buffer_pool::TexturePool;
|
||||
use crate::descriptors::Descriptors;
|
||||
use crate::filters::bevel::BevelFilter;
|
||||
use crate::filters::blur::BlurFilter;
|
||||
use crate::filters::color_matrix::ColorMatrixFilter;
|
||||
use crate::filters::drop_shadow::DropShadowFilter;
|
||||
|
@ -130,6 +132,73 @@ impl<'a> FilterSource<'a> {
|
|||
usage: wgpu::BufferUsages::VERTEX,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn vertices_with_highlight_and_shadow(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
blur_offset: (f32, f32),
|
||||
) -> wgpu::Buffer {
|
||||
let source_width = self.texture.width() as f32;
|
||||
let source_height = self.texture.height() as f32;
|
||||
let source_left = self.point.0 as f32;
|
||||
let source_top = self.point.1 as f32;
|
||||
let source_right = (self.point.0 + self.size.0) as f32;
|
||||
let source_bottom = (self.point.1 + self.size.1) as f32;
|
||||
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: create_debug_label!("Filter vertices").as_deref(),
|
||||
contents: bytemuck::cast_slice(&[
|
||||
FilterVertexWithDoubleBlur {
|
||||
position: [0.0, 0.0],
|
||||
source_uv: [source_left / source_width, source_top / source_height],
|
||||
blur_uv_left: [
|
||||
(source_left + blur_offset.0) / source_width,
|
||||
(source_top + blur_offset.1) / source_height,
|
||||
],
|
||||
blur_uv_right: [
|
||||
(source_left - blur_offset.0) / source_width,
|
||||
(source_top - blur_offset.1) / source_height,
|
||||
],
|
||||
},
|
||||
FilterVertexWithDoubleBlur {
|
||||
position: [1.0, 0.0],
|
||||
source_uv: [source_right / source_width, source_top / source_height],
|
||||
blur_uv_left: [
|
||||
(source_right + blur_offset.0) / source_width,
|
||||
(source_top + blur_offset.1) / source_height,
|
||||
],
|
||||
blur_uv_right: [
|
||||
(source_right - blur_offset.0) / source_width,
|
||||
(source_top - blur_offset.1) / source_height,
|
||||
],
|
||||
},
|
||||
FilterVertexWithDoubleBlur {
|
||||
position: [1.0, 1.0],
|
||||
source_uv: [source_right / source_width, source_bottom / source_height],
|
||||
blur_uv_left: [
|
||||
(source_right + blur_offset.0) / source_width,
|
||||
(source_bottom + blur_offset.1) / source_height,
|
||||
],
|
||||
blur_uv_right: [
|
||||
(source_right - blur_offset.0) / source_width,
|
||||
(source_bottom - blur_offset.1) / source_height,
|
||||
],
|
||||
},
|
||||
FilterVertexWithDoubleBlur {
|
||||
position: [0.0, 1.0],
|
||||
source_uv: [source_left / source_width, source_bottom / source_height],
|
||||
blur_uv_left: [
|
||||
(source_left + blur_offset.0) / source_width,
|
||||
(source_bottom + blur_offset.1) / source_height,
|
||||
],
|
||||
blur_uv_right: [
|
||||
(source_left - blur_offset.0) / source_width,
|
||||
(source_bottom - blur_offset.1) / source_height,
|
||||
],
|
||||
},
|
||||
]),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Filters {
|
||||
|
@ -137,6 +206,7 @@ pub struct Filters {
|
|||
pub color_matrix: ColorMatrixFilter,
|
||||
pub shader: ShaderFilter,
|
||||
pub glow: GlowFilter,
|
||||
pub bevel: BevelFilter,
|
||||
}
|
||||
|
||||
impl Filters {
|
||||
|
@ -146,6 +216,7 @@ impl Filters {
|
|||
color_matrix: ColorMatrixFilter::new(device),
|
||||
shader: ShaderFilter::new(),
|
||||
glow: GlowFilter::new(device),
|
||||
bevel: BevelFilter::new(device),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,6 +234,10 @@ impl Filters {
|
|||
Filter::DropShadowFilter(filter) => {
|
||||
DropShadowFilter::calculate_dest_rect(filter, source_rect, &self.blur, &self.glow)
|
||||
}
|
||||
Filter::BevelFilter(filter) => {
|
||||
self.bevel
|
||||
.calculate_dest_rect(filter, source_rect, &self.blur)
|
||||
}
|
||||
_ => source_rect,
|
||||
}
|
||||
}
|
||||
|
@ -215,10 +290,17 @@ impl Filters {
|
|||
&self.blur,
|
||||
&self.glow,
|
||||
)),
|
||||
Filter::BevelFilter(filter) => Some(descriptors.filters.bevel.apply(
|
||||
descriptors,
|
||||
texture_pool,
|
||||
draw_encoder,
|
||||
&source,
|
||||
&filter,
|
||||
&self.blur,
|
||||
)),
|
||||
filter => {
|
||||
static WARNED_FILTERS: OnceLock<Mutex<HashSet<&'static str>>> = OnceLock::new();
|
||||
let name = match filter {
|
||||
Filter::BevelFilter(_) => "BevelFilter",
|
||||
Filter::GradientGlowFilter(_) => "GradientGlowFilter",
|
||||
Filter::GradientBevelFilter(_) => "GradientBevelFilter",
|
||||
Filter::ConvolutionFilter(_) => "ConvolutionFilter",
|
||||
|
@ -227,6 +309,7 @@ impl Filters {
|
|||
| Filter::BlurFilter(_)
|
||||
| Filter::GlowFilter(_)
|
||||
| Filter::DropShadowFilter(_)
|
||||
| Filter::BevelFilter(_)
|
||||
| Filter::ShaderFilter(_) => unreachable!(),
|
||||
};
|
||||
// Only warn once per filter type
|
||||
|
@ -297,3 +380,24 @@ pub const VERTEX_BUFFERS_DESCRIPTION_FILTERS_WITH_BLUR: [wgpu::VertexBufferLayou
|
|||
2 => Float32x2,
|
||||
],
|
||||
}];
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
||||
pub struct FilterVertexWithDoubleBlur {
|
||||
pub position: [f32; 2],
|
||||
pub source_uv: [f32; 2],
|
||||
pub blur_uv_left: [f32; 2],
|
||||
pub blur_uv_right: [f32; 2],
|
||||
}
|
||||
|
||||
pub const VERTEX_BUFFERS_DESCRIPTION_FILTERS_WITH_DOUBLE_BLUR: [wgpu::VertexBufferLayout; 1] =
|
||||
[wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<FilterVertexWithDoubleBlur>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![
|
||||
0 => Float32x2,
|
||||
1 => Float32x2,
|
||||
2 => Float32x2,
|
||||
3 => Float32x2,
|
||||
],
|
||||
}];
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
use crate::backend::RenderTargetMode;
|
||||
use crate::buffer_pool::TexturePool;
|
||||
use crate::descriptors::Descriptors;
|
||||
use crate::filters::blur::BlurFilter;
|
||||
use crate::filters::{FilterSource, VERTEX_BUFFERS_DESCRIPTION_FILTERS_WITH_DOUBLE_BLUR};
|
||||
use crate::surface::target::CommandTarget;
|
||||
use crate::utils::SampleCountMap;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use std::sync::OnceLock;
|
||||
use swf::{BevelFilter as BevelFilterArgs, Rectangle};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Pod, Zeroable, PartialEq)]
|
||||
struct BevelUniform {
|
||||
highlight_color: [f32; 4],
|
||||
shadow_color: [f32; 4],
|
||||
strength: f32,
|
||||
bevel_type: u32, // 0 outer, 1 inner, 2 full
|
||||
knockout: u32, // a wasteful bool, but we need to be aligned anyway
|
||||
composite_source: u32, // undocumented flash feature, another bool
|
||||
}
|
||||
|
||||
pub struct BevelFilter {
|
||||
bind_group_layout: wgpu::BindGroupLayout,
|
||||
pipeline_layout: wgpu::PipelineLayout,
|
||||
pipeline: SampleCountMap<OnceLock<wgpu::RenderPipeline>>,
|
||||
}
|
||||
|
||||
impl BevelFilter {
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: false },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: wgpu::BufferSize::new(
|
||||
std::mem::size_of::<BevelUniform>() as u64,
|
||||
),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: false },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: create_debug_label!("Bevel filter binds").as_deref(),
|
||||
});
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: None,
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
Self {
|
||||
pipeline: Default::default(),
|
||||
pipeline_layout,
|
||||
bind_group_layout,
|
||||
}
|
||||
}
|
||||
|
||||
fn pipeline(&self, descriptors: &Descriptors, msaa_sample_count: u32) -> &wgpu::RenderPipeline {
|
||||
self.pipeline.get_or_init(msaa_sample_count, || {
|
||||
let label = create_debug_label!("Bevel Filter ({} msaa)", msaa_sample_count);
|
||||
descriptors
|
||||
.device
|
||||
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: label.as_deref(),
|
||||
layout: Some(&self.pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &descriptors.shaders.bevel_filter,
|
||||
entry_point: "main_vertex",
|
||||
buffers: &VERTEX_BUFFERS_DESCRIPTION_FILTERS_WITH_DOUBLE_BLUR,
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
polygon_mode: wgpu::PolygonMode::default(),
|
||||
unclipped_depth: false,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: msaa_sample_count,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &descriptors.shaders.bevel_filter,
|
||||
entry_point: "main_fragment",
|
||||
targets: &[Some(wgpu::TextureFormat::Rgba8Unorm.into())],
|
||||
}),
|
||||
multiview: None,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn calculate_dest_rect(
|
||||
&self,
|
||||
filter: &BevelFilterArgs,
|
||||
source_rect: Rectangle<i32>,
|
||||
blur_filter: &BlurFilter,
|
||||
) -> Rectangle<i32> {
|
||||
let mut result = blur_filter.calculate_dest_rect(&filter.inner_blur_filter(), source_rect);
|
||||
let distance = filter.distance.to_f32();
|
||||
let angle = filter.angle.to_f32();
|
||||
let x = (angle.cos() * distance).ceil() as i32;
|
||||
let y = (angle.sin() * distance).ceil() as i32;
|
||||
if x < 0 {
|
||||
result.x_min += x;
|
||||
result.x_max -= x;
|
||||
} else {
|
||||
result.x_max += x;
|
||||
result.x_min -= x;
|
||||
}
|
||||
if y < 0 {
|
||||
result.y_min += y;
|
||||
result.y_max -= y;
|
||||
} else {
|
||||
result.y_max += y;
|
||||
result.y_min -= y;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn apply(
|
||||
&self,
|
||||
descriptors: &Descriptors,
|
||||
texture_pool: &mut TexturePool,
|
||||
draw_encoder: &mut wgpu::CommandEncoder,
|
||||
source: &FilterSource,
|
||||
filter: &BevelFilterArgs,
|
||||
blur_filter: &BlurFilter,
|
||||
) -> CommandTarget {
|
||||
let sample_count = source.texture.sample_count();
|
||||
let format = source.texture.format();
|
||||
let pipeline = self.pipeline(descriptors, sample_count);
|
||||
let blurred = blur_filter.apply(
|
||||
descriptors,
|
||||
texture_pool,
|
||||
draw_encoder,
|
||||
source,
|
||||
&filter.inner_blur_filter(),
|
||||
);
|
||||
let blurred_texture = if let Some(blurred) = &blurred {
|
||||
blurred.ensure_cleared(draw_encoder);
|
||||
blurred.color_texture()
|
||||
} else {
|
||||
source.texture
|
||||
};
|
||||
let source_view = source.texture.create_view(&Default::default());
|
||||
let blurred_view = blurred_texture.create_view(&Default::default());
|
||||
let distance = filter.distance.to_f32();
|
||||
let angle = filter.angle.to_f32();
|
||||
let blur_offset = (angle.cos() * distance, angle.sin() * distance);
|
||||
|
||||
let target = CommandTarget::new(
|
||||
descriptors,
|
||||
texture_pool,
|
||||
wgpu::Extent3d {
|
||||
width: source.size.0,
|
||||
height: source.size.1,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
format,
|
||||
sample_count,
|
||||
RenderTargetMode::FreshWithColor(wgpu::Color::TRANSPARENT),
|
||||
draw_encoder,
|
||||
);
|
||||
let mut highlight_color = [
|
||||
f32::from(filter.highlight_color.r) / 255.0,
|
||||
f32::from(filter.highlight_color.g) / 255.0,
|
||||
f32::from(filter.highlight_color.b) / 255.0,
|
||||
f32::from(filter.highlight_color.a) / 255.0,
|
||||
];
|
||||
highlight_color[0] *= highlight_color[3];
|
||||
highlight_color[1] *= highlight_color[3];
|
||||
highlight_color[2] *= highlight_color[3];
|
||||
let mut shadow_color = [
|
||||
f32::from(filter.shadow_color.r) / 255.0,
|
||||
f32::from(filter.shadow_color.g) / 255.0,
|
||||
f32::from(filter.shadow_color.b) / 255.0,
|
||||
f32::from(filter.shadow_color.a) / 255.0,
|
||||
];
|
||||
shadow_color[0] *= shadow_color[3];
|
||||
shadow_color[1] *= shadow_color[3];
|
||||
shadow_color[2] *= shadow_color[3];
|
||||
let buffer = descriptors
|
||||
.device
|
||||
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: create_debug_label!("Filter arguments").as_deref(),
|
||||
contents: bytemuck::cast_slice(&[BevelUniform {
|
||||
highlight_color,
|
||||
shadow_color,
|
||||
strength: filter.strength.to_f32(),
|
||||
bevel_type: if filter.is_on_top() {
|
||||
2
|
||||
} else if filter.is_inner() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
knockout: if filter.is_knockout() { 1 } else { 0 },
|
||||
composite_source: 1,
|
||||
}]),
|
||||
usage: wgpu::BufferUsages::UNIFORM,
|
||||
});
|
||||
let vertices = source.vertices_with_highlight_and_shadow(&descriptors.device, blur_offset);
|
||||
let filter_group = descriptors
|
||||
.device
|
||||
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: create_debug_label!("Filter group").as_deref(),
|
||||
layout: &self.bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&source_view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(
|
||||
descriptors.bitmap_samplers.get_sampler(false, false),
|
||||
),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: buffer.as_entire_binding(),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 3,
|
||||
resource: wgpu::BindingResource::TextureView(&blurred_view),
|
||||
},
|
||||
],
|
||||
});
|
||||
let mut render_pass = draw_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: create_debug_label!("Bevel filter").as_deref(),
|
||||
color_attachments: &[target.color_attachments()],
|
||||
depth_stencil_attachment: None,
|
||||
});
|
||||
render_pass.set_pipeline(pipeline);
|
||||
|
||||
render_pass.set_bind_group(0, &filter_group, &[]);
|
||||
|
||||
render_pass.set_vertex_buffer(0, vertices.slice(..));
|
||||
render_pass.set_index_buffer(
|
||||
descriptors.quad.indices.slice(..),
|
||||
wgpu::IndexFormat::Uint32,
|
||||
);
|
||||
render_pass.draw_indexed(0..6, 0, 0..1);
|
||||
drop(render_pass);
|
||||
target
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ pub struct Shaders {
|
|||
pub color_matrix_filter: wgpu::ShaderModule,
|
||||
pub blur_filter: wgpu::ShaderModule,
|
||||
pub glow_filter: wgpu::ShaderModule,
|
||||
pub bevel_filter: wgpu::ShaderModule,
|
||||
}
|
||||
|
||||
impl Shaders {
|
||||
|
@ -95,6 +96,13 @@ impl Shaders {
|
|||
"filter/glow.wgsl",
|
||||
include_str!("../shaders/filter/glow.wgsl"),
|
||||
);
|
||||
let bevel_filter = make_shader(
|
||||
device,
|
||||
&mut composer,
|
||||
&shader_defs,
|
||||
"filter/bevel.wgsl",
|
||||
include_str!("../shaders/filter/bevel.wgsl"),
|
||||
);
|
||||
let gradient_shader = make_shader(
|
||||
device,
|
||||
&mut composer,
|
||||
|
@ -126,6 +134,7 @@ impl Shaders {
|
|||
color_matrix_filter,
|
||||
blur_filter,
|
||||
glow_filter,
|
||||
bevel_filter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 213 KiB |
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
num_frames = 1
|
||||
|
||||
[image_comparison]
|
||||
tolerance = 3
|
||||
|
||||
[player_options]
|
||||
with_renderer = { optional = false, sample_count = 1 }
|
Binary file not shown.
After Width: | Height: | Size: 376 KiB |
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
num_frames = 1
|
||||
|
||||
[image_comparison]
|
||||
tolerance = 3
|
||||
|
||||
[player_options]
|
||||
with_renderer = { optional = false, sample_count = 1 }
|
Binary file not shown.
After Width: | Height: | Size: 230 KiB |
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
num_frames = 1
|
||||
|
||||
[image_comparison]
|
||||
tolerance = 3
|
||||
|
||||
[player_options]
|
||||
with_renderer = { optional = false, sample_count = 1 }
|
Binary file not shown.
After Width: | Height: | Size: 355 KiB |
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
num_frames = 1
|
||||
|
||||
[image_comparison]
|
||||
tolerance = 3
|
||||
|
||||
[player_options]
|
||||
with_renderer = { optional = false, sample_count = 1 }
|
Loading…
Reference in New Issue