Render text with a C64 font!
[mandelwow.git] / text.rs
1 use cgmath::conv::array4x4;
2 use cgmath::{Matrix4, One};
3 use glium;
4 use glium::{Surface, texture};
5 use image;
6 use std::io::Cursor;
7
8 #[derive(Copy, Clone)]
9 struct Vertex {
10     position: [f32; 2],
11     tex_coords: [f32; 2],
12 }
13 implement_vertex!(Vertex, position, tex_coords);
14
15 pub struct Text<'a> {
16     tex: texture::CompressedSrgbTexture2d,
17     vertex_buffer: glium::VertexBuffer<Vertex>,
18     index_buffer: glium::IndexBuffer<u16>,
19     program: glium::Program,
20     params: glium::DrawParameters<'a>,
21     model: Matrix4<f32>,
22 }
23
24 impl<'a> Text<'a> {
25     pub fn new(display: &glium::Display) -> Text {
26         let image = image::load(Cursor::new(&include_bytes!("c64-font.png")[..]), image::PNG)
27             .unwrap()
28             .to_rgba();
29         let dimensions = image.dimensions();
30         let image =
31             glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), dimensions);
32         let tex = glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
33
34         // building the vertex buffer, which contains all the vertices that we will draw
35         let vertex_buffer = {
36             glium::VertexBuffer::new(
37                 display,
38                 &[
39                     Vertex {
40                         position: [-1.0, -1.0],
41                         tex_coords: [0.0, 0.0],
42                     },
43                     Vertex {
44                         position: [-1.0, 1.0],
45                         tex_coords: [0.0, 1.0],
46                     },
47                     Vertex {
48                         position: [1.0, 1.0],
49                         tex_coords: [1.0, 1.0],
50                     },
51                     Vertex {
52                         position: [1.0, -1.0],
53                         tex_coords: [1.0, 0.0],
54                     },
55                 ],
56             ).unwrap()
57         };
58
59         let index_buffer = glium::IndexBuffer::new(
60             display,
61             glium::index::PrimitiveType::TriangleStrip,
62             &[1 as u16, 2, 0, 3],
63         ).unwrap();
64
65         // compiling shaders and linking them together
66         let program = program!(display,
67         140 => {
68             vertex: "
69                 #version 140
70
71                 uniform mat4 model;
72                 uniform mat4 perspview;
73
74                 in vec2 position;
75                 in vec2 tex_coords;
76
77                 out vec2 v_tex_coords;
78
79                 void main() {
80                     gl_Position = perspview * model * vec4(position, 0.0, 1.0);
81                     // Characters are arranged in a 16x16 square.
82                     // Texture oordinates originate in the bottom-left corner.
83                     v_tex_coords = (tex_coords) / 16.0 + vec2(0. / 16., 15. / 16.);
84                 }
85             ",
86
87             fragment: "
88                 #version 140
89                 uniform sampler2D tex;
90                 in vec2 v_tex_coords;
91                 out vec4 f_color;
92
93                 void main() {
94                     f_color = texture(tex, v_tex_coords);
95                 }
96             "
97         }).unwrap();
98
99         let params = glium::DrawParameters {
100             depth: glium::Depth {
101                 test: glium::draw_parameters::DepthTest::IfLess,
102                 write: true,
103                 ..Default::default()
104             },
105             multisampling: true,
106             ..Default::default()
107         };
108
109         Text {
110             model: Matrix4::one(),
111             tex: tex,
112             vertex_buffer: vertex_buffer,
113             index_buffer: index_buffer,
114             program: program,
115             params: params,
116         }
117     }
118
119     pub fn draw(&self, frame: &mut glium::Frame, perspview: &[[f32; 4]; 4]) {
120         let uniforms = uniform! {
121             model: array4x4(self.model),
122             perspview: *perspview,
123             tex: self.tex.sampled()
124                 //.minify_filter(glium::uniforms::MinifySamplerFilter::Nearest)
125                 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
126         };
127         frame
128             .draw(
129                 &self.vertex_buffer,
130                 &self.index_buffer,
131                 &self.program,
132                 &uniforms,
133                 &self.params,
134             )
135             .unwrap();
136     }
137 }