3D Text Rendering in Haskell with FTGL
While I was writing a sort of password manager for my personal use (in Haskell) — actually, a friend of mine was doing the same in Java, so there was some competition 🙂 — I decided that just printing the password in the terminal wasn’t enough, at all. That’s why I decided to look at how it was possible to render text easily inside an OpenGL context, with possibly some depth given to each letter.
You know what ? Nearly like every time you look for some library in Haskell, you find it ! Mine was ftgl. You can, with only few lines, while in an OpenGL context, create some 3D text from given text and (TrueType) font and render it.
Since it is really easy to get working, here’s a little howto.
– be sure to have libftgl (the C version of the library), glut (often freeglut3 in distro repositories) and opengl correctly installed.
– be sure to have the Haskell OpenGL binding installed, and also GLUT (thus we can get a working 3D context in a (GLUT) window quite easily).
– get the Haskell binding of FTGL from hackage using cabal : cabal install ftgl.
Then you can try to play around the following code, that you may want to compile with ghc –make hs3dtext.hs -o hs3dtext.
module Main where import Data.List import Data.IORef import Graphics.Rendering.OpenGL import Graphics.Rendering.FTGL import Graphics.UI.GLUT import System.IO main :: IO () main = do (_, _) <- getArgsAndInitialize initialDisplayMode $= [DoubleBuffered] createWindow "3D Text Renderer" angle <- newIORef 0.0 font <- createExtrudeFont "FreeSans.ttf" setFontFaceSize font 7 7 setFontDepth font 1.0 displayCallback $= display "Haskell" angle font idleCallback $= Just (animate angle) mainLoop display text angle font = do clear [ColorBuffer] loadIdentity scale 0.04 0.05 (0.5 :: GLfloat) a > 179 of True -> angle $= -180 False -> angle $= a + 0.03 postRedisplay Nothing
Don’t forget to get FreeSans.ttf from anywhere for it to work. The depth of the letters here is 1.0, you can play with it, but it doesn’t look as well as it does like I pasted.
Here is a cool screenshot 🙂