From 8c4dafcdc1b1edc686f02df6e9a53b10e1ca1bf0 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Sun, 18 Jun 2017 12:56:24 -0400 Subject: [PATCH] Render text with a C64 font! --- c64-font.png | Bin 0 -> 2574 bytes lib.rs | 11 +++++ main.rs | 12 ++--- sound.rs | 4 +- text.rs | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 c64-font.png create mode 100644 text.rs diff --git a/c64-font.png b/c64-font.png new file mode 100644 index 0000000000000000000000000000000000000000..61d5e562182f778ff515ce57181e1163f87088d5 GIT binary patch literal 2574 zcmV+p3i0)cP)_+m9dT_WN&teC+o8*3Qa*DgEp7*FV$t)qMI#ma#G-lM>;YplMP3<`NSssEbim!rj8Mc7qu%ZH`FtO#f3*Hz&l*o;^hOk@83B5K zFTRlU^ZBBIPi`3iuo~pfYHwixD;lANwNMmah5=@E(#$z}B#x2Z|MmBt!V&g?uqiPR z#PG-{4@Krfi^h3BU%$(`e`K1;jFVUtT?_;Y0`Sfd1a|BMKqBv0mm zyv9-*I`2e;LuuI6Q=9`ImhqvZs0Xl+P&0xjuK!0u!RWP7gODPb|Ik3zdRGi-u0Y{d zk&}^+iUU|2HG<07@3qAss}nqnHBUAAW5rR%^4Z>6g=enT{-)jcDz7B}N^y>tEN!%6 zdsGFbiIS2~mJwa1JwM0u{1vB)6a(ndJ`J29ATP3(ju=uEKF|V9-svPG&?G&(d@aCo zd8ne9(K{n8ESj-23nZ3ffF1{x__f62C7Q;1CMKBT1;LRxM-(G?;uOb70j(gB6(e8* zK^`SoKu?oRGj!|wne=ck2j7^(XS9|zhgsK0csc@twEIV|9}x`7z%SZ0lKe-;9A;hb z;py5`adoBW{UsNiDSwt1VDSq&eO-U&-WR}(hA7=(EZw4|m9Eyhw>J)f(m*XvA+`Uk z1xUP|={)pBER@f5B)Zs?IfZ2!(a4=u*T1!_7eXUxXS8m0GPAb;xj%zBv{97p{-u%Y z2?ViTrpe~As?8wguglK_|%0LV9{MDxcCRPGX0nBo3R-k4U+puIDk*yQymzTTG*sA_&N9M?> z4wW*`_b6b5XUNFz%`~pInk&3x@+Fh0#0IInUZR8rc=>2n%9odmXXNZ@d+((E46G4U ztvG7$zvBRJ-rT!`EpQmUKEk6{-5t#4I!2~W^z)I;<2~1-DOIaBZ|$NP_(WX|9NA&3 zDKIOqp9Qhe1utZzUkgv1KSR5N8DTs{qGpT;CW>e6KDJ!Ev~y@=+(9ywRxvWItlnxW zWGP=uo9dx_2`gmK*UZ|6(&ygDe|ago&WNCS7=brIbY|)I2pfpv zEo4_!dQRY-C|@?vy8HXJCo3nz0NLo@Hh?#nyR*v4MdB@4Ubkg+&a5dQs+_F)Mpc2T z>i*jvU;+ln0(|UX+!!Em{arDDC1+b*z$apWm0C)jz{vGX7EsnM<54u$Get1_7ZA)~ z{r&jZ?QK2VTY$g{;8g7?rx^g+8BaRZBST4AdfDopWYfUnkjS(=eE_!5px0&Y`T#Yc zl&%j@_3&LEARjLbsSkj-SY%}F`T#Y7o$UGm$BYP6)%klfV+G9l1ta!IP*XtG-nd;K zVAluO?T&$(Ks&)5d%Rbi-Q66&-N#WK3)&DbqT^~R;lB)Uu$h}#5$=qYt z2l%M158%DNDzWv7S9X1Xf`E_}=#pIW`Pv=}h_1i%+KvM}sCfog>Ujat^>60;>nMqy zNaB%UMLHUa1FT@Z9zN?imyiW=*13F${Ie^h^<-(I72BgK3~-am&_!ulB#yrl&1F4# zt8hKN&e5iTY@W?9fJ_6IWYs)YX3)bO2e>hZ z&uA@c4$C}wGkd)~W4*q*c25R=(XI*a3qY+ml22egH=6e^x!_Fsv%CO{U(o4Gtri|p zOa>UsN;}tRX{D=;q^&dFReMkCT1>Kt`Ar9I7tFID3RMpzNxwtoK2Uzylzs z7m120c;pm;7`!%MGKxbW9)?N^MSdJvsJQzaeSLS-2&!c1$q`9Kn~niydk|0Oj|98g z4yBCPL|d(+ck>yeS3jS>{QT$l5sGK)+C{l{WRqniR=~zd7&)^xj-K1W+{k=lM$00fL$}{2Xd;7D4-`%kHnL!hjpUH-z@(rVb)j=We z$Y-w~eV#z|^R@?=;P$=usmQ*1dklb90Ke;;Zy7~fUBHd@Ya6vMpt2-tW};(NnbqjK zMlnFej;Vcg?3=g8gTU&v^+y>1+8IykwAJVL>b~AIaIgZ|MX6|<#kyY`34HG8Ic5jC kb|C2H2C{nFEa1)CU%uZ^7iSWm{r~^~07*qoM6N<$f+Ak)S^xk5 literal 0 HcmV?d00001 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(); + } +} -- 2.25.1