Browse Source

Hacky and quick sky generator

Getty Ritter 6 years ago
commit
d413ef58d7
3 changed files with 138 additions and 0 deletions
  1. 3 0
      .gitignore
  2. 10 0
      Cargo.toml
  3. 125 0
      src/main.rs

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+/target/
+**/*.rs.bk
+*~

+ 10 - 0
Cargo.toml

@@ -0,0 +1,10 @@
+[package]
+name = "here-comes-a-thought"
+version = "0.1.0"
+authors = ["gdritter"]
+
+[dependencies]
+cairo-rs = { version = "0.3.0", features = ["png"] }
+png = "0.11.0"
+rand = "0.3.18"
+palette = "0.2.1"

+ 125 - 0
src/main.rs

@@ -0,0 +1,125 @@
+extern crate cairo;
+extern crate palette;
+extern crate rand;
+
+use rand::Rng;
+use cairo::Gradient;
+
+const WIDTH: i32 = 3840;
+const HEIGHT: i32 = 2160;
+
+fn cloud(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
+    let x_scale = rng.gen::<f64>() * 2.0 + 1.0;
+    let x = (rng.gen::<f64>() * WIDTH as f64) / x_scale;
+    let y = rng.gen::<f64>() * HEIGHT as f64;
+    let num_circles = 2 + (rng.gen::<isize>() % 2);
+    let vec: Vec<(f64, f64)> = (0..num_circles).map(|_| {
+        let width = 60.0 + rng.gen::<f64>() * 200.0;
+        let dist = 30.0 + rng.gen::<f64>() * 30.0;
+        (width, dist)
+    }).collect();
+
+    let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
+
+    surf.save();
+    let mut max_y = 0.0;
+    let mut offset = x;
+    surf.scale(x_scale, 1.0);
+    surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
+    for (width, dist) in vec {
+        surf.arc(offset, y, width, 0.0, 3.14159 * 2.0);
+        surf.fill();
+        offset = offset + width + dist;
+        max_y = if width > max_y { width } else { max_y };
+    }
+    surf.set_source_rgba(0.0, 0.0, 0.0, 0.0);
+    surf.set_operator(cairo::Operator::Source);
+    surf.rectangle(x - 260.0, y, offset + 260.0, max_y);
+    surf.fill();
+    surf.restore();
+
+    surf.set_source_rgba(1.0, 1.0, 1.0, 0.8);
+    ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
+}
+
+fn shinedies(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
+    let r = rng.gen::<f64>();
+    for _ in 0..20 {
+        let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
+
+        surf.save();
+        surf.scale(0.5, 0.5);
+        surf.translate(rng.gen::<f64>() * WIDTH as f64 * 2.0, rng.gen::<f64>() * HEIGHT as f64 * 2.0);
+        surf.rotate(r);
+        surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
+        let w = 300.0 + rng.gen::<f64>() * 1200.0;
+        let r = rng.gen::<f64>() * 300.0;
+        surf.arc(0.0, 0.0, r, 0.0, 3.14159 * 2.0);
+        surf.fill();
+        surf.arc(w, 0.0, r, 0.0, 3.14159 * 2.0);
+        surf.fill();
+        surf.rectangle(0.0, -r, w, r * 2.0);
+        surf.fill();
+        surf.restore();
+
+        ctx.set_source_rgba(1.0, 1.0, 1.0, 0.3);
+        ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
+    }
+}
+
+fn stars(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
+    ctx.set_source_rgba(1.0, 1.0, 1.0, 0.8);
+    for _ in 0..200 {
+        let x = rng.gen::<f64>() * WIDTH as f64;
+        let y = rng.gen::<f64>() * HEIGHT as f64;
+        let s = 4.0 + rng.gen::<f64>() * 6.0 as f64;
+        ctx.arc(x, y, s, 0.0, 3.14159 * 2.0);
+        ctx.fill();
+    }
+}
+
+fn get_sky_colors(rng: &mut rand::ThreadRng) -> (palette::Rgb, palette::Rgb) {
+    use palette::{RgbHue, Hsv, Hue};
+    let default_dark: Hsv = Hsv::from(palette::Rgb::new(0.188, 0.333, 0.51));
+    let default_light: Hsv = Hsv::from(palette::Rgb::new(0.482, 0.749, 0.839));
+    let shift = RgbHue::from_radians(rng.gen::<f32>() * 3.14159 * 2.0);
+    (default_dark.shift_hue(shift).into(), default_light.shift_hue(shift).into())
+}
+
+fn main() {
+    let surf = cairo::ImageSurface::create(
+        cairo::Format::Rgb24,
+        WIDTH,
+        HEIGHT
+    ).unwrap();
+
+    let mut rng = rand::thread_rng();
+    let ctx = cairo::Context::new(&surf);
+    let w = rng.gen::<u8>() % 3;
+    ctx.set_source_rgb(
+        if w == 0 { 0.4 } else { 0.2 },
+        if w == 1 { 0.4 } else { 0.2 },
+        if w == 2 { 0.4 } else { 0.2 },
+    );
+    ctx.paint();
+
+    let g = cairo::LinearGradient::new(
+        0.0, 0.0, 0.0, HEIGHT as f64
+    );
+    let (dark, light) = get_sky_colors(&mut rng);
+    g.add_color_stop_rgb(0.0, dark.red as f64, dark.green as f64, dark.blue as f64);
+    g.add_color_stop_rgb(1.0, light.red as f64, light.green as f64, light.blue as f64);
+    ctx.set_source(&g);
+    ctx.paint();
+
+    stars(&ctx, &mut rng);
+    for _ in 0..10 {
+        cloud(&ctx, &mut rng);
+    }
+    shinedies(&ctx, &mut rng);
+
+    {
+        let mut f = std::fs::File::create("image.png").unwrap();
+        surf.write_to_png(&mut f).unwrap();
+    }
+}