1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
use std::path::Path; use std::fs::File; use std::io::Read; use std::cell::Cell; use std::time::Duration; use glium::{self, DisplayBuild}; use rusttype; use text; use mesh; use math::Vec2; use color::Color; static VERTEX_SHADER: &'static str = r" #version 150 in vec3 position; in vec2 uv; out vec3 v_position; out vec2 v_uv; uniform mat4 u_model; uniform mat4 u_projection; void main() { gl_Position = u_projection * u_model * vec4(position, 1); v_position = position; v_uv = uv; } "; static FRAGMENT_SHADER: &'static str = r" #version 140 in vec3 v_position; in vec2 v_uv; out vec4 color; uniform vec4 u_color; uniform sampler2D u_texture; void main() { color = texture(u_texture, v_uv) * u_color; } "; fn load_bytes<P: AsRef<Path>>(path: P) -> Vec<u8> { let mut bytes = Vec::new(); File::open(path).and_then(|mut file| file.read_to_end(&mut bytes)).unwrap(); bytes } pub struct Context { pub display: glium::Display, pub color: Cell<Color>, pub background_color: Cell<Color>, pub size: Cell<Vec2>, pub mouse: Cell<Vec2>, pub dt: Cell<Duration>, pub quad: mesh::Mesh, pub white: Texture, pub default_shader: Shader, } impl Context { pub fn new(title: &str, size: (u32, u32)) -> Self { let display = glium::glutin::WindowBuilder::new() .with_title(title) .with_dimensions(size.0, size.1) .with_vsync() .build_glium() .unwrap(); let quad = new_mesh(&display, &[ mesh::Vertex::new(Vec2::new(0.0, 0.0), Vec2::new(0.0, 0.0)), mesh::Vertex::new(Vec2::new(1.0, 0.0), Vec2::new(1.0, 0.0)), mesh::Vertex::new(Vec2::new(0.0, 1.0), Vec2::new(0.0, 1.0)), mesh::Vertex::new(Vec2::new(1.0, 1.0), Vec2::new(1.0, 1.0)), ], &[0, 1, 2, 3]); let white = new_texture(&display, vec![255, 255, 255, 255], (1, 1)); let default_shader = new_shader(&display, VERTEX_SHADER, FRAGMENT_SHADER); Context { display: display, color: Cell::new((1.0, 1.0, 1.0, 1.0)), background_color: Cell::new((0.0, 0.0, 0.0, 1.0)), size: Cell::new(Vec2::new(size.0 as f32, size.1 as f32)), mouse: Cell::new(Vec2::zero()), dt: Cell::new(Default::default()), quad: quad, white: white, default_shader: default_shader, } } pub fn new_shader(&self, vertex_src: &str, fragment_src: &str) -> Shader { new_shader(&self.display, vertex_src, fragment_src) } pub fn new_mesh(&self, vertices: &[mesh::Vertex], indices: &[mesh::Index]) -> mesh::Mesh { new_mesh(&self.display, vertices, indices) } pub fn new_texture(&self, bytes: Vec<u8>, size: (u32, u32)) -> Texture { new_texture(&self.display, bytes, size) } pub fn new_text(&self, text: &str, font: &text::Font, height: f32) -> Texture { let text::Text { bytes, size } = text::Text::new(text, font, height); self.new_texture(bytes, size) } pub fn new_font<P: AsRef<Path>>(&self, path: P) -> text::Font { let bytes = load_bytes(path); rusttype::FontCollection::from_bytes(bytes).into_font().unwrap() } pub fn dt(&self) -> f32 { let dt = self.dt.get(); dt.subsec_nanos() as f32 / 1_000_000_000.0 + dt.as_secs() as f32 } pub fn size(&self) -> Vec2 { self.size.get() } } fn new_shader(display: &glium::Display, vertex_src: &str, fragment_src: &str) -> Shader { Shader::from_source(display, vertex_src, fragment_src, None).unwrap() } fn new_mesh(display: &glium::Display, vertices: &[mesh::Vertex], indices: &[mesh::Index]) -> mesh::Mesh { mesh::Mesh { vertices: glium::VertexBuffer::new(display, vertices).unwrap(), indices: glium::IndexBuffer::new(display, glium::index::PrimitiveType::TriangleStrip, indices).unwrap(), } } fn new_texture(display: &glium::Display, bytes: Vec<u8>, size: (u32, u32)) -> Texture { Texture::new(display, glium::texture::RawImage2d::from_raw_rgba(bytes, size)).unwrap() } pub type Texture = glium::texture::Texture2d; pub type Shader = glium::Program;