dynamic-graph-0.1.0.0: Graphics/DynamicGraph/SimpleLine.hs
{-| Draw and update line graphs with OpenGL.
Based on: <https://en.wikibooks.org/wiki/OpenGL_Programming/Scientific_OpenGL_Tutorial_01>
You probably want to use "Graphics.DynamicGraph.TextureLine" as it is better.
-}
module Graphics.DynamicGraph.SimpleLine (
graph
) where
import Control.Monad
import Graphics.UI.GLFW as G
import Graphics.Rendering.OpenGL
import Graphics.GLUtil
import Control.Monad.Trans.Class
import Control.Monad.Trans.Either
import Foreign.Storable
import Foreign.Ptr
import Paths_dynamic_graph
{-| @(graph windowWidth windowHeight bufLen)@ creates a window
of width @windowWidth@ and height @windowHeight@ for displaying a line
graph. A function is returned for updating the line graph. It takes
a pointer to a c array of length @bufLen@ consisting of pairs of \<x,
y\> coordinates for updating the graph as this is the format that
OpenGL requires.
-}
graph :: Int -> Int -> Int -> EitherT String IO (Ptr GLfloat -> IO ())
graph width height bufLen = do
res' <- lift $ createWindow width height "" Nothing Nothing
win <- maybe (left "error creating window") return res'
lift $ do
makeContextCurrent (Just win)
--Load the shaders
vertFN <- getDataFileName "shaders/simple_line.vert"
fragFN <- getDataFileName "shaders/simple_line.frag"
vs <- loadShader VertexShader vertFN
fs <- loadShader FragmentShader fragFN
p <- linkShaderProgram [vs, fs]
--Set stuff
clearColor $= Color4 1 1 1 1
currentProgram $= Just p
ab <- genObjectName
loc <- get $ attribLocation p "coord"
let stride = fromIntegral $ sizeOf (undefined::GLfloat) * 2
vad = VertexArrayDescriptor 2 Float stride offset0
bindBuffer ArrayBuffer $= Just ab
vertexAttribArray loc $= Enabled
vertexAttribPointer loc $= (ToFloat, vad)
return $ \ptr -> do
makeContextCurrent (Just win)
clear [ColorBuffer]
bufferData ArrayBuffer $= (fromIntegral $ 2 * bufLen * sizeOf (undefined :: GLfloat), ptr, StaticDraw)
drawArrays LineStrip 0 (fromIntegral bufLen)
swapBuffers win