aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs294
1 files changed, 3 insertions, 291 deletions
diff --git a/src/main.rs b/src/main.rs
index 7da9b4e9..69e4ca6c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,23 +8,10 @@ extern crate euclid;
mod list_fonts;
mod text;
+mod renderer;
-use std::ffi::CString;
-use std::mem::size_of;
-use std::ptr;
+use renderer::{Glyph, QuadRenderer};
-use euclid::{Rect, Size2D, Point2D};
-
-use libc::c_void;
-
-use gl::types::*;
-
-use cgmath::Matrix;
-
-use text::RasterizedGlyph;
-
-static TEXT_SHADER_V: &'static str = include_str!("../res/text.v.glsl");
-static TEXT_SHADER_F: &'static str = include_str!("../res/text.f.glsl");
fn main() {
let window = glutin::Window::new().unwrap();
@@ -39,6 +26,7 @@ fn main() {
}
let rasterizer = text::Rasterizer::new();
+
let glyph_R = Glyph::new(&rasterizer.get_glyph(180., 'R'));
let glyph_u = Glyph::new(&rasterizer.get_glyph(180., 'u'));
let glyph_s = Glyph::new(&rasterizer.get_glyph(180., 's'));
@@ -72,279 +60,3 @@ fn main() {
}
}
-struct QuadRenderer {
- program: ShaderProgram,
- vao: GLuint,
- vbo: GLuint,
- ebo: GLuint,
-}
-
-impl QuadRenderer {
- // TODO should probably hand this a transform instead of width/height
- pub fn new(width: u32, height: u32) -> QuadRenderer {
- let program = ShaderProgram::new(width, height);
-
- let mut vao: GLuint = 0;
- let mut vbo: GLuint = 0;
- let mut ebo: GLuint = 0;
-
- unsafe {
- gl::GenVertexArrays(1, &mut vao);
- gl::GenBuffers(1, &mut vbo);
- gl::GenBuffers(1, &mut ebo);
- gl::BindVertexArray(vao);
-
- gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
- gl::BufferData(
- gl::ARRAY_BUFFER,
- (size_of::<f32>() * 4 * 4) as GLsizeiptr,
- ptr::null(),
- gl::DYNAMIC_DRAW
- );
-
- let indices: [u32; 6] = [0, 1, 3,
- 1, 2, 3];
-
- gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
- gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
- 6 * size_of::<u32>() as isize,
- indices.as_ptr() as *const _,
- gl::STATIC_DRAW);
-
- gl::EnableVertexAttribArray(0);
- gl::VertexAttribPointer(0, 4, gl::FLOAT, gl::FALSE, 4 * size_of::<f32>() as i32,
- ptr::null());
-
- gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);
- gl::BindBuffer(gl::ARRAY_BUFFER, 0);
- gl::BindVertexArray(0);
- }
-
- QuadRenderer {
- program: program,
- vao: vao,
- vbo: vbo,
- ebo: ebo,
- }
- }
-
- pub fn render(&self, glyph: &Glyph, x: f32, y: f32) {
- self.program.activate();
- unsafe {
- // set color
- gl::Uniform3f(self.program.u_color, 1., 1., 0.5);
- }
-
- let rect = get_rect(glyph, x, y);
-
- // top right of character
- let vertices: [[f32; 4]; 4] = [
- [rect.max_x(), rect.max_y(), 1., 0.], // top-right
- [rect.max_x(), rect.min_y(), 1., 1.], // bottom-right
- [rect.min_x(), rect.min_y(), 0., 1.], // bottom-left
- [rect.min_x(), rect.max_y(), 0., 0.], // top-left
- ];
-
- unsafe {
- bind_mask_texture(glyph.tex_id);
- gl::BindVertexArray(self.vao);
-
- gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
- gl::BufferSubData(
- gl::ARRAY_BUFFER,
- 0,
- (4 * 4 * size_of::<f32>()) as isize,
- vertices.as_ptr() as *const _
- );
- gl::BindBuffer(gl::ARRAY_BUFFER, 0);
- gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
-
- gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
- gl::BindVertexArray(0);
- gl::BindTexture(gl::TEXTURE_2D, 0);
- }
-
- self.program.deactivate();
- }
-}
-
-fn get_rect(glyph: &Glyph, x: f32, y: f32) -> Rect<f32> {
- Rect::new(
- Point2D::new(x, y),
- Size2D::new(glyph.width as f32, glyph.height as f32)
- )
-}
-
-fn bind_mask_texture(id: u32) {
- unsafe {
- gl::ActiveTexture(gl::TEXTURE0);
- gl::BindTexture(gl::TEXTURE_2D, id);
- }
-}
-
-pub struct ShaderProgram {
- id: GLuint,
- /// projection matrix uniform
- u_projection: GLint,
- /// color uniform
- u_color: GLint,
-}
-
-impl ShaderProgram {
- pub fn activate(&self) {
- unsafe {
- gl::UseProgram(self.id);
- }
- }
-
- pub fn deactivate(&self) {
- unsafe {
- gl::UseProgram(0);
- }
- }
-
- pub fn new(width: u32, height: u32) -> ShaderProgram {
- let vertex_shader = ShaderProgram::create_vertex_shader();
- let fragment_shader = ShaderProgram::create_fragment_shader();
- let program = ShaderProgram::create_program(vertex_shader, fragment_shader);
-
- unsafe {
- gl::DeleteShader(vertex_shader);
- gl::DeleteShader(fragment_shader);
- }
-
- // get uniform locations
- let projection_str = CString::new("projection").unwrap();
- let color_str = CString::new("textColor").unwrap();
-
- let (projection, color) = unsafe {
- (
- gl::GetUniformLocation(program, projection_str.as_ptr()),
- gl::GetUniformLocation(program, color_str.as_ptr())
- )
- };
-
- assert!(projection != gl::INVALID_VALUE as i32);
- assert!(projection != gl::INVALID_OPERATION as i32);
- assert!(color != gl::INVALID_VALUE as i32);
- assert!(color != gl::INVALID_OPERATION as i32);
-
- let shader = ShaderProgram {
- id: program,
- u_projection: projection,
- u_color: color,
- };
-
- // set projection uniform
- let ortho = cgmath::ortho(0., width as f32, 0., height as f32, -1., 1.);
- let projection: [[f32; 4]; 4] = ortho.into();
-
- println!("width: {}, height: {}", width, height);
-
- shader.activate();
- unsafe {
- gl::UniformMatrix4fv(shader.u_projection,
- 1, gl::FALSE, projection.as_ptr() as *const _);
- }
- shader.deactivate();
-
- shader
- }
-
- fn create_program(vertex: GLuint, fragment: GLuint) -> GLuint {
-
- unsafe {
- let program = gl::CreateProgram();
- gl::AttachShader(program, vertex);
- gl::AttachShader(program, fragment);
- gl::LinkProgram(program);
-
- let mut success: GLint = 0;
- gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);
-
- if success != (gl::TRUE as GLint) {
- panic!("failed to link shader program");
- }
- program
- }
- }
-
- fn create_fragment_shader() -> GLuint {
- unsafe {
- let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
- let fragment_source = CString::new(TEXT_SHADER_F).unwrap();
- gl::ShaderSource(fragment_shader, 1, &fragment_source.as_ptr(), ptr::null());
- gl::CompileShader(fragment_shader);
-
- let mut success: GLint = 0;
- gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
-
- if success != (gl::TRUE as GLint) {
- panic!("failed to compiler fragment shader");
- }
- fragment_shader
- }
- }
-
- fn create_vertex_shader() -> GLuint {
- unsafe {
- let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
- let vertex_source = CString::new(TEXT_SHADER_V).unwrap();
- gl::ShaderSource(vertex_shader, 1, &vertex_source.as_ptr(), ptr::null());
- gl::CompileShader(vertex_shader);
-
- let mut success: GLint = 0;
- gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
-
- if success != (gl::TRUE as GLint) {
- panic!("failed to compiler vertex shader");
- }
- vertex_shader
- }
- }
-}
-
-struct Glyph {
- tex_id: GLuint,
- top: i32,
- left: i32,
- width: i32,
- height: i32,
-}
-
-impl Glyph {
- pub fn new(rasterized: &RasterizedGlyph) -> Glyph {
- let mut id: GLuint = 0;
- unsafe {
- gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
- gl::GenTextures(1, &mut id);
- gl::BindTexture(gl::TEXTURE_2D, id);
- gl::TexImage2D(
- gl::TEXTURE_2D,
- 0,
- gl::RED as i32,
- rasterized.width as i32,
- rasterized.height as i32,
- 0,
- gl::RED,
- gl::UNSIGNED_BYTE,
- rasterized.buf.as_ptr() as *const _
- );
-
- gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
- gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
- gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
- gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
-
- gl::BindTexture(gl::TEXTURE_2D, 0);
- }
-
- Glyph {
- tex_id: id,
- top: rasterized.top as i32,
- width: rasterized.width as i32,
- height: rasterized.height as i32,
- left: rasterized.left as i32,
- }
- }
-}