wasm: Enable backtraces in browser console
[mandelwow.git] / text.rs
1 use cgmath::conv::array4x4;
2 use cgmath::{Matrix4, Vector3};
3 use glium;
4 use glium::{Display, Program, Surface, texture};
5 use std;
6
7 fn gamma<T>(x: T) -> f32
8 where
9     f32: From<T>,
10     T: Copy,
11 {
12     ((f32::from(x)) / 255.).powf(2.2)
13 }
14
15 fn srgb<T>(c: [T; 3]) -> [f32; 4]
16 where
17     f32: From<T>,
18     T: Copy,
19 {
20     [gamma(c[0]), gamma(c[1]), gamma(c[2]), 0.0]
21 }
22
23 #[cfg(feature = "image")]
24 fn c64_font() -> (u32, u32, Vec<u8>) {
25     use image;
26     let image = image::load_from_memory_with_format(
27         &include_bytes!("textures/c64-font.png")[..],
28         image::PNG,
29     ).unwrap()
30         .to_luma();
31     let (w, h) = image.dimensions();
32     (w, h, image.into_raw())
33 }
34
35 #[cfg(not(feature = "image"))]
36 fn c64_font() -> (u32, u32, Vec<u8>) {
37     let pixels = &include_bytes!("textures/c64-font.gray")[..];
38     (128, 128, Vec::from(pixels))
39 }
40
41 pub fn text_program(display: &Display) -> Program {
42     //load_program(display, "shaders/text.vert", "shaders/text.frag");
43     let vertex_shader_src = include_str!("shaders/text.vert");
44     let fragment_shader_src = include_str!("shaders/text.frag");
45     Program::from_source(display, vertex_shader_src, fragment_shader_src, None).unwrap()
46 }
47
48 #[derive(Copy, Clone)]
49 struct Vertex {
50     position: [f32; 2],
51     tex_coords: [f32; 2],
52 }
53 implement_vertex!(Vertex, position, tex_coords);
54
55 pub struct Text<'a> {
56     tex: texture::Texture2d,
57     vertex_buffer: glium::VertexBuffer<Vertex>,
58     index_buffer: glium::IndexBuffer<u16>,
59     program: glium::Program,
60     params: glium::DrawParameters<'a>,
61     pub model: Matrix4<f32>,
62     pub character: char,
63 }
64
65 impl<'a> Text<'a> {
66     pub fn new(display: &Display, character: char) -> Text {
67         let (w, h, pixels) = c64_font();
68         let image = glium::texture::RawImage2d {
69             data: std::borrow::Cow::from(pixels),
70             width: w,
71             height: h,
72             format: glium::texture::ClientFormat::U8,
73         };
74         let tex = glium::texture::Texture2d::with_format(
75             display,
76             image,
77             glium::texture::UncompressedFloatFormat::U8,
78             glium::texture::MipmapsOption::NoMipmap,
79         ).unwrap();
80
81         // building the vertex buffer, which contains all the vertices that we will draw
82         let vertex_buffer = {
83             glium::VertexBuffer::new(
84                 display,
85                 &[
86                     Vertex {
87                         position: [-0.5, -0.5],
88                         tex_coords: [0.0, 1.0],
89                     },
90                     Vertex {
91                         position: [-0.5, 0.5],
92                         tex_coords: [0.0, 0.0],
93                     },
94                     Vertex {
95                         position: [0.5, 0.5],
96                         tex_coords: [1.0, 0.0],
97                     },
98                     Vertex {
99                         position: [0.5, -0.5],
100                         tex_coords: [1.0, 1.0],
101                     },
102                 ],
103             ).unwrap()
104         };
105
106         let index_buffer = glium::IndexBuffer::new(
107             display,
108             glium::index::PrimitiveType::TriangleStrip,
109             &[1 as u16, 2, 0, 3],
110         ).unwrap();
111
112         let params = glium::DrawParameters {
113             depth: glium::Depth {
114                 test: glium::draw_parameters::DepthTest::IfLess,
115                 write: true,
116                 ..Default::default()
117             },
118             multisampling: true,
119             ..Default::default()
120         };
121
122         Text {
123             tex: tex,
124             vertex_buffer: vertex_buffer,
125             index_buffer: index_buffer,
126             program: text_program(display),
127             params: params,
128             model: Matrix4::from_translation(Vector3::unit_z() * (-1.0)),
129             character: character,
130         }
131     }
132
133     pub fn draw(&self, frame: &mut glium::Frame, perspview: &[[f32; 4]; 4]) {
134         let uniforms =
135             uniform! {
136             model: array4x4(self.model),
137             perspview: *perspview,
138             tex: self.tex.sampled()
139                 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
140             index: self.character as i32,
141             // RGB values from http://unusedino.de/ec64/technical/misc/vic656x/colors/
142             bgcolor: srgb([ 64,  50, 133u8]),  //  6 - blue
143             fgcolor: srgb([120, 106, 189u8]),  // 14 - light blue
144         };
145         frame
146             .draw(
147                 &self.vertex_buffer,
148                 &self.index_buffer,
149                 &self.program,
150                 &uniforms,
151                 &self.params,
152             )
153             .unwrap();
154     }
155 }