diff --git a/uw8-window/src/gpu/crt.rs b/uw8-window/src/gpu/crt.rs index d75b2c0..4dbf3d1 100644 --- a/uw8-window/src/gpu/crt.rs +++ b/uw8-window/src/gpu/crt.rs @@ -112,7 +112,7 @@ impl CrtFilter { } impl Filter for CrtFilter { - fn resize(&self, queue: &wgpu::Queue, new_size: PhysicalSize) { + fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize) { let uniforms = Uniforms { texture_scale: texture_scale_from_resolution(new_size), }; diff --git a/uw8-window/src/gpu/fast_crt.rs b/uw8-window/src/gpu/fast_crt.rs index cc8f26a..ce6efaa 100644 --- a/uw8-window/src/gpu/fast_crt.rs +++ b/uw8-window/src/gpu/fast_crt.rs @@ -15,6 +15,7 @@ impl FastCrtFilter { screen: &wgpu::TextureView, resolution: PhysicalSize, surface_format: wgpu::TextureFormat, + chromatic: bool, ) -> FastCrtFilter { let uniforms = Uniforms { texture_scale: texture_scale_from_resolution(resolution), @@ -104,7 +105,11 @@ impl FastCrtFilter { }, fragment: Some(wgpu::FragmentState { module: &shader, - entry_point: "fs_main", + entry_point: if chromatic { + "fs_main_chromatic" + } else { + "fs_main" + }, targets: &[Some(wgpu::ColorTargetState { format: surface_format, blend: None, @@ -126,7 +131,7 @@ impl FastCrtFilter { } impl Filter for FastCrtFilter { - fn resize(&self, queue: &wgpu::Queue, new_size: PhysicalSize) { + fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize) { let uniforms = Uniforms { texture_scale: texture_scale_from_resolution(new_size), }; diff --git a/uw8-window/src/gpu/fast_crt.wgsl b/uw8-window/src/gpu/fast_crt.wgsl index 2688cd6..0680491 100644 --- a/uw8-window/src/gpu/fast_crt.wgsl +++ b/uw8-window/src/gpu/fast_crt.wgsl @@ -34,10 +34,9 @@ fn col_factor(offset: f32) -> f32 { return 1.0 / (1.0 + offset * offset * 16.0); } -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - let base = round(in.tex_coords) - vec2(0.5); - let frac = in.tex_coords - base; +fn sample_screen(tex_coords: vec2) -> vec4 { + let base = round(tex_coords) - vec2(0.5); + let frac = tex_coords - base; let top_factor = row_factor(frac.y); let bottom_factor = row_factor(frac.y - 1.0); @@ -52,3 +51,16 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { return textureSample(screen_texture, linear_sampler, vec2(u, v) / vec2(320.0, 240.0)) * (top_factor + bottom_factor) * (left_factor + right_factor) * 1.1; } +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return sample_screen(in.tex_coords); +} + +@fragment +fn fs_main_chromatic(in: VertexOutput) -> @location(0) vec4 { + let r = sample_screen(in.tex_coords + vec2(0.2, 0.2)).r; + let g = sample_screen(in.tex_coords + vec2(0.07, -0.27)).g; + let b = sample_screen(in.tex_coords + vec2(-0.27, 0.07)).b; + return vec4(r, g, b, 1.0); +} + diff --git a/uw8-window/src/gpu/mod.rs b/uw8-window/src/gpu/mod.rs index a0ef71e..407eab5 100644 --- a/uw8-window/src/gpu/mod.rs +++ b/uw8-window/src/gpu/mod.rs @@ -73,7 +73,7 @@ impl Window { present_mode: wgpu::PresentMode::AutoNoVsync, }; - let filter: Box = Box::new(CrtFilter::new( + let filter: Box = Box::new(AutoCrtFilter::new( &device, &palette_screen_mode.screen_view, window.inner_size(), @@ -167,6 +167,7 @@ impl WindowImpl for Window { &self.palette_screen_mode.screen_view, self.window.inner_size(), self.surface_config.format, + false, )) } Some(VirtualKeyCode::Key3) => { @@ -177,6 +178,23 @@ impl WindowImpl for Window { self.surface_config.format, )) } + Some(VirtualKeyCode::Key4) => { + self.filter = Box::new(FastCrtFilter::new( + &self.device, + &self.palette_screen_mode.screen_view, + self.window.inner_size(), + self.surface_config.format, + true, + )) + } + Some(VirtualKeyCode::Key5) => { + self.filter = Box::new(AutoCrtFilter::new( + &self.device, + &self.palette_screen_mode.screen_view, + self.window.inner_size(), + self.surface_config.format, + )) + } _ => (), } @@ -252,10 +270,49 @@ impl WindowImpl for Window { } trait Filter { - fn resize(&self, queue: &wgpu::Queue, new_size: PhysicalSize); + fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize); fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>); } +struct AutoCrtFilter { + small: CrtFilter, + large: FastCrtFilter, + resolution: PhysicalSize, +} + +impl AutoCrtFilter { + fn new( + device: &wgpu::Device, + screen: &wgpu::TextureView, + resolution: PhysicalSize, + surface_format: wgpu::TextureFormat, + ) -> AutoCrtFilter { + let small = CrtFilter::new(device, screen, resolution, surface_format); + let large = FastCrtFilter::new(device, screen, resolution, surface_format, true); + AutoCrtFilter { + small, + large, + resolution, + } + } +} + +impl Filter for AutoCrtFilter { + fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize) { + self.small.resize(queue, new_size); + self.large.resize(queue, new_size); + self.resolution = new_size; + } + + fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) { + if self.resolution.width < 960 || self.resolution.height < 720 { + self.small.render(render_pass); + } else { + self.large.render(render_pass); + } + } +} + struct PaletteScreenMode { framebuffer: wgpu::Texture, palette: wgpu::Texture, diff --git a/uw8-window/src/gpu/square.rs b/uw8-window/src/gpu/square.rs index 1171183..b06fcc1 100644 --- a/uw8-window/src/gpu/square.rs +++ b/uw8-window/src/gpu/square.rs @@ -126,7 +126,7 @@ impl SquareFilter { } impl Filter for SquareFilter { - fn resize(&self, queue: &wgpu::Queue, new_size: PhysicalSize) { + fn resize(&mut self, queue: &wgpu::Queue, new_size: PhysicalSize) { let uniforms = Uniforms { texture_scale: texture_scale_from_resolution(new_size), };