Skip to content

Instantly share code, notes, and snippets.

@malleusinferni
Created July 7, 2016 19:11
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/87fd502cf17ff5f5fdad30d9e7e72846 to your computer and use it in GitHub Desktop.
Save malleusinferni/87fd502cf17ff5f5fdad30d9e7e72846 to your computer and use it in GitHub Desktop.
extern crate sdl2;
extern crate sdl2_image;
use sdl2::rect::Rect;
use sdl2_image::SaveSurface;
fn main() {
let _sdl = sdl2::init().unwrap();
let _img_ctx = { use sdl2_image::*; init(INIT_PNG) }.unwrap();
let size_variations = 3;
let color_variations = 12;
let radius = 3;
let tile_size = radius * 2;
let width = tile_size * size_variations;
let height = tile_size * color_variations;
let mut surf = {
use sdl2::surface::Surface;
use sdl2::pixels::PixelFormatEnum::RGBA8888;
Surface::new(width, height, RGBA8888).unwrap()
};
let clear_color = sdl2::pixels::Color::RGBA(0, 0, 0, 0);
surf.fill_rect(Some(Rect::new(0, 0, width, height)), clear_color)
.unwrap();
let colors = ColorTemp::range(44, 82, color_variations as usize);
let sizes = 0 .. size_variations;
for (y, color) in colors.into_iter().enumerate() {
let rgb = color.to_rgb();
for (x, size) in sizes.clone().enumerate() {
let (x, y) = (x as u32 * tile_size, y as u32 * tile_size);
let shape = StarShape::for_tile(x as i32, y as i32, size);
for &rect in &shape {
match rect {
r@Some(_) => surf.fill_rect(r, rgb).unwrap(),
None => (),
}
}
}
}
use sdl2_image::SaveSurface;
use std::path::Path;
surf.save(Path::new("stars.png")).unwrap();
}
#[derive(Copy, Clone)]
struct ColorTemp(f32);
impl ColorTemp {
fn range(low: u32, high: u32, steps: usize) -> Vec<ColorTemp> {
let step_size = (high - low) as f32 / steps as f32;
let mut result = Vec::with_capacity(steps);
for i in 0 .. steps {
// TODO: Non-linear interpolation?
result.push(ColorTemp(low as f32 + step_size * i as f32));
}
result
}
/// Helland-Bartlett simplified color temperature conversion
fn to_rgb(self) -> sdl2::pixels::Color {
fn abcx(x: f32, a: f32, b: f32, c: f32) -> f32 {
a + b * x + c * x.ln()
}
let r = if self.0 < 66.0 {
255.0
} else {
abcx(self.0 - 55.0, 351.9769, 0.1142, -40.2537)
}.clamp(0.0, 255.0);
let g = if self.0 < 66.0 {
abcx(self.0 - 2.0, -155.2549, -0.446, 104.4922)
} else {
abcx(self.0 - 50.0, 325.4494, 0.0794, -28.0853)
}.clamp(0.0, 255.0);
let b = {
abcx(self.0 - 10.0, -254.7694, 0.8274, 115.6799)
}.clamp(0.0, 255.0);
sdl2::pixels::Color::RGB(r as u8, g as u8, b as u8)
}
}
trait Clamp { fn clamp(self, low: Self, high: Self) -> Self; }
impl Clamp for f32 {
fn clamp(self, low: Self, high: Self) -> Self {
if self < low { return low; }
if self > high { return high; }
self
}
}
type StarShape = [Option<Rect>; 3];
trait StarLike { fn for_tile(x: i32, y: i32, size: u32) -> Self; }
impl StarLike for StarShape {
fn for_tile(x: i32, y: i32, size: u32) -> Self {
// Gee, this could probably be more elegant
match size {
0 => {
let center = Rect::new(x + 2, y + 2, 2, 2);
[Some(center), None, None]
}
1 => {
let vertical = Rect::new(x + 2, y + 1, 1, 3);
let horizontal = Rect::new(x + 1, y + 2, 3, 1);
[Some(vertical), Some(horizontal), None]
}
2 => {
let vertical = Rect::new(x + 2, y + 0, 1, 5);
let horizontal = Rect::new(x + 0, y + 2, 5, 1);
[Some(vertical), Some(horizontal), None]
}
3 => {
let vertical = Rect::new(x + 2, y + 0, 1, 5);
let horizontal = Rect::new(x + 0, y + 2, 5, 1);
let center = Rect::new(x + 1, y + 1, 3, 3);
[Some(vertical), Some(horizontal), Some(center)]
}
_ => [None, None, None]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment