packages feed

GLUtil 0.3.0 → 0.6.1

raw patch · 10 files changed

+495/−48 lines, 10 filesdep +JuicyPixelsdep +containersdep +linearPVP ok

version bump matches the API change (PVP)

Dependencies added: JuicyPixels, containers, linear

API changes (from Hackage documentation)

- Graphics.GLUtil.Textures: class Storable a => HasGLType a
- Graphics.GLUtil.Textures: glType :: HasGLType a => a -> DataType
- Graphics.GLUtil.Textures: instance HasGLType Float
- Graphics.GLUtil.Textures: instance HasGLType Int
- Graphics.GLUtil.Textures: instance HasGLType Word16
- Graphics.GLUtil.Textures: instance HasGLType Word8
- Graphics.GLUtil.VertexArrayObjects: VertexArrayObject :: GLuint -> VertexArrayObject
- Graphics.GLUtil.VertexArrayObjects: bindVertexArray :: Maybe VertexArrayObject -> IO ()
- Graphics.GLUtil.VertexArrayObjects: deleteVAO :: VertexArrayObject -> IO ()
- Graphics.GLUtil.VertexArrayObjects: newtype VertexArrayObject
+ Graphics.GLUtil: readTexture :: FilePath -> IO (Either String TextureObject)
+ Graphics.GLUtil.JuicyTextures: readTexInfo :: FilePath -> (forall a. IsPixelData a => TexInfo a -> IO b) -> IO (Either String b)
+ Graphics.GLUtil.JuicyTextures: readTexture :: FilePath -> IO (Either String TextureObject)
+ Graphics.GLUtil.Linear: asUniform :: AsUniform t => t -> UniformLocation -> IO ()
+ Graphics.GLUtil.Linear: class AsUniform t
+ Graphics.GLUtil.Linear: instance AsUniform (M22 GLfloat)
+ Graphics.GLUtil.Linear: instance AsUniform (M33 GLfloat)
+ Graphics.GLUtil.Linear: instance AsUniform (M44 GLfloat)
+ Graphics.GLUtil.Linear: instance AsUniform (V2 GLfloat)
+ Graphics.GLUtil.Linear: instance AsUniform (V2 GLint)
+ Graphics.GLUtil.Linear: instance AsUniform (V2 GLuint)
+ Graphics.GLUtil.Linear: instance AsUniform (V3 GLfloat)
+ Graphics.GLUtil.Linear: instance AsUniform (V3 GLint)
+ Graphics.GLUtil.Linear: instance AsUniform (V3 GLuint)
+ Graphics.GLUtil.Linear: instance AsUniform (V4 GLfloat)
+ Graphics.GLUtil.Linear: instance AsUniform (V4 GLint)
+ Graphics.GLUtil.Linear: instance AsUniform (V4 GLuint)
+ Graphics.GLUtil.Linear: instance AsUniform GLfloat
+ Graphics.GLUtil.Linear: instance AsUniform GLint
+ Graphics.GLUtil.Linear: instance AsUniform GLuint
+ Graphics.GLUtil.Linear: instance AsUniform [V2 GLfloat]
+ Graphics.GLUtil.Linear: instance AsUniform [V2 GLint]
+ Graphics.GLUtil.Linear: instance AsUniform [V2 GLuint]
+ Graphics.GLUtil.Linear: instance AsUniform [V3 GLfloat]
+ Graphics.GLUtil.Linear: instance AsUniform [V3 GLint]
+ Graphics.GLUtil.Linear: instance AsUniform [V3 GLuint]
+ Graphics.GLUtil.Linear: instance AsUniform [V4 GLfloat]
+ Graphics.GLUtil.Linear: instance AsUniform [V4 GLint]
+ Graphics.GLUtil.Linear: instance AsUniform [V4 GLuint]
+ Graphics.GLUtil.ShaderProgram: ShaderProgram :: Map String (AttribLocation, VariableType) -> Map String (UniformLocation, VariableType) -> Program -> ShaderProgram
+ Graphics.GLUtil.ShaderProgram: attribs :: ShaderProgram -> Map String (AttribLocation, VariableType)
+ Graphics.GLUtil.ShaderProgram: data ShaderProgram
+ Graphics.GLUtil.ShaderProgram: enableAttrib :: ShaderProgram -> String -> IO ()
+ Graphics.GLUtil.ShaderProgram: getAttrib :: ShaderProgram -> String -> AttribLocation
+ Graphics.GLUtil.ShaderProgram: getUniform :: ShaderProgram -> String -> UniformLocation
+ Graphics.GLUtil.ShaderProgram: loadGeoProgram :: FilePath -> FilePath -> FilePath -> IO ShaderProgram
+ Graphics.GLUtil.ShaderProgram: loadGeoProgramWith :: FilePath -> FilePath -> FilePath -> (Program -> IO ()) -> IO ShaderProgram
+ Graphics.GLUtil.ShaderProgram: loadShaderExplicit :: FilePath -> FilePath -> ([String], [String]) -> IO ShaderProgram
+ Graphics.GLUtil.ShaderProgram: loadShaderProgram :: FilePath -> FilePath -> IO ShaderProgram
+ Graphics.GLUtil.ShaderProgram: loadShaderProgramWith :: FilePath -> FilePath -> (Program -> IO ()) -> IO ShaderProgram
+ Graphics.GLUtil.ShaderProgram: program :: ShaderProgram -> Program
+ Graphics.GLUtil.ShaderProgram: setAttrib :: ShaderProgram -> String -> IntegerHandling -> VertexArrayDescriptor a -> IO ()
+ Graphics.GLUtil.ShaderProgram: setUniform :: Uniform a => ShaderProgram -> String -> a -> IO ()
+ Graphics.GLUtil.ShaderProgram: uniforms :: ShaderProgram -> Map String (UniformLocation, VariableType)
+ Graphics.GLUtil.Shaders: instance Eq GeometryShader
+ Graphics.GLUtil.Shaders: instance ObjectName GeometryShader
+ Graphics.GLUtil.Shaders: instance Ord GeometryShader
+ Graphics.GLUtil.Shaders: instance Show GeometryShader
+ Graphics.GLUtil.Shaders: linkGeoProgram :: [VertexShader] -> [GeometryShader] -> [FragmentShader] -> IO Program
+ Graphics.GLUtil.Shaders: linkGeoProgramWith :: [VertexShader] -> [GeometryShader] -> [FragmentShader] -> (Program -> IO ()) -> IO Program
+ Graphics.GLUtil.Shaders: linkShaderProgramWith :: [VertexShader] -> [FragmentShader] -> (Program -> IO ()) -> IO Program
+ Graphics.GLUtil.Shaders: loadGeoShader :: FilePath -> IO GeometryShader
+ Graphics.GLUtil.Textures: generateMipmap' :: TextureTarget -> IO ()
+ Graphics.GLUtil.Textures: texture2DWrap :: StateVar (Repetition, Clamping)
+ Graphics.GLUtil.Textures: texture3DWrap :: StateVar (Repetition, Clamping)
+ Graphics.GLUtil.Textures: withTextures :: TextureTarget -> [TextureObject] -> IO a -> IO a
+ Graphics.GLUtil.Textures: withTextures2D :: [TextureObject] -> IO a -> IO a
+ Graphics.GLUtil.TypeMapping: class Storable a => HasGLType a
+ Graphics.GLUtil.TypeMapping: class HasVariableType a
+ Graphics.GLUtil.TypeMapping: glType :: HasGLType a => a -> DataType
+ Graphics.GLUtil.TypeMapping: instance HasGLType Float
+ Graphics.GLUtil.TypeMapping: instance HasGLType GLfloat
+ Graphics.GLUtil.TypeMapping: instance HasGLType GLint
+ Graphics.GLUtil.TypeMapping: instance HasGLType GLuint
+ Graphics.GLUtil.TypeMapping: instance HasGLType Int
+ Graphics.GLUtil.TypeMapping: instance HasGLType Word16
+ Graphics.GLUtil.TypeMapping: instance HasGLType Word32
+ Graphics.GLUtil.TypeMapping: instance HasGLType Word8
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (M22 GLfloat)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (M33 GLfloat)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (M44 GLfloat)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V2 GLfloat)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V2 GLint)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V2 GLuint)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V2 Int32)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V2 Word32)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V3 GLfloat)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V3 GLint)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V3 GLuint)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V3 Int32)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V3 Word32)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V4 GLfloat)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V4 GLint)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V4 GLuint)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V4 Int32)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType (V4 Word32)
+ Graphics.GLUtil.TypeMapping: instance HasVariableType Float
+ Graphics.GLUtil.TypeMapping: instance HasVariableType GLfloat
+ Graphics.GLUtil.TypeMapping: instance HasVariableType GLint
+ Graphics.GLUtil.TypeMapping: instance HasVariableType GLuint
+ Graphics.GLUtil.TypeMapping: instance HasVariableType Int32
+ Graphics.GLUtil.TypeMapping: instance HasVariableType Word32
+ Graphics.GLUtil.TypeMapping: variableDataType :: VariableType -> DataType
+ Graphics.GLUtil.TypeMapping: variableType :: HasVariableType a => a -> VariableType
+ Graphics.GLUtil.VertexArrayObjects: withVAO :: VertexArrayObject -> IO r -> IO r
+ Graphics.GLUtil.Viewport: withViewport :: Position -> Size -> IO a -> IO a
- Graphics.GLUtil.Textures: loadTexture :: IsPixelData a => TexInfo a -> IO (TextureObject)
+ Graphics.GLUtil.Textures: loadTexture :: IsPixelData a => TexInfo a -> IO TextureObject

Files

GLUtil.cabal view
@@ -1,5 +1,5 @@ Name:                GLUtil-Version:             0.3.0+Version:             0.6.1 Synopsis:            Miscellaneous OpenGL utilities. License:             BSD3 License-file:        LICENSE@@ -23,22 +23,30 @@ Library   Exposed-modules:     Graphics.GLUtil,                        Graphics.GLUtil.GLError,-                       Graphics.GLUtil.Shaders, -                       Graphics.GLUtil.BufferObjects, +                       Graphics.GLUtil.Shaders,+                       Graphics.GLUtil.ShaderProgram,+                       Graphics.GLUtil.BufferObjects,                        Graphics.GLUtil.Textures,-                       Graphics.GLUtil.VertexArrayObjects+                       Graphics.GLUtil.JuicyTextures,+                       Graphics.GLUtil.VertexArrayObjects,+                       Graphics.GLUtil.Linear,+                       Graphics.GLUtil.TypeMapping,+                       Graphics.GLUtil.Viewport      Build-depends:       base >= 4.2 && < 5,                        bytestring,                        array,+                       containers,+                       linear,+                       JuicyPixels >= 3,                        OpenGLRaw >= 1.1,                        OpenGL >= 2.4,                        vector >= 0.7-+  Build-tools:         cpphs   GHC-Options:         -Odph -Wall   HS-Source-Dirs:      src    source-repository this   type:     git+  tag:      0.6.1   location: http://github.com/acowley/GLUtil.git-  tag:      0.2.2
src/Graphics/GLUtil.hs view
@@ -3,11 +3,22 @@ module Graphics.GLUtil (module Graphics.GLUtil.BufferObjects,                         module Graphics.GLUtil.Shaders,                         module Graphics.GLUtil.Textures,+                        readTexture,                         module Graphics.GLUtil.GLError,-                        module Graphics.GLUtil.VertexArrayObjects) where+                        module Graphics.GLUtil.VertexArrayObjects,+                        module Graphics.GLUtil.ShaderProgram,+                        module Graphics.GLUtil.TypeMapping,+                        module Graphics.GLUtil.Linear,+                        module Graphics.GLUtil.Viewport) where  import Graphics.GLUtil.BufferObjects import Graphics.GLUtil.Shaders import Graphics.GLUtil.Textures import Graphics.GLUtil.GLError import Graphics.GLUtil.VertexArrayObjects+import Graphics.GLUtil.ShaderProgram+import Graphics.GLUtil.TypeMapping+import Graphics.GLUtil.Viewport++import Graphics.GLUtil.JuicyTextures (readTexture)+import Graphics.GLUtil.Linear
+ src/Graphics/GLUtil/JuicyTextures.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE RankNTypes #-}+module Graphics.GLUtil.JuicyTextures where+import Codec.Picture (readImage, DynamicImage(..), Image(..))+import Control.Applicative ((<$>))+import Graphics.GLUtil.Textures+import Graphics.Rendering.OpenGL (TextureObject)++readTexInfo :: FilePath+            -> (forall a. IsPixelData a => TexInfo a -> IO b)+            -> IO (Either String b)+readTexInfo f k = readImage f >>= either (return . Left) aux+  where aux (ImageY8 (Image w h p)) = Right <$> k (texInfo w h TexMono p)+        aux (ImageYF (Image w h p)) = Right <$> k (texInfo w h TexMono p)+        aux (ImageYA8 _) = return $ Left "YA format not supported"+        aux (ImageRGB8 (Image w h p)) = Right <$> k (texInfo w h TexRGB p)+        aux (ImageRGBF (Image w h p)) = Right <$> k (texInfo w h TexRGB p)+        aux (ImageRGBA8 (Image w h p)) = Right <$> k (texInfo w h TexRGBA p)+        aux (ImageYCbCr8 _) = return $ Left "YCbCr format not supported"++readTexture :: FilePath -> IO (Either String TextureObject)+readTexture f = readTexInfo f loadTexture
+ src/Graphics/GLUtil/Linear.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE FlexibleInstances, FlexibleContexts, ScopedTypeVariables #-}+{-# OPTIONS_GHC -cpp -pgmPcpphs -optP--cpp -optP--hashes #-}+-- |Support for writing "Linear" types to uniform locations in+-- shader programs.+module Graphics.GLUtil.Linear (AsUniform(..)) where+import Foreign.Marshal.Array (withArray)+import Foreign.Marshal.Utils (with)+import Foreign.Ptr (Ptr, castPtr)+import Foreign.Storable (Storable)+import Graphics.Rendering.OpenGL (UniformLocation)+import Graphics.Rendering.OpenGL.Raw.Core31+import Linear+import Unsafe.Coerce (unsafeCoerce)++-- | A type class for things we can write to uniform locations in+-- shader programs.+class AsUniform t where+  asUniform :: t -> UniformLocation -> IO ()++getUL :: UniformLocation -> GLint+getUL = unsafeCoerce++castVecComponent :: Ptr (t a) -> Ptr a+castVecComponent = castPtr++castMatComponent :: Ptr (t (f a)) -> Ptr a+castMatComponent = castPtr++instance AsUniform GLint where+  x `asUniform` loc = with x $ glUniform1iv (getUL loc) 1++instance AsUniform GLuint where+  x `asUniform` loc = with x $ glUniform1uiv (getUL loc) 1++instance AsUniform GLfloat where+  x `asUniform` loc = with x $ glUniform1fv (getUL loc) 1++#define UNIFORMVEC_T(d,ht,glt) instance AsUniform (V ## d ht) where {v `asUniform` loc = with v $ glUniform##d##glt##v (getUL loc) 1 . castVecComponent}++#define UNIFORMVEC(d) UNIFORMVEC_T(d,GLint,i); UNIFORMVEC_T(d,GLuint,ui); UNIFORMVEC_T(d,GLfloat,f)++UNIFORMVEC(2)+UNIFORMVEC(3)+UNIFORMVEC(4)++instance AsUniform (M22 GLfloat) where+  m `asUniform` loc = with m+                    $ glUniformMatrix2fv (getUL loc) 1 1 . castMatComponent++instance AsUniform (M33 GLfloat) where+  m `asUniform` loc = with m+                    $ glUniformMatrix3fv (getUL loc) 1 1 . castMatComponent++instance AsUniform (M44 GLfloat) where+  m `asUniform` loc = with m+                    $ glUniformMatrix4fv (getUL loc) 1 1 . castMatComponent++-- Support lists of vectors as uniform arrays of vectors.++#define UNIFORMARRAY_T(d,ht,glt) instance AsUniform [V##d ht] where {l `asUniform` loc = withArray l $ glUniform##d##glt##v (getUL loc) (fromIntegral $ length l) . castVecComponent}++#define UNIFORMARRAY(d) UNIFORMARRAY_T(d,GLint,i); UNIFORMARRAY_T(d,GLuint,ui); UNIFORMARRAY_T(d,GLfloat,f)++UNIFORMARRAY(2)+UNIFORMARRAY(3)+UNIFORMARRAY(4)
+ src/Graphics/GLUtil/ShaderProgram.hs view
@@ -0,0 +1,142 @@+-- |Convenience interface for working with GLSL shader+-- programs. Provides an interface for setting attributes and+-- uniforms.+module Graphics.GLUtil.ShaderProgram (ShaderProgram(..), loadShaderProgram, +                                      loadShaderProgramWith,+                                      loadGeoProgram,+                                      loadGeoProgramWith,+                                      loadShaderExplicit, +                                      getAttrib, enableAttrib, setAttrib, +                                      setUniform, getUniform) where+import Prelude hiding (lookup)+import Control.Applicative ((<$>), (<*>))+import Data.List (find, findIndex)+import Data.Map.Strict (Map, fromList, lookup)+import Data.Maybe (isJust, isNothing, catMaybes)+import Graphics.GLUtil.Shaders (loadShader, loadGeoShader, linkShaderProgram,+                                linkGeoProgramWith)+import Graphics.GLUtil.GLError (throwError)+import Graphics.Rendering.OpenGL++-- |Representation of a GLSL shader program that has been compiled and+-- linked.+data ShaderProgram = +  ShaderProgram { attribs  :: Map String (AttribLocation, VariableType)+                , uniforms :: Map String (UniformLocation, VariableType)+                , program  :: Program }++-- |Load a 'ShaderProgram' from a vertex and fragment shader source+-- files. the third argument is a tuple of the attribute names and+-- uniform names that will be set in this program. If all attributes+-- and uniforms are desired, consider using 'loadShaderProgram'.+loadShaderExplicit :: FilePath -> FilePath -> ([String],[String])+                   -> IO ShaderProgram+loadShaderExplicit vsrc fsrc names =+  do vs <- loadShader vsrc+     fs <- loadShader fsrc+     p <- linkShaderProgram [vs] [fs]+     throwError+     (attrs,unis) <- getExplicits p names+     return $ ShaderProgram (fromList attrs) (fromList unis) p++-- |Load a 'ShaderProgram' from a vertex shader source file and a+-- fragment shader source file. The active attributes and uniforms in+-- the linked program are recorded in the 'ShaderProgram'.+loadShaderProgram :: FilePath -> FilePath -> IO ShaderProgram+loadShaderProgram vsrc fsrc = loadShaderProgramWith vsrc fsrc (\_ -> return ())++-- |Load a 'ShaderProgram' from a vertex shader source file, a+-- geometry shader source file, and a fragment shader source file. The+-- active attributes and uniforms in the linked program are recorded+-- in the 'ShaderProgram'.+loadGeoProgram :: FilePath -> FilePath -> FilePath -> IO ShaderProgram+loadGeoProgram vsrc gsrc fsrc = +  loadGeoProgramWith vsrc gsrc fsrc (\_ -> return ())++-- |Load a 'ShaderProgram' from a vertex shader source file and a+-- fragment shader source file. The active attributes and uniforms in+-- the linked program are recorded in the 'ShaderProgram'. The+-- supplied 'IO' function is applied to the new program after shader+-- objects are attached to the program, but before linking. This+-- supports the use of 'bindFragDataLocation' to map fragment shader+-- outputs.+loadShaderProgramWith :: FilePath -> FilePath -> (Program -> IO ())+                      -> IO ShaderProgram+loadShaderProgramWith vsrc fsrc m = loadProgramWithAux vsrc Nothing fsrc m++-- |Load a 'ShaderProgram' from a vertex shader source file, a+-- geometry shader source file, and a fragment shader source file. The+-- active attributes and uniforms in the linked program are recorded+-- in the 'ShaderProgram'. The supplied 'IO' function is applied to+-- the new program after shader objects are attached to the program,+-- but before linking. This supports the use of 'bindFragDataLocation'+-- to map fragment shader outputs.+loadGeoProgramWith :: FilePath -> FilePath -> FilePath -> (Program -> IO ())+                   -> IO ShaderProgram+loadGeoProgramWith vsrc gsrc fsrc m = loadProgramWithAux vsrc (Just gsrc) fsrc m++-- | Helper for @load*Program*@ variants.+loadProgramWithAux :: FilePath -> Maybe FilePath -> FilePath+                   -> (Program -> IO ()) -> IO ShaderProgram+loadProgramWithAux vsrc gsrc fsrc m =+  do vs <- loadShader vsrc+     gs <- maybe (return []) (fmap (:[]) . loadGeoShader) gsrc+     fs <- loadShader fsrc+     p <- linkGeoProgramWith [vs] gs [fs] m+     throwError+     (attrs,unis) <- getActives p+     return $ ShaderProgram (fromList attrs) (fromList unis) p+     ++getActives :: Program -> +              IO ( [(String, (AttribLocation, VariableType))]+                 , [(String, (UniformLocation, VariableType))] )+getActives p = +  (,) <$> (get (activeAttribs p) >>= mapM (aux (attribLocation p)))+      <*> (get (activeUniforms p) >>= mapM (aux (uniformLocation p)))+  where aux f (_,t,name) = get (f name) >>= \l -> return (name, (l, t))++getExplicits :: Program -> ([String], [String]) ->+                IO ( [(String, (AttribLocation, VariableType))]+                   , [(String, (UniformLocation, VariableType))] )+getExplicits p (anames, unames) = +  do attrs <- get (activeAttribs p)+     attrs' <- mapM (aux (get . (attribLocation p))) . checkJusts $+               map (\a -> find (\(_,_,n) -> n == a) attrs) anames+     unis <- get (activeUniforms p)+     unis' <- mapM (aux (get . (uniformLocation p))) . checkJusts $+              map (\u -> find (\(_,_,n) -> n == u) unis) unames+     return (attrs', unis')+  where aux f (_,t,n) = f n >>= \l -> return (n, (l,t))+        checkJusts xs+          | all isJust xs = catMaybes xs+          | otherwise = let Just i = findIndex isNothing xs+                        in error $ "Missing GLSL variable: " ++ anames !! i++setUniform :: Uniform a => ShaderProgram -> String -> a -> IO ()+setUniform sp name = maybe (const (putStrLn warn >> return ()))+                           (\(u,_) -> let u' = uniform u+                                      in \x -> u' $= x)+                           (lookup name $ uniforms sp)+  where warn = "WARNING: uniform "++name++" is not active"++getUniform :: ShaderProgram -> String -> UniformLocation+getUniform sp n = maybe (error msg) fst . lookup n $ uniforms sp+  where msg = "Uniform "++show n++" is not active"++setAttrib :: ShaderProgram -> String -> +             IntegerHandling -> VertexArrayDescriptor a -> IO ()+setAttrib sp name = maybe (\_ _ -> putStrLn warn >> return ())+                          (\(a,_) -> let vap = vertexAttribPointer a+                                     in \ih vad -> (($= (ih, vad)) vap))+                          (lookup name $ attribs sp)+  where warn = "WARNING: attrib "++name++" is not active"++getAttrib :: ShaderProgram -> String -> AttribLocation+getAttrib sp n = maybe (error msg) fst . lookup n $ attribs sp+  where msg = "Attrib "++show n++" is not active"++enableAttrib :: ShaderProgram -> String -> IO ()+enableAttrib sp name = maybe (return ())+                             (($= Enabled) . vertexAttribArray . fst)+                             (lookup name $ attribs sp)
src/Graphics/GLUtil/Shaders.hs view
@@ -1,10 +1,20 @@ -- |Utilities for working with fragment and vertex shader programs.-module Graphics.GLUtil.Shaders (loadShader, linkShaderProgram, namedUniform, +module Graphics.GLUtil.Shaders (loadShader, loadGeoShader,+                                linkShaderProgram,+                                linkShaderProgramWith, +                                linkGeoProgram, linkGeoProgramWith,+                                namedUniform,                                  uniformScalar, uniformVec, uniformMat,                                  namedUniformMat, uniformGLMat4) where-import Control.Monad (unless)+import Control.Applicative ((<$>))+import Control.Monad (unless, replicateM)+import Foreign.C.String (peekCStringLen, withCStringLen)+import Foreign.Marshal.Alloc (alloca, allocaBytes)+import Foreign.Marshal.Array (withArray)+import Foreign.Storable (peek) import Graphics.Rendering.OpenGL import Graphics.Rendering.OpenGL.Raw.Core31+import Graphics.Rendering.OpenGL.Raw.ARB.GeometryShader4 import Graphics.GLUtil.GLError import Foreign.Ptr (Ptr) import Unsafe.Coerce (unsafeCoerce)@@ -29,11 +39,76 @@     ioError (userError "shader compilation failed")   return shader +-- |Specialized loading for geometry shaders that are not yet fully+-- supported by the Haskell OpenGL package.+loadGeoShader :: FilePath -> IO GeometryShader+loadGeoShader filePath = do+  src <- readFile filePath+  [shader@(GeometryShader gid)] <- genObjectNames 1+  setSource gid src+  glCompileShader gid+  printError+  ok <- alloca $ \buf -> do+          glGetShaderiv gid gl_COMPILE_STATUS buf+          fmap (> 0) (peek buf)+  infoLogLen <- alloca $ \ptr -> do glGetShaderiv gid gl_INFO_LOG_LENGTH ptr+                                    peek ptr+  infoLog <- alloca $ \len ->+               allocaBytes (fromIntegral infoLogLen) $ \chars -> do +                 glGetShaderInfoLog gid infoLogLen len chars+                 len' <- fromIntegral <$> peek len+                 peekCStringLen (chars, len')+  unless (null infoLog)+         (mapM_ putStrLn +                ["Shader info log for '" ++ filePath ++ "':", infoLog, ""])+  unless ok $ do+    deleteObjectNames [shader]+    ioError (userError "shader compilation failed")+  return shader+  where setSource i src = +          do withCStringLen src $ \(charBuf,len)-> do+               withArray [charBuf] $ \charBufsBuf ->+                 withArray [fromIntegral len] $ \lengthsBuf ->+                   glShaderSource i 1 charBufsBuf lengthsBuf++ -- |Link vertex and fragment shaders into a 'Program'. linkShaderProgram :: [VertexShader] -> [FragmentShader] -> IO Program-linkShaderProgram vs fs = do+linkShaderProgram vs fs = linkShaderProgramWith vs fs (\_ -> return ())++-- |Link vertex and fragment shaders into a 'Program'. The supplied+-- 'IO' action is run after attaching shader objects to the new+-- program, but before linking. This supports the use of+-- 'bindFragDataLocation' to map fragment shader outputs.+linkShaderProgramWith :: [VertexShader] -> [FragmentShader]+                      -> (Program -> IO ()) -> IO Program+linkShaderProgramWith vs fs m = linkGeoProgramWith vs [] fs m++newtype GeometryShader = GeometryShader { geometryShaderID :: GLuint }+  deriving (Eq,Ord,Show)++instance ObjectName GeometryShader where+  genObjectNames n = replicateM n $ +                     fmap GeometryShader (glCreateShader gl_GEOMETRY_SHADER)+  deleteObjectNames = mapM_ (glDeleteShader . geometryShaderID)+  isObjectName = fmap (> 0) . glIsShader . geometryShaderID++-- |Link vertex, geometry, and fragment shaders into a 'Program'.+linkGeoProgram :: [VertexShader] -> [GeometryShader] -> [FragmentShader]+               -> IO Program+linkGeoProgram vs gs fs = linkGeoProgramWith vs gs fs (\_ -> return ())++-- |Link vertex, geometry, and fragment shaders into a 'Program'. The+-- supplied 'IO' action is run after attaching shader objects to the+-- new program, but before linking. This supports the use of+-- 'bindFragDataLocation' to map fragment shader outputs.+linkGeoProgramWith :: [VertexShader] -> [GeometryShader] -> [FragmentShader]+                   -> (Program -> IO ()) -> IO Program+linkGeoProgramWith vs gs fs m = do   [prog] <- genObjectNames 1   attachedShaders prog $= (vs, fs)+  mapM_ (glAttachShader (unsafeCoerce prog) . geometryShaderID) gs+  m prog   linkProgram prog   printError   ok <- get (linkStatus prog)
src/Graphics/GLUtil/Textures.hs view
@@ -2,8 +2,11 @@              ScopedTypeVariables, TypeFamilies, FlexibleContexts #-} -- |Utilities for loading texture data. module Graphics.GLUtil.Textures where+import Control.Monad (forM_) import Graphics.Rendering.OpenGL import qualified Graphics.Rendering.OpenGL.GL.VertexArrays as GL+import Graphics.Rendering.OpenGL.Raw.Core31 (glGenerateMipmap,+                                             gl_TEXTURE_2D, gl_TEXTURE_CUBE_MAP) import Data.Array.Storable (StorableArray, withStorableArray) import Data.ByteString.Internal (ByteString, toForeignPtr) import Data.Vector.Storable (Vector, unsafeWith)@@ -11,8 +14,9 @@ import Foreign.ForeignPtr (ForeignPtr, withForeignPtr) import Foreign.Ptr (Ptr, plusPtr, castPtr) import Foreign.Marshal.Array (withArray)-import Foreign.Storable (Storable) +import Graphics.GLUtil.TypeMapping (HasGLType(..))+ -- |Pixel format of image data. data TexColor = TexMono | TexRGB | TexBGR | TexRGBA @@ -27,15 +31,6 @@ texInfo :: Int -> Int -> TexColor -> a -> TexInfo a texInfo w h = TexInfo (fromIntegral w) (fromIntegral h) --- |Open mapping from Haskell types to OpenGL types.-class Storable a => HasGLType a where-  glType :: a -> DataType--instance HasGLType Int where glType _ = GL.Int-instance HasGLType Word8 where glType _ = GL.UnsignedByte-instance HasGLType Word16 where glType _ = GL.UnsignedShort-instance HasGLType Float where glType _ = GL.Float- -- |Class for containers of texture data. class HasGLType (Elem a) => IsPixelData a where   type Elem a@@ -78,7 +73,7 @@                            m (plusPtr (castPtr p :: Ptr Word16) o)  -- |Create a new 2D texture with data from a 'TexInfo'.-loadTexture :: IsPixelData a => TexInfo a -> IO (TextureObject)+loadTexture :: IsPixelData a => TexInfo a -> IO TextureObject loadTexture tex = do [obj] <- genObjectNames 1                      reloadTexture obj tex                      return obj@@ -90,7 +85,9 @@                            loadTex $ texColor tex   where loadTex TexMono = case pixelType of                             GL.UnsignedShort -> loadAux Luminance16 Luminance+                            GL.Float         -> loadAux R32F Red                             _                -> loadAux Luminance' Luminance+                                     loadTex TexRGB = loadAux RGBA' RGB         loadTex TexBGR = loadAux RGBA' BGR         loadTex TexRGBA = loadAux RGBA' RGBA@@ -99,3 +96,44 @@         loadAux i e = withPixels (texData tex) $                        (texImage2D Nothing NoProxy 0 i sz 0 .                        PixelData e pixelType)++-- | Set texture coordinate wrapping options for both the 'S' and 'T'+-- dimensions of a 2D texture.+texture2DWrap :: StateVar (Repetition, Clamping)+texture2DWrap = makeStateVar (get (textureWrapMode Texture2D S))+                             (forM_ [S,T] . aux)+  where aux x d = textureWrapMode Texture2D d $= x++-- | Set texture coordinate wrapping options for the 'S', 'T', and 'R'+-- dimensions of a 3D texture.+texture3DWrap :: StateVar (Repetition, Clamping)+texture3DWrap = makeStateVar (get (textureWrapMode Texture2D S))+                             (forM_ [S,T,R] . aux)+  where aux x d = textureWrapMode Texture2D d $= x+++-- | Bind each of the given textures to successive texture units at+-- the given 'TextureTarget'.+withTextures :: TextureTarget -> [TextureObject] -> IO a -> IO a+withTextures tt ts m = do mapM_ aux (zip ts [0..])+                          r <- m+                          cleanup 0 ts+                          return r+  where aux (t,i) = do activeTexture $= TextureUnit i+                       textureBinding tt $= Just t+        cleanup _ [] = return ()+        cleanup i (_:ts') = do activeTexture $= TextureUnit i+                               textureBinding Texture2D $= Nothing+                               cleanup (i+1) ts'++-- | Bind each of the given 2D textures to successive texture units.+withTextures2D :: [TextureObject] -> IO a -> IO a+withTextures2D = withTextures Texture2D++-- | Generate a complete set of mipmaps for the currently bound+-- texture object.+generateMipmap' :: TextureTarget -> IO ()+generateMipmap' Texture2D = glGenerateMipmap gl_TEXTURE_2D+generateMipmap' TextureCubeMap = glGenerateMipmap gl_TEXTURE_CUBE_MAP+generateMipmap' _ = error $ "generateMipmap' is only defined for "+++                            "2D textures and cube maps."
+ src/Graphics/GLUtil/TypeMapping.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}+-- |This module contains classes and functions to relate Haskell types+-- with OpenGL DataTypes (typically used to describe the values stored+-- in arrays) and VariableTypes (used as attributes and uniforms in+-- GLSL programs).+module Graphics.GLUtil.TypeMapping where+import Data.Int+import Data.Word+import Foreign.Storable (Storable)+import qualified Graphics.Rendering.OpenGL as GL+import Graphics.Rendering.OpenGL+import Linear (V2, V3, V4, M22, M33, M44)++class HasVariableType a where+  variableType :: a -> VariableType++instance HasVariableType Float where variableType _ = Float'+instance HasVariableType GLfloat where variableType _ = Float'+instance HasVariableType GLint where variableType _ = Int'+instance HasVariableType Int32 where variableType _ = Int'+instance HasVariableType Word32 where variableType _ = UnsignedInt'+instance HasVariableType GLuint where variableType _ = UnsignedInt'++instance HasVariableType (V2 GLfloat) where variableType _ = FloatVec2+instance HasVariableType (V3 GLfloat) where variableType _ = FloatVec3+instance HasVariableType (V4 GLfloat) where variableType _ = FloatVec4++instance HasVariableType (V2 GLint) where variableType _ = IntVec2+instance HasVariableType (V3 GLint) where variableType _ = IntVec3+instance HasVariableType (V4 GLint) where variableType _ = IntVec4++instance HasVariableType (V2 Int32) where variableType _ = IntVec2+instance HasVariableType (V3 Int32) where variableType _ = IntVec3+instance HasVariableType (V4 Int32) where variableType _ = IntVec4++instance HasVariableType (V2 Word32) where variableType _ = UnsignedIntVec2+instance HasVariableType (V3 Word32) where variableType _ = UnsignedIntVec3+instance HasVariableType (V4 Word32) where variableType _ = UnsignedIntVec4++instance HasVariableType (V2 GLuint) where variableType _ = UnsignedIntVec2+instance HasVariableType (V3 GLuint) where variableType _ = UnsignedIntVec3+instance HasVariableType (V4 GLuint) where variableType _ = UnsignedIntVec4++instance HasVariableType (M22 GLfloat) where variableType _ = FloatMat2+instance HasVariableType (M33 GLfloat) where variableType _ = FloatMat3+instance HasVariableType (M44 GLfloat) where variableType _ = FloatMat4++-- | Maps each 'VariableType' to its corresponding+-- 'DataType'. Typically this indicates the element type of composite+-- variable types (e.g. @variableDataType FloatVec2 = Float@). Note+-- that this is a partial mapping as we are primarily supporting the+-- use of these types as inputs to GLSL programs where types such as+-- Bool are not supported.+variableDataType :: VariableType -> DataType+variableDataType Float' = GL.Float+variableDataType FloatVec2 = GL.Float+variableDataType FloatVec3 = GL.Float+variableDataType FloatVec4 = GL.Float+variableDataType Int' = GL.Int+variableDataType IntVec2 = GL.Int+variableDataType IntVec3 = GL.Int+variableDataType IntVec4 = GL.Int+variableDataType UnsignedInt' = GL.UnsignedInt+variableDataType UnsignedIntVec2 = GL.UnsignedInt+variableDataType UnsignedIntVec3 = GL.UnsignedInt+variableDataType UnsignedIntVec4 = GL.UnsignedInt+variableDataType FloatMat2 = GL.Float+variableDataType FloatMat3 = GL.Float+variableDataType FloatMat4 = GL.Float+variableDataType FloatMat2x3 = GL.Float	+variableDataType FloatMat2x4 = GL.Float	 +variableDataType FloatMat3x2 = GL.Float	 +variableDataType FloatMat3x4 = GL.Float	 +variableDataType FloatMat4x2 = GL.Float	 +variableDataType FloatMat4x3 = GL.Float+variableDataType _ = error "Unsupported variable type!"++-- |Open mapping from Haskell types to OpenGL types.+class Storable a => HasGLType a where+  glType :: a -> DataType++instance HasGLType Int where glType _ = GL.Int+instance HasGLType GLint where glType _ = GL.Int+instance HasGLType Word8 where glType _ = GL.UnsignedByte+instance HasGLType Word16 where glType _ = GL.UnsignedShort+instance HasGLType Word32 where glType _ = GL.UnsignedInt+instance HasGLType GLuint where glType _ = GL.UnsignedInt+instance HasGLType Float where glType _ = GL.Float+instance HasGLType GLfloat where glType _ = GL.Float
src/Graphics/GLUtil/VertexArrayObjects.hs view
@@ -1,36 +1,24 @@ -- | A thin layer over OpenGL 3.1+ vertex array objects.-module Graphics.GLUtil.VertexArrayObjects -  (VertexArrayObject(..), VAO, makeVAO, deleteVAO, bindVertexArray) where-import Foreign.Marshal.Array (allocaArray)-import Foreign.Marshal.Utils (with)-import Foreign.Storable (peek)-import Graphics.Rendering.OpenGL.Raw.Core31---- |A vertex array object captures OpenGL state needed for drawing a--- vertex array. It encapsulates the binding of an array buffer and an--- element buffer, as well as vertex attribute setup.-newtype VertexArrayObject = VertexArrayObject GLuint+module Graphics.GLUtil.VertexArrayObjects (makeVAO, withVAO, VAO) where+import Control.Applicative+import Graphics.Rendering.OpenGL --- |Short alias.+-- |Short alias for 'VertexArrayObject'. type VAO = VertexArrayObject  -- |Allocate a 'VertexArrayObject', and initialize it with the -- provided action. This action should bind the buffer data, index -- data (if necessary), and setup vertex attributes. makeVAO :: IO () -> IO VertexArrayObject-makeVAO m = do vao <- allocaArray 1 $ \ptr -> -                        glGenVertexArrays 1 ptr >> peek ptr-               glBindVertexArray vao-               m-               glBindVertexArray 0-               return $ VertexArrayObject vao---- |Delete a 'VertexArrayObject'. Do not use the VAO after running--- this action!-deleteVAO :: VertexArrayObject -> IO ()-deleteVAO (VertexArrayObject i) = with i $ glDeleteVertexArrays 1+makeVAO setup = do [vao] <- genObjectNames 1+                   bindVertexArrayObject $= Just vao+                   setup+                   bindVertexArrayObject $= Nothing+                   return vao --- |Bind a 'VertexArrayObject', or ensure that no VAO is bound.-bindVertexArray :: Maybe VertexArrayObject -> IO ()-bindVertexArray (Just (VertexArrayObject i)) = glBindVertexArray i-bindVertexArray Nothing = glBindVertexArray 0+-- |Run an action with the given 'VertexArrayObject' bound.+withVAO :: VertexArrayObject -> IO r -> IO r+withVAO vao useIt = do bindVertexArrayObject $= Just vao+                       r <- useIt+                       bindVertexArrayObject $= Nothing+                       return r
+ src/Graphics/GLUtil/Viewport.hs view
@@ -0,0 +1,9 @@+module Graphics.GLUtil.Viewport where+import Graphics.Rendering.OpenGL++withViewport :: Position -> Size -> IO a -> IO a+withViewport p s m = do oldVP <- get viewport+                        viewport $= (p,s)+                        r <- m+                        viewport $= oldVP+                        return r