Created
July 7, 2016 19:11
-
-
Save malleusinferni/87fd502cf17ff5f5fdad30d9e7e72846 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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