Draw Text with OpenGL in Rust

Posted by yhuang
Public (Editable by Users)

This code snippet draws text by loading a font via rusttype and computes the vertex data needed to draw a string and feeds that to an OpenGL shader. Supports arbitrary font sizes and colors. This is a nice way to draw text with raw opengl without a framework.

Rust
Edit
use glow::*;
use text;

fn main() {
  // Setup window gl context ...
  // possibly_current_ctx is something that you can create from glutin.
  let gl = glow::Context::from_loader_function(|s| {
      possibly_current_ctx.get_proc_address(s) as *const _
  });
  
  let mut gfx_ctx = Graphics::create(gl);
  gfx_ctx.init_font();
  
  // Inside some render loop.
  gfx_ctx.current_font_size = 18;
  gfx_ctx.current_fill_color = graphics::Color::create_rgba(r, g, b, a);
  gfx_ctx.fill_text(&text, x, y);
}

pub struct Graphics<T: HasContext> {
  pub gl: T,
  pub current_fill_color: Color,
  pub current_font_size: f32,
}

impl<T: HasContext> Graphics<T> {
  pub fn create(gl: T) -> Self {
    unsafe {
      // Initialize the shader program.
      // Unsafe since we're using glow.
      // Not shown here are also buffer initializations.
      let text_program = Self::create_program(&gl, text::VERT_300_SRC, text::FRAG_300_SRC);
      Graphics::<T> {
        gl: gl,
        simple_program: gl_simple_program,
        current_fill_color: Color::create_rgba(0.0, 0.0, 0.0, 0.0),
        current_font_size: 20.0,
        projection_transform_matrix: projection_transform_matrix,
        text_program: gl_text_program,
        font: None,
      }
    }
  }
  pub fn init_font(&mut self) {
    // Load default font.
    let font = text::FontTexture::new(self, &include_bytes!("Montserrat-Regular.ttf")[..],
      70, text::ascii_character_list());
    self.font = Some(font);
  }
  pub fn fill_text(&mut self, text: &str, x: f32, y: f32) {
    pub current_fill_color: Color,
  	pub current_font_size: f32,
    let font = self.font.as_ref().unwrap();
    text::fill_text(self, &font, text, x, y, &self.current_fill_color, self.current_font_size);
  }
}