ff87a793417ca02328c7a7d7f6cb6a16ef8c6935
[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                 uniform int index;
74
75                 in vec2 position;
76                 in vec2 tex_coords;
77
78                 out vec2 v_tex_coords;
79
80                 void main() {
81                     gl_Position = perspview * model * vec4(position, 0.0, 1.0);
82
83                     // Characters are arranged in a 16x16 square.
84                     // Texture oordinates originate in the bottom-left corner.
85                     int xpos = index % 16;
86                     int ypos = 15 - index / 16;
87                     v_tex_coords = (tex_coords) / 16.0 + vec2(xpos / 16., ypos / 16.);
88                 }
89             ",
90
91             fragment: "
92                 #version 140
93                 uniform sampler2D tex;
94                 in vec2 v_tex_coords;
95                 out vec4 f_color;
96
97                 void main() {
98                     f_color = texture(tex, v_tex_coords);
99                 }
100             "
101         }).unwrap();
102
103         let params = glium::DrawParameters {
104             depth: glium::Depth {
105                 test: glium::draw_parameters::DepthTest::IfLess,
106                 write: true,
107                 ..Default::default()
108             },
109             multisampling: true,
110             ..Default::default()
111         };
112
113         Text {
114             model: Matrix4::one(),
115             tex: tex,
116             vertex_buffer: vertex_buffer,
117             index_buffer: index_buffer,
118             program: program,
119             params: params,
120         }
121     }
122
123     pub fn draw(&self, frame: &mut glium::Frame, perspview: &[[f32; 4]; 4]) {
124         let uniforms = uniform! {
125             model: array4x4(self.model),
126             perspview: *perspview,
127             tex: self.tex.sampled()
128                 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
129             index: 'A' as i32,
130         };
131         frame
132             .draw(
133                 &self.vertex_buffer,
134                 &self.index_buffer,
135                 &self.program,
136                 &uniforms,
137                 &self.params,
138             )
139             .unwrap();
140     }
141 }