diff options
Diffstat (limited to 'old/vgcodec/src/approximate.rs')
-rw-r--r-- | old/vgcodec/src/approximate.rs | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/old/vgcodec/src/approximate.rs b/old/vgcodec/src/approximate.rs new file mode 100644 index 0000000..5bff325 --- /dev/null +++ b/old/vgcodec/src/approximate.rs @@ -0,0 +1,175 @@ +use crate::{ + app::App, + diff::Differ, + export::Exporter, + paint::{PaintUniforms, Painter}, +}; +use log::{debug, info, warn}; +use rand::Rng; +use std::sync::Arc; +use wgpu::{Extent3d, Texture, TextureUsages}; + +#[allow(unused)] +pub struct Approximator { + app: Arc<App>, + size: Extent3d, + differ: Differ, + painter: Painter, + exporter: Exporter, + + tex_approx: Texture, + tex_savestate: Texture, + tex_target: Texture, +} + +impl Approximator { + pub fn new(app: &Arc<App>, tex_target: Texture, size: Extent3d) -> Self { + let App { device, .. } = app.as_ref(); + let tex_approx = device.create_texture(&wgpu::TextureDescriptor { + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8Unorm, + usage: TextureUsages::COPY_DST + | TextureUsages::TEXTURE_BINDING + | TextureUsages::STORAGE_BINDING + | TextureUsages::COPY_SRC, + label: None, + }); + let tex_savestate = device.create_texture(&wgpu::TextureDescriptor { + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8Unorm, + usage: TextureUsages::COPY_DST | TextureUsages::COPY_SRC, + label: None, + }); + + // let initial_init = (0..) + // write_texture(queue, &tex_approx, initial_init, size); + + let differ = Differ::new(&app, size, &tex_approx, &tex_target); + let painter = Painter::new(&app, size, &tex_approx); + let exporter = Exporter::new(&app, size); + + Approximator { + app: app.clone(), + size, + differ, + tex_savestate, + tex_approx, + tex_target, + painter, + exporter, + } + } + + pub fn save(&self) { + self.app + .copy_texture(&self.tex_approx, &self.tex_savestate, self.size); + } + pub fn restore(&self) { + self.app + .copy_texture(&self.tex_savestate, &self.tex_approx, self.size); + } + + pub async fn run(&mut self, iters: usize, out: &str) -> Vec<PaintUniforms> { + let rscale = self.size.width as f32 * 0.1; + let mut objects = vec![]; + for i in 0..iters { + let mut p = PaintUniforms { + x: rand::thread_rng().gen_range(0.0..self.size.width as f32), + y: rand::thread_rng().gen_range(0.0..self.size.height as f32), + rx: rscale, + ry: rscale, + r: rand::thread_rng().gen_range(0.0..1.0), + g: rand::thread_rng().gen_range(0.0..1.0), + b: rand::thread_rng().gen_range(0.0..1.0), + }; + + // Find initial diff + self.save(); + self.painter.run(p); + let initial_diff = pollster::block_on(self.differ.run()); + debug!("initial diff={initial_diff}"); + self.restore(); + + let mut cd = initial_diff; + self.save(); + let ok = loop { + let mut q = 0; + let mut k = |k: usize| { + q += k; + q == 0 + }; + if k(self.optimize_param(&mut cd, &mut p, "more red", |p| p.r += 0.1)) { + k(self.optimize_param(&mut cd, &mut p, "less red", |p| p.r -= 0.1)); + } + if k(self.optimize_param(&mut cd, &mut p, "more green", |p| p.g += 0.1)) { + k(self.optimize_param(&mut cd, &mut p, "less green", |p| p.g -= 0.1)); + } + if k(self.optimize_param(&mut cd, &mut p, "more blue", |p| p.b += 0.1)) { + k(self.optimize_param(&mut cd, &mut p, "less blue", |p| p.b -= 0.1)); + } + if k(self.optimize_param(&mut cd, &mut p, "increase rx", |p| p.rx *= 1.5)) { + k(self.optimize_param(&mut cd, &mut p, "decrease rx", |p| p.rx /= 1.5)); + } + if k(self.optimize_param(&mut cd, &mut p, "increase ry", |p| p.ry *= 1.5)) { + k(self.optimize_param(&mut cd, &mut p, "decrease ry", |p| p.ry /= 1.5)); + } + if k(self.optimize_param(&mut cd, &mut p, "move right", |p| p.x += 8.0)) { + k(self.optimize_param(&mut cd, &mut p, "move left", |p| p.x -= 8.0)); + } + if k(self.optimize_param(&mut cd, &mut p, "move down", |p| p.y += 8.0)) { + k(self.optimize_param(&mut cd, &mut p, "move up", |p| p.y -= 8.0)); + } + if p.rx < 5.0 || p.ry < 5.0 { + break false; + } + if q == 0 { + break true; + } + }; + if ok { + self.painter.run(p); + info!("{i} (improvement={})", initial_diff - cd); + objects.push(p); + } else { + warn!("object aborted"); + } + } + self.exporter.run(&self.tex_approx, out).await; + return objects; + } + + pub fn optimize_param<F>( + &self, + current_diff: &mut u32, + params: &mut PaintUniforms, + label: &'static str, + f: F, + ) -> usize + where + F: Fn(&mut PaintUniforms) -> (), + { + let mut p = params.clone(); + let mut i = 0; + loop { + f(&mut p); + self.painter.run(p); + let diff = pollster::block_on(self.differ.run()); + // pollster::block_on(self.exporter.run(&self.tex_approx, &format!("a/snap.png"))); + debug!("try {label:?} ({})", diff as i64 - *current_diff as i64); + self.restore(); + if diff >= *current_diff { + break i; + } + debug!("applied {label:?}"); + i += 1; + *current_diff = diff; + *params = p + } + } +} |