ggez / ggez

Rust library to create a Good Game Easily
http://ggez.rs
MIT License
4.26k stars 421 forks source link

Font rendering could be faster #24

Closed icefoxen closed 7 years ago

icefoxen commented 7 years ago

See what can be done to speed it up, since rusttype forces us to write our own renderer.

icefoxen commented 7 years ago

It would be nice to be able to slurp in a TTF file and then create a bitmap font atlas out of it. We'd lose things in it like ligatures and kerning, but that might be a fair tradeoff for most people.

icefoxen commented 7 years ago

I whipped up a cute little test program for this:

extern crate ggez;
use ggez::conf;
use ggez::game;
use ggez::{GameResult, Context};
use ggez::graphics;
use ggez::timer;
use std::time::Duration;

struct MainState {
    font: graphics::Font,
    text: graphics::Text,
    frame: u64,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let font = graphics::Font::new(ctx, "DejaVuSerif.ttf", 48)?;
        let text = graphics::Text::new(ctx, "Hello world!", &font)?;

        let s = MainState {
            font: font,
            text: text,
            frame: 0,
        };
        Ok(s)
    }
}

impl game::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        if self.frame % 100 == 0 {
            let fps = format!("FPS: {:0.2}", timer::get_fps(ctx));
            self.text = graphics::Text::new(ctx, &fps, &self.font)?;
            timer::sleep(Duration::from_secs(0));
        }
        self.frame += 1;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        ctx.renderer.clear();
        graphics::draw(ctx, &mut self.text, None, None)?;
        ctx.renderer.present();
        Ok(())
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let ctx = &mut Context::load_from_conf("helloworld", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    if let Err(e) = game::run(ctx, state) {
        println!("Error encountered: {}", e);
    } else {
        println!("Game exited cleanly.");
    }
}

If you do the update every 100 frames it works fine in debug mode but trying to make it update more often than that makes it die pretty horribly. In release mode though, it can easily render at >2000 FPS. :D

For more lulz, it might be fun to check out the rusttype GPU cache module. Might not be compatible with our graphics stuff though.

icefoxen commented 7 years ago

Benchmarks:

All benchmarks on laptop
Opt = 0: 14-15 fps
Opt = 1: 52 fps
Opt = 2: 430 fps
Opt = 3: 450 fps

Might want to just set opt-level to 1 or 2 by default in the Cargo.toml

icefoxen commented 7 years ago

This is only open for hysterical raisins now so I'm closing it.