Skip to content

Instantly share code, notes, and snippets.

@malleusinferni
Created February 1, 2019 01:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save malleusinferni/9d2c17746991184f20208fe0cf42eaa8 to your computer and use it in GitHub Desktop.
Save malleusinferni/9d2c17746991184f20208fe0cf42eaa8 to your computer and use it in GitHub Desktop.
Cubemap generator
use cgmath::prelude::*;
use image::*;
use noise::*;
pub type Vec2d = cgmath::Vector2<f64>;
pub type Vec3d = cgmath::Vector3<f64>;
pub type Mat4d = cgmath::Matrix4<f64>;
pub struct Vertex {
pub pos: Vec3d,
}
pub type Quad = [Vertex; 4];
fn main() {
let rotations: [_; 6] = {
use cgmath::Deg;
let mx = |d| Mat4d::from_angle_x(Deg(d as f64));
let my = |d| Mat4d::from_angle_y(Deg(d as f64));
// TODO: Reorder/reorient these to match what OpenGL does
[mx(0), mx(90), mx(180), mx(270), my(90), my(270)]
};
let function = HybridMulti::new()
.set_octaves(12)
.set_frequency(3.3)
.set_lacunarity(2.13)
.set_persistence(0.9);
const SIZE: u32 = 1 << 10;
eprintln!("Sampling...");
let mut min = std::f64::INFINITY;
let mut max = -std::f64::INFINITY;
let images = rotations.iter().map(|matrix| {
image::ImageBuffer::from_fn(SIZE, SIZE, |x, y| {
let mut uv = Vec2d::new(x as f64 + 0.5, y as f64 + 0.5);
// Remap (0 .. SIZE) to (0.0 .. 1.0)
uv = uv.map(|n| n / SIZE as f64);
// Remap (0.0 .. 1.0) to (-1.0 .. 1.0)
uv = uv.map(|n| 2.0 * n - 1.0);
// Constant z
let xyz = uv.extend(1.0);
let dir: [f64; 3] = matrix.transform_vector(xyz)
.normalize()
.into();
let altitude: f64 = function.get(dir);
if altitude < min { min = altitude; }
if altitude > max { max = altitude; }
Luma([altitude])
})
}).collect::<Vec<_>>();
eprintln!("Altitude range: {} ... {}", min, max);
let normalize = |a| (a - min) / (max - min);
let ease_in_out_cubic = |mut t: f64| {
let duration = 1.0;
let delta_t = 1.0;
t /= duration / 2.0;
if t < 1.0 {
delta_t / 2.0 * t.powi(3)
} else {
t -= 2.0;
delta_t / 2.0 * (t.powi(3) + 2.0)
}
};
for (i, image) in images.into_iter().enumerate() {
let image = GrayImage::from_vec(SIZE, SIZE, {
image.into_vec().into_iter().map(|mut altitude| {
altitude = normalize(altitude);
altitude = ease_in_out_cubic(altitude);
//altitude = ease_in_out_cubic(altitude);
(altitude * 255.0) as u8
}).collect()
}).unwrap();
let filename = format!("face_{}.png", i);
eprintln!("Writing {}", &filename);
image.save(&filename).unwrap();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment