aboutsummaryrefslogtreecommitdiff
path: root/old/vgcodec/src/approximate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'old/vgcodec/src/approximate.rs')
-rw-r--r--old/vgcodec/src/approximate.rs175
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
+ }
+ }
+}