From: Bernie Innocenti Date: Sun, 18 Jun 2017 16:56:24 +0000 (-0400) Subject: Render text with a C64 font! X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=8c4dafcdc1b1edc686f02df6e9a53b10e1ca1bf0;p=mandelwow.git Render text with a C64 font! --- diff --git a/c64-font.png b/c64-font.png new file mode 100644 index 0000000..61d5e56 Binary files /dev/null and b/c64-font.png differ diff --git a/lib.rs b/lib.rs index aaf2b3c..c702671 100644 --- a/lib.rs +++ b/lib.rs @@ -2,6 +2,7 @@ extern crate cgmath; #[macro_use(uniform,program,implement_vertex)] extern crate glium; extern crate glutin; +extern crate image; extern crate libxm; extern crate sdl2; @@ -11,7 +12,17 @@ pub mod mandelwow; pub mod shaded_cube; pub mod sound; pub mod support; +pub mod text; pub use bounding_box::BoundingBox; pub use cube::Cube; pub use shaded_cube::ShadedCube; + +pub fn screenshot(display : &glium::Display) { + let image: glium::texture::RawImage2d = display.read_front_buffer(); + let image = image::ImageBuffer::from_raw(image.width, image.height, image.data.into_owned()).unwrap(); + let image = image::DynamicImage::ImageRgba8(image).flipv(); + let mut output = std::fs::File::create(&std::path::Path::new("screenshot.png")).unwrap(); + image.save(&mut output, image::ImageFormat::PNG).unwrap(); +} + diff --git a/main.rs b/main.rs index 769c16f..aee2e86 100644 --- a/main.rs +++ b/main.rs @@ -4,7 +4,6 @@ extern crate cgmath; #[macro_use(uniform)] extern crate glium; extern crate glutin; -extern crate image; use cgmath::{Euler, Matrix4, Rad, SquareMatrix, Vector3, Vector4, Zero}; use cgmath::conv::array4x4; @@ -19,14 +18,6 @@ use std::time::{Duration, Instant}; #[cfg(target_os = "emscripten")] use std::os::raw::{c_int, c_void}; -fn screenshot(display : &glium::Display) { - let image: glium::texture::RawImage2d = display.read_front_buffer(); - let image = image::ImageBuffer::from_raw(image.width, image.height, image.data.into_owned()).unwrap(); - let image = image::DynamicImage::ImageRgba8(image).flipv(); - let mut output = std::fs::File::create(&std::path::Path::new("screenshot.png")).unwrap(); - image.save(&mut output, image::ImageFormat::PNG).unwrap(); -} - fn gl_info(display : &glium::Display) { let version = *display.get_opengl_version(); let api = match version { @@ -84,6 +75,7 @@ fn main() { gl_info(&display); + let text = text::Text::new(&display); let mandelwow_program = mandelwow::program(&display); let bounding_box_program = bounding_box::solid_fill_program(&display); let shaded_program = shaded_cube::shaded_program(&display); @@ -196,6 +188,8 @@ fn main() { mandelwow::draw(&display, &mut frame, &mandelwow_program, model, &camera, &bounds, wow); + text.draw(&mut frame, &perspview); + frame.finish().unwrap(); let time_after_draw = Instant::now(); diff --git a/sound.rs b/sound.rs index d7dae92..859decf 100644 --- a/sound.rs +++ b/sound.rs @@ -29,8 +29,8 @@ fn play_xm(raw_xm: &[u8]) -> SoundPlayer { let desired_spec = AudioSpecDesired { freq: Some(SAMPLE_RATE), - channels: Some(2u8), - samples: None, + channels: Some(2), + samples: Some(4096), // 85ms }; let device = sdl_audio.open_playback(None, &desired_spec, |actual_spec| { let xm = XMContext::new(&raw_xm, actual_spec.freq as u32).unwrap(); diff --git a/text.rs b/text.rs new file mode 100644 index 0000000..c483846 --- /dev/null +++ b/text.rs @@ -0,0 +1,137 @@ +use cgmath::conv::array4x4; +use cgmath::{Matrix4, One}; +use glium; +use glium::{Surface, texture}; +use image; +use std::io::Cursor; + +#[derive(Copy, Clone)] +struct Vertex { + position: [f32; 2], + tex_coords: [f32; 2], +} +implement_vertex!(Vertex, position, tex_coords); + +pub struct Text<'a> { + tex: texture::CompressedSrgbTexture2d, + vertex_buffer: glium::VertexBuffer, + index_buffer: glium::IndexBuffer, + program: glium::Program, + params: glium::DrawParameters<'a>, + model: Matrix4, +} + +impl<'a> Text<'a> { + pub fn new(display: &glium::Display) -> Text { + let image = image::load(Cursor::new(&include_bytes!("c64-font.png")[..]), image::PNG) + .unwrap() + .to_rgba(); + let dimensions = image.dimensions(); + let image = + glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), dimensions); + let tex = glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap(); + + // building the vertex buffer, which contains all the vertices that we will draw + let vertex_buffer = { + glium::VertexBuffer::new( + display, + &[ + Vertex { + position: [-1.0, -1.0], + tex_coords: [0.0, 0.0], + }, + Vertex { + position: [-1.0, 1.0], + tex_coords: [0.0, 1.0], + }, + Vertex { + position: [1.0, 1.0], + tex_coords: [1.0, 1.0], + }, + Vertex { + position: [1.0, -1.0], + tex_coords: [1.0, 0.0], + }, + ], + ).unwrap() + }; + + let index_buffer = glium::IndexBuffer::new( + display, + glium::index::PrimitiveType::TriangleStrip, + &[1 as u16, 2, 0, 3], + ).unwrap(); + + // compiling shaders and linking them together + let program = program!(display, + 140 => { + vertex: " + #version 140 + + uniform mat4 model; + uniform mat4 perspview; + + in vec2 position; + in vec2 tex_coords; + + out vec2 v_tex_coords; + + void main() { + gl_Position = perspview * model * vec4(position, 0.0, 1.0); + // Characters are arranged in a 16x16 square. + // Texture oordinates originate in the bottom-left corner. + v_tex_coords = (tex_coords) / 16.0 + vec2(0. / 16., 15. / 16.); + } + ", + + fragment: " + #version 140 + uniform sampler2D tex; + in vec2 v_tex_coords; + out vec4 f_color; + + void main() { + f_color = texture(tex, v_tex_coords); + } + " + }).unwrap(); + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: true, + ..Default::default() + }, + multisampling: true, + ..Default::default() + }; + + Text { + model: Matrix4::one(), + tex: tex, + vertex_buffer: vertex_buffer, + index_buffer: index_buffer, + program: program, + params: params, + } + } + + pub fn draw(&self, frame: &mut glium::Frame, perspview: &[[f32; 4]; 4]) { + let uniforms = uniform! { + model: array4x4(self.model), + perspview: *perspview, + tex: self.tex.sampled() + //.minify_filter(glium::uniforms::MinifySamplerFilter::Nearest) + .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest), + }; + frame + .draw( + &self.vertex_buffer, + &self.index_buffer, + &self.program, + &uniforms, + &self.params, + ) + .unwrap(); + } +}