mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
158 lines
5.3 KiB
Rust
158 lines
5.3 KiB
Rust
use wgpu::util::DeviceExt;
|
|
use winit::dpi::PhysicalSize;
|
|
|
|
use super::Filter;
|
|
|
|
pub struct SquareFilter {
|
|
uniform_buffer: wgpu::Buffer,
|
|
bind_group: wgpu::BindGroup,
|
|
pipeline: wgpu::RenderPipeline,
|
|
}
|
|
|
|
impl SquareFilter {
|
|
pub fn new(
|
|
device: &wgpu::Device,
|
|
screen: &wgpu::TextureView,
|
|
resolution: PhysicalSize<u32>,
|
|
surface_format: wgpu::TextureFormat,
|
|
) -> SquareFilter {
|
|
let uniforms = Uniforms {
|
|
texture_scale: texture_scale_from_resolution(resolution),
|
|
};
|
|
|
|
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
label: None,
|
|
contents: bytemuck::cast_slice(&[uniforms]),
|
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
|
});
|
|
|
|
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,
|
|
view_dimension: wgpu::TextureViewDimension::D2,
|
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
|
},
|
|
count: None,
|
|
},
|
|
wgpu::BindGroupLayoutEntry {
|
|
binding: 1,
|
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
|
count: None,
|
|
},
|
|
wgpu::BindGroupLayoutEntry {
|
|
binding: 2,
|
|
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
|
ty: wgpu::BindingType::Buffer {
|
|
ty: wgpu::BufferBindingType::Uniform,
|
|
has_dynamic_offset: false,
|
|
min_binding_size: None,
|
|
},
|
|
count: None,
|
|
},
|
|
],
|
|
label: None,
|
|
});
|
|
|
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
|
mag_filter: wgpu::FilterMode::Linear,
|
|
..Default::default()
|
|
});
|
|
|
|
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
layout: &bind_group_layout,
|
|
entries: &[
|
|
wgpu::BindGroupEntry {
|
|
binding: 0,
|
|
resource: wgpu::BindingResource::TextureView(&screen),
|
|
},
|
|
wgpu::BindGroupEntry {
|
|
binding: 1,
|
|
resource: wgpu::BindingResource::Sampler(&sampler),
|
|
},
|
|
wgpu::BindGroupEntry {
|
|
binding: 2,
|
|
resource: uniform_buffer.as_entire_binding(),
|
|
},
|
|
],
|
|
label: None,
|
|
});
|
|
|
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
|
label: None,
|
|
source: wgpu::ShaderSource::Wgsl(include_str!("square.wgsl").into()),
|
|
});
|
|
|
|
let render_pipeline_layout =
|
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
|
label: None,
|
|
bind_group_layouts: &[&bind_group_layout],
|
|
push_constant_ranges: &[],
|
|
});
|
|
|
|
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
label: None,
|
|
layout: Some(&render_pipeline_layout),
|
|
vertex: wgpu::VertexState {
|
|
module: &shader,
|
|
entry_point: "vs_main",
|
|
buffers: &[],
|
|
},
|
|
fragment: Some(wgpu::FragmentState {
|
|
module: &shader,
|
|
entry_point: "fs_main",
|
|
targets: &[Some(wgpu::ColorTargetState {
|
|
format: surface_format,
|
|
blend: None,
|
|
write_mask: wgpu::ColorWrites::ALL,
|
|
})],
|
|
}),
|
|
primitive: Default::default(),
|
|
depth_stencil: None,
|
|
multisample: Default::default(),
|
|
multiview: None,
|
|
});
|
|
|
|
SquareFilter {
|
|
uniform_buffer,
|
|
bind_group,
|
|
pipeline: render_pipeline,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Filter for SquareFilter {
|
|
fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize<u32>) {
|
|
let uniforms = Uniforms {
|
|
texture_scale: texture_scale_from_resolution(new_size),
|
|
};
|
|
queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]));
|
|
}
|
|
|
|
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
|
|
render_pass.set_pipeline(&self.pipeline);
|
|
render_pass.set_bind_group(0, &self.bind_group, &[]);
|
|
render_pass.draw(0..6, 0..1);
|
|
}
|
|
}
|
|
|
|
fn texture_scale_from_resolution(res: PhysicalSize<u32>) -> [f32; 4] {
|
|
let scale = ((res.width as f32) / 160.0).min((res.height as f32) / 120.0);
|
|
[
|
|
scale / res.width as f32,
|
|
scale / res.height as f32,
|
|
2.0 / scale,
|
|
0.0,
|
|
]
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
struct Uniforms {
|
|
texture_scale: [f32; 4],
|
|
}
|