{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module Main where import Control.Monad (forever) import Control.Monad.Except (runExceptT, withExceptT) import Control.Monad.IO.Class (MonadIO (..)) import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B8 import qualified Data.Vector.Unboxed as UV import Graphics.GL import SDL import System.FilePath (()) import Typograffiti import Typograffiti.GL vertexShader :: ByteString vertexShader = B8.pack $ unlines [ "#version 330 core" , "uniform mat4 projection;" , "uniform mat4 modelview;" , "in vec2 position;" , "in vec2 uv;" , "out vec2 fuv;" , "void main () {" , " fuv = uv;" , " gl_Position = projection * modelview * vec4(position, 0.0, 0.1);" , "}" ] fragmentShader :: ByteString fragmentShader = B8.pack $ unlines [ "#version 330 core" , "in vec2 fuv;" , "out vec4 fcolor;" , "uniform sampler2D tex;" , "void main () {" , " fcolor = texture(tex, fuv);" , "}" ] main :: IO () main = do SDL.initializeAll let openGL = defaultOpenGL { glProfile = Core Debug 3 3 } wcfg = defaultWindow { windowInitialSize = V2 640 480 , windowOpenGL = Just openGL } w <- createWindow "Typograffiti" wcfg _ <- glCreateContext w let ttfName = "assets" "Neuton-Regular.ttf" (either fail return =<<) . runExceptT $ do -- Get the atlas atlas <- withExceptT show $ allocAtlas ttfName (PixelSize 16 16) asciiChars -- Compile our shader program let position = 0 uv = 1 vert <- compileOGLShader vertexShader GL_VERTEX_SHADER frag <- compileOGLShader fragmentShader GL_FRAGMENT_SHADER prog <- compileOGLProgram [ ("position", fromIntegral position) , ("uv", fromIntegral uv) ] [vert, frag] glUseProgram prog -- Get our uniform locations projection <- getUniformLocation prog "projection" modelview <- getUniformLocation prog "modelview" tex <- getUniformLocation prog "tex" -- Generate our string geometry geom <- withExceptT show $ stringTris atlas True "Hi there" let (ps, uvs) = UV.unzip geom -- Buffer the geometry into our attributes textVao <- withVAO $ \vao -> do withBuffers 2 $ \[pbuf, uvbuf] -> do bufferGeometry position pbuf ps bufferGeometry uv uvbuf uvs return vao atlasVao <- withVAO $ \vao -> do withBuffers 2 $ \[pbuf, uvbuf] -> do let V2 w h = fromIntegral <$> atlasTextureSize atlas bufferGeometry position pbuf $ UV.fromList [ V2 0 0, V2 w 0, V2 w h , V2 0 0, V2 w h, V2 0 h ] bufferGeometry uv uvbuf $ UV.fromList [ V2 0 0, V2 1 0, V2 1 1 , V2 0 0, V2 1 1, V2 0 1 ] return vao -- Set our model view transform let mv :: M44 Float mv = mat4Translate (V3 10 100 0) mv2 :: M44 Float mv2 = mv !*! mat4Scale (V3 0.125 0.125 1) -- Forever loop, drawing stuff forever $ do _ <- pollEvents pj :: M44 Float <- orthoProjection <$> get (windowSize w) withBoundTextures [atlasTexture atlas] $ do updateUniform prog projection pj updateUniform prog modelview mv updateUniform prog tex (0 :: Int) drawVAO prog textVao GL_TRIANGLES (fromIntegral $ UV.length ps) updateUniform prog modelview mv2 drawVAO prog atlasVao GL_TRIANGLES 6 glSwapWindow w