module Graphics.Rendering.OpenGL.GL.Shaders (
Shader, VertexShader, FragmentShader, shaderDeleteStatus, shaderSource,
compileShader, compileStatus, shaderInfoLog,
Program, programDeleteStatus, attachedShaders, linkProgram, linkStatus,
programInfoLog, validateProgram, validateStatus, currentProgram,
attribLocation, VariableType(..), activeAttribs,
UniformLocation, uniformLocation, activeUniforms, Uniform(..),
UniformComponent,
maxVertexTextureImageUnits, maxTextureImageUnits,
maxCombinedTextureImageUnits, maxTextureCoords, maxVertexUniformComponents,
maxFragmentUniformComponents, maxVertexAttribs, maxVaryingFloats
) where
import Control.Monad ( replicateM, mapM_, foldM )
import Control.Monad.Fix ( MonadFix(..) )
import Data.Int
import Data.List ( genericLength, (\\) )
import Foreign.C.String ( peekCAStringLen, withCAStringLen )
import Foreign.Marshal.Alloc ( alloca, allocaBytes )
import Foreign.Marshal.Array ( allocaArray, withArray, peekArray )
import Foreign.Marshal.Utils ( withMany )
import Foreign.Ptr ( Ptr, castPtr, nullPtr )
import Foreign.Storable ( Storable(peek,sizeOf) )
import Graphics.Rendering.OpenGL.GL.BasicTypes (
GLboolean, GLchar, GLint, GLuint, GLsizei, GLenum, GLfloat )
import Graphics.Rendering.OpenGL.GL.BufferObjects ( ObjectName(..) )
import Graphics.Rendering.OpenGL.GL.Extensions (
FunPtr, unsafePerformIO, Invoker, getProcAddress )
import Graphics.Rendering.OpenGL.GL.GLboolean ( unmarshalGLboolean )
import Graphics.Rendering.OpenGL.GL.PeekPoke ( peek1 )
import Graphics.Rendering.OpenGL.GL.QueryUtils (
GetPName(GetMaxCombinedTextureImageUnits, GetMaxFragmentUniformComponents,
GetMaxTextureCoords, GetMaxTextureImageUnits,GetMaxVaryingFloats,
GetMaxVertexAttribs, GetMaxVertexTextureImageUnits,
GetMaxVertexUniformComponents, GetCurrentProgram),
getInteger1, getSizei1 )
import Graphics.Rendering.OpenGL.GL.StateVar (
HasGetter(get), GettableStateVar, makeGettableStateVar, StateVar,
makeStateVar )
import Graphics.Rendering.OpenGL.GL.VertexSpec (
AttribLocation(..), Vertex2(..), Vertex3(..), Vertex4(..), TexCoord1(..),
TexCoord2(..), TexCoord3(..), TexCoord4(..), Normal3(..), FogCoord1(..),
Color3(..), Color4(..), Index1(..) )
#include "HsOpenGLExt.h"
#include "HsOpenGLTypes.h"
type GLStringLen = (Ptr GLchar, GLsizei)
peekGLstringLen :: GLStringLen -> IO String
peekGLstringLen (p,l) = peekCAStringLen (castPtr p, fromIntegral l)
withGLStringLen :: String -> (GLStringLen -> IO a) -> IO a
withGLStringLen s act =
withCAStringLen s $ \(p,len) ->
act (castPtr p, fromIntegral len)
newtype VertexShader = VertexShader { vertexShaderID :: GLuint }
deriving ( Eq, Ord, Show )
newtype FragmentShader = FragmentShader { fragmentShaderID :: GLuint }
deriving ( Eq, Ord, Show )
class (Eq s, Ord s, Show s, ObjectName s) => Shader s where
shaderID :: s -> GLuint
makeShader :: GLuint -> s
shaderType :: s -> GLenum
instance Shader VertexShader where
makeShader = VertexShader
shaderID = vertexShaderID
shaderType = const 0x8B31
instance Shader FragmentShader where
makeShader = FragmentShader
shaderID = fragmentShaderID
shaderType = const 0x8B30
instance ObjectName VertexShader where
genObjectNames = genShaderNames
deleteObjectNames = deleteShaderNames
isObjectName = isShaderName
instance ObjectName FragmentShader where
genObjectNames = genShaderNames
deleteObjectNames = deleteShaderNames
isObjectName = isShaderName
genShaderNames :: Shader s => Int -> IO [s]
genShaderNames n = replicateM n createShader
createShader :: Shader s => IO s
createShader = mfix (fmap makeShader . glCreateShader . shaderType)
deleteShaderNames :: Shader s => [s] -> IO ()
deleteShaderNames = mapM_ (glDeleteShader . shaderID)
isShaderName :: Shader s => s -> IO Bool
isShaderName = fmap unmarshalGLboolean . glIsShader . shaderID
EXTENSION_ENTRY("OpenGL 2.0",glCreateShader,GLenum -> IO GLuint)
EXTENSION_ENTRY("OpenGL 2.0",glDeleteShader,GLuint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glIsShader,GLuint -> IO GLboolean)
compileShader :: Shader s => s -> IO ()
compileShader = glCompileShader . shaderID
EXTENSION_ENTRY("OpenGL 2.0",glCompileShader,GLuint -> IO ())
shaderSource :: Shader s => s -> StateVar [String]
shaderSource shader =
makeStateVar (getShaderSource shader) (setShaderSource shader)
setShaderSource :: Shader s => s -> [String] -> IO ()
setShaderSource shader srcs = do
let len = genericLength srcs
withMany withGLStringLen srcs $ \charBufsAndLengths -> do
let (charBufs, lengths) = unzip charBufsAndLengths
withArray charBufs $ \charBufsBuf ->
withArray lengths $ \lengthsBuf ->
glShaderSource (shaderID shader) len charBufsBuf lengthsBuf
EXTENSION_ENTRY("OpenGL 2.0",glShaderSource,GLuint -> GLsizei -> Ptr (Ptr GLchar) -> Ptr GLint -> IO ())
getShaderSource :: Shader s => s -> IO [String]
getShaderSource shader = do
src <- get (stringQuery (shaderSourceLength shader)
(glGetShaderSource (shaderID shader)))
return [src]
EXTENSION_ENTRY("OpenGL 2.0",glGetShaderSource,GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO ())
stringQuery :: GettableStateVar GLsizei -> (GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO ()) -> GettableStateVar String
stringQuery lengthVar getStr =
makeGettableStateVar $ do
len <- get lengthVar
if len == 0
then return ""
else allocaArray (fromIntegral len) $ \buf -> do
getStr len nullPtr buf
peekGLstringLen (buf, len1)
shaderInfoLog :: Shader s => s -> GettableStateVar String
shaderInfoLog shader =
stringQuery (shaderInfoLogLength shader) (glGetShaderInfoLog (shaderID shader))
EXTENSION_ENTRY("OpenGL 2.0",glGetShaderInfoLog,GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO ())
shaderDeleteStatus :: Shader s => s -> GettableStateVar Bool
shaderDeleteStatus = shaderVar unmarshalGLboolean ShaderDeleteStatus
compileStatus :: Shader s => s -> GettableStateVar Bool
compileStatus = shaderVar unmarshalGLboolean CompileStatus
shaderInfoLogLength :: Shader s => s -> GettableStateVar GLsizei
shaderInfoLogLength = shaderVar fromIntegral ShaderInfoLogLength
shaderSourceLength :: Shader s => s -> GettableStateVar GLsizei
shaderSourceLength = shaderVar fromIntegral ShaderSourceLength
shaderTypeEnum :: Shader s => s -> GettableStateVar GLenum
shaderTypeEnum = shaderVar fromIntegral ShaderType
data GetShaderPName =
ShaderDeleteStatus
| CompileStatus
| ShaderInfoLogLength
| ShaderSourceLength
| ShaderType
marshalGetShaderPName :: GetShaderPName -> GLenum
marshalGetShaderPName x = case x of
ShaderDeleteStatus -> 0x8B80
CompileStatus -> 0x8B81
ShaderInfoLogLength -> 0x8B84
ShaderSourceLength -> 0x8B88
ShaderType -> 0x8B4F
shaderVar :: Shader s => (GLint -> a) -> GetShaderPName -> s -> GettableStateVar a
shaderVar f p shader =
makeGettableStateVar $
alloca $ \buf -> do
glGetShaderiv (shaderID shader) (marshalGetShaderPName p) buf
peek1 f buf
EXTENSION_ENTRY("OpenGL 2.0",glGetShaderiv,GLuint -> GLenum -> Ptr GLint -> IO ())
newtype Program = Program { programID :: GLuint }
deriving ( Eq, Ord, Show )
instance ObjectName Program where
genObjectNames n = replicateM n $ fmap Program glCreateProgram
deleteObjectNames = mapM_ (glDeleteProgram . programID)
isObjectName = fmap unmarshalGLboolean . glIsProgram . programID
EXTENSION_ENTRY("OpenGL 2.0",glCreateProgram,IO GLuint)
EXTENSION_ENTRY("OpenGL 2.0",glDeleteProgram,GLuint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glIsProgram,GLuint -> IO GLboolean)
attachedShaders :: Program -> StateVar ([VertexShader],[FragmentShader])
attachedShaders program =
makeStateVar (getAttachedShaders program) (setAttachedShaders program)
getAttachedShaders :: Program -> IO ([VertexShader],[FragmentShader])
getAttachedShaders program = getAttachedShaderIDs program >>= splitShaderIDs
getAttachedShaderIDs :: Program -> IO [GLuint]
getAttachedShaderIDs program = do
numShaders <- get (numAttachedShaders program)
allocaArray (fromIntegral numShaders) $ \buf -> do
glGetAttachedShaders (programID program) numShaders nullPtr buf
peekArray (fromIntegral numShaders) buf
EXTENSION_ENTRY("OpenGL 2.0",glGetAttachedShaders,GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLuint -> IO ())
splitShaderIDs :: [GLuint] -> IO ([VertexShader],[FragmentShader])
splitShaderIDs ids = do
(vs, fs) <- partitionM isVertexShaderID ids
return (map VertexShader vs, map FragmentShader fs)
isVertexShaderID :: GLuint -> IO Bool
isVertexShaderID x = do
t <- get (shaderTypeEnum (VertexShader x))
return $ t == shaderType (undefined :: VertexShader)
partitionM :: (a -> IO Bool) -> [a] -> IO ([a],[a])
partitionM p = foldM select ([],[])
where select (ts, fs) x = do
b <- p x
return $ if b then (x:ts, fs) else (ts, x:fs)
setAttachedShaders :: Program -> ([VertexShader],[FragmentShader]) -> IO ()
setAttachedShaders program (vs, fs) = do
currentIDs <- getAttachedShaderIDs program
let newIDs = map shaderID vs ++ map shaderID fs
mapM_ (glAttachShader program) (newIDs \\ currentIDs)
mapM_ (glDetachShader program) (currentIDs \\ newIDs)
EXTENSION_ENTRY("OpenGL 2.0",glAttachShader,Program -> GLuint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glDetachShader,Program -> GLuint -> IO ())
linkProgram :: Program -> IO ()
linkProgram = glLinkProgram
EXTENSION_ENTRY("OpenGL 2.0",glLinkProgram,Program -> IO ())
currentProgram :: StateVar (Maybe Program)
currentProgram =
makeStateVar
(do p <- getCurrentProgram
return $ if p == noProgram then Nothing else Just p)
(glUseProgram . maybe noProgram id)
getCurrentProgram :: IO Program
getCurrentProgram = fmap Program $ getInteger1 fromIntegral GetCurrentProgram
noProgram :: Program
noProgram = Program 0
EXTENSION_ENTRY("OpenGL 2.0",glUseProgram,Program -> IO ())
validateProgram :: Program -> IO ()
validateProgram = glValidateProgram
EXTENSION_ENTRY("OpenGL 2.0",glValidateProgram,Program -> IO ())
programInfoLog :: Program -> GettableStateVar String
programInfoLog p =
stringQuery (programInfoLogLength p) (glGetProgramInfoLog (programID p))
EXTENSION_ENTRY("OpenGL 2.0",glGetProgramInfoLog,GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO ())
programDeleteStatus :: Program -> GettableStateVar Bool
programDeleteStatus = programVar unmarshalGLboolean ProgramDeleteStatus
linkStatus :: Program -> GettableStateVar Bool
linkStatus = programVar unmarshalGLboolean LinkStatus
validateStatus :: Program -> GettableStateVar Bool
validateStatus = programVar unmarshalGLboolean ValidateStatus
programInfoLogLength :: Program -> GettableStateVar GLsizei
programInfoLogLength = programVar fromIntegral ProgramInfoLogLength
numAttachedShaders :: Program -> GettableStateVar GLsizei
numAttachedShaders = programVar fromIntegral AttachedShaders
activeAttributes :: Program -> GettableStateVar GLuint
activeAttributes = programVar fromIntegral ActiveAttributes
activeAttributeMaxLength :: Program -> GettableStateVar GLsizei
activeAttributeMaxLength = programVar fromIntegral ActiveAttributeMaxLength
numActiveUniforms :: Program -> GettableStateVar GLuint
numActiveUniforms = programVar fromIntegral ActiveUniforms
activeUniformMaxLength :: Program -> GettableStateVar GLsizei
activeUniformMaxLength = programVar fromIntegral ActiveUniformMaxLength
data GetProgramPName =
ProgramDeleteStatus
| LinkStatus
| ValidateStatus
| ProgramInfoLogLength
| AttachedShaders
| ActiveAttributes
| ActiveAttributeMaxLength
| ActiveUniforms
| ActiveUniformMaxLength
marshalGetProgramPName :: GetProgramPName -> GLenum
marshalGetProgramPName x = case x of
ProgramDeleteStatus -> 0x8B80
LinkStatus -> 0x8B82
ValidateStatus -> 0x8B83
ProgramInfoLogLength -> 0x8B84
AttachedShaders -> 0x8B85
ActiveAttributes -> 0x8B89
ActiveAttributeMaxLength -> 0x8B8A
ActiveUniforms -> 0x8B86
ActiveUniformMaxLength -> 0x8B87
programVar :: (GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
programVar f p program =
makeGettableStateVar $
alloca $ \buf -> do
glGetProgramiv (programID program) (marshalGetProgramPName p) buf
peek1 f buf
EXTENSION_ENTRY("OpenGL 2.0",glGetProgramiv,GLuint -> GLenum -> Ptr GLint -> IO ())
attribLocation :: Program -> String -> StateVar AttribLocation
attribLocation program name =
makeStateVar (getAttribLocation program name)
(\location -> bindAttribLocation program location name)
getAttribLocation :: Program -> String -> IO AttribLocation
getAttribLocation program name =
withGLStringLen name $ \(buf,_) ->
fmap (AttribLocation . fromIntegral) $
glGetAttribLocation program buf
EXTENSION_ENTRY("OpenGL 2.0",glGetAttribLocation,Program -> Ptr GLchar -> IO GLint)
bindAttribLocation :: Program -> AttribLocation -> String -> IO ()
bindAttribLocation program location name =
withGLStringLen name $ \(buf,_) ->
glBindAttribLocation program location buf
EXTENSION_ENTRY("OpenGL 2.0",glBindAttribLocation,Program -> AttribLocation -> Ptr GLchar -> IO ())
data VariableType =
Float'
| FloatVec2
| FloatVec3
| FloatVec4
| FloatMat2
| FloatMat3
| FloatMat4
| Int'
| IntVec2
| IntVec3
| IntVec4
| Bool
| BoolVec2
| BoolVec3
| BoolVec4
| Sampler1D
| Sampler2D
| Sampler3D
| SamplerCube
| Sampler1DShadow
| Sampler2DShadow
deriving ( Eq, Ord, Show )
unmarshalVariableType :: GLenum -> VariableType
unmarshalVariableType x
| x == 0x1406 = Float'
| x == 0x8B50 = FloatVec2
| x == 0x8B51 = FloatVec3
| x == 0x8B52 = FloatVec4
| x == 0x8B5A = FloatMat2
| x == 0x8B5B = FloatMat3
| x == 0x8B5C = FloatMat4
| x == 0x1404 = Int'
| x == 0x8B53 = IntVec2
| x == 0x8B54 = IntVec3
| x == 0x8B55 = IntVec4
| x == 0x8B56 = Bool
| x == 0x8B57 = BoolVec2
| x == 0x8B58 = BoolVec3
| x == 0x8B59 = BoolVec4
| x == 0x8B5D = Sampler1D
| x == 0x8B5E = Sampler2D
| x == 0x8B5F = Sampler3D
| x == 0x8B60 = SamplerCube
| x == 0x8B61 = Sampler1DShadow
| x == 0x8B62 = Sampler2DShadow
| otherwise = error ("unmarshalVariableType: illegal value " ++ show x)
activeVars :: (Program -> GettableStateVar GLuint)
-> (Program -> GettableStateVar GLsizei)
-> (Program -> GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLint -> Ptr GLenum -> Ptr GLchar -> IO ())
-> Program -> GettableStateVar [(GLint,VariableType,String)]
activeVars numVars maxLength getter program =
makeGettableStateVar $ do
numActiveVars <- get (numVars program)
maxLen <- get (maxLength program)
allocaArray (fromIntegral maxLen) $ \nameBuf ->
alloca $ \nameLengthBuf ->
alloca $ \sizeBuf ->
alloca $ \typeBuf ->
flip mapM [0 .. numActiveVars 1] $ \i -> do
getter program i maxLen nameLengthBuf sizeBuf typeBuf nameBuf
l <- peek nameLengthBuf
s <- peek sizeBuf
t <- peek typeBuf
n <- peekGLstringLen (nameBuf, l)
return (s, unmarshalVariableType t, n)
activeAttribs :: Program -> GettableStateVar [(GLint,VariableType,String)]
activeAttribs = activeVars activeAttributes activeAttributeMaxLength glGetActiveAttrib
EXTENSION_ENTRY("OpenGL 2.0",glGetActiveAttrib,Program -> GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLint -> Ptr GLenum -> Ptr GLchar -> IO ())
newtype UniformLocation = UniformLocation GLint
deriving ( Eq, Ord, Show )
uniformLocation :: Program -> String -> GettableStateVar UniformLocation
uniformLocation program name =
makeGettableStateVar $
withGLStringLen name $ \(buf,_) ->
fmap UniformLocation $
glGetUniformLocation program buf
EXTENSION_ENTRY("OpenGL 2.0",glGetUniformLocation,Program -> Ptr GLchar -> IO GLint)
activeUniforms :: Program -> GettableStateVar [(GLint,VariableType,String)]
activeUniforms = activeVars numActiveUniforms activeUniformMaxLength glGetActiveUniform
EXTENSION_ENTRY("OpenGL 2.0",glGetActiveUniform,Program -> GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLint -> Ptr GLenum -> Ptr GLchar -> IO ())
class Storable a => UniformComponent a where
uniform1 :: UniformLocation -> a -> IO ()
uniform2 :: UniformLocation -> a -> a -> IO ()
uniform3 :: UniformLocation -> a -> a -> a -> IO ()
uniform4 :: UniformLocation -> a -> a -> a -> a -> IO ()
getUniform :: Storable (b a) => Program -> UniformLocation -> Ptr (b a) -> IO ()
uniform1v :: UniformLocation -> GLsizei -> Ptr a -> IO ()
uniform2v :: UniformLocation -> GLsizei -> Ptr a -> IO ()
uniform3v :: UniformLocation -> GLsizei -> Ptr a -> IO ()
uniform4v :: UniformLocation -> GLsizei -> Ptr a -> IO ()
EXTENSION_ENTRY("OpenGL 2.0",glUniform1i,UniformLocation -> GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform2i,UniformLocation -> GLint -> GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform3i,UniformLocation -> GLint -> GLint -> GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform4i,UniformLocation -> GLint -> GLint -> GLint -> GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glGetUniformiv,Program -> UniformLocation -> Ptr GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform1iv,UniformLocation -> GLsizei -> Ptr GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform2iv,UniformLocation -> GLsizei -> Ptr GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform3iv,UniformLocation -> GLsizei -> Ptr GLint -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform4iv,UniformLocation -> GLsizei -> Ptr GLint -> IO ())
instance UniformComponent GLint_ where
uniform1 = glUniform1i
uniform2 = glUniform2i
uniform3 = glUniform3i
uniform4 = glUniform4i
getUniform program location = glGetUniformiv program location . castPtr
uniform1v = glUniform1iv
uniform2v = glUniform2iv
uniform3v = glUniform3iv
uniform4v = glUniform4iv
EXTENSION_ENTRY("OpenGL 2.0",glUniform1f,UniformLocation -> GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform2f,UniformLocation -> GLfloat -> GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform3f,UniformLocation -> GLfloat -> GLfloat -> GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform4f,UniformLocation -> GLfloat -> GLfloat -> GLfloat -> GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glGetUniformfv,Program -> UniformLocation -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform1fv,UniformLocation -> GLsizei -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform2fv,UniformLocation -> GLsizei -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform3fv,UniformLocation -> GLsizei -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniform4fv,UniformLocation -> GLsizei -> Ptr GLfloat -> IO ())
instance UniformComponent GLfloat_ where
uniform1 = glUniform1f
uniform2 = glUniform2f
uniform3 = glUniform3f
uniform4 = glUniform4f
getUniform program location = glGetUniformfv program location . castPtr
uniform1v = glUniform1fv
uniform2v = glUniform2fv
uniform3v = glUniform3fv
uniform4v = glUniform4fv
EXTENSION_ENTRY("OpenGL 2.0",glUniformMatrix2fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniformMatrix3fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.0",glUniformMatrix4fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.1",glUniformMatrix2x3fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.1",glUniformMatrix3x2fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.1",glUniformMatrix2x4fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.1",glUniformMatrix4x2fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.1",glUniformMatrix3x4fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
EXTENSION_ENTRY("OpenGL 2.1",glUniformMatrix4x3fv,UniformLocation -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ())
class Uniform a where
uniform :: UniformLocation -> StateVar a
uniformv :: UniformLocation -> GLsizei -> Ptr a -> IO ()
maxComponentSize :: Int
maxComponentSize = sizeOf (undefined :: GLint) `max` sizeOf (undefined :: GLfloat)
maxNumComponents :: Int
maxNumComponents = 16
maxUniformBufferSize :: Int
maxUniformBufferSize = maxComponentSize * maxNumComponents
makeUniformVar :: (UniformComponent a, Storable (b a))
=> (UniformLocation -> b a -> IO ())
-> UniformLocation -> StateVar (b a)
makeUniformVar setter location = makeStateVar getter (setter location)
where getter = do
program <- getCurrentProgram
allocaBytes maxUniformBufferSize $ \buf -> do
getUniform program location buf
peek buf
instance UniformComponent a => Uniform (Vertex2 a) where
uniform = makeUniformVar $ \location (Vertex2 x y) -> uniform2 location x y
uniformv location count = uniform2v location count . (castPtr :: Ptr (Vertex2 b) -> Ptr b)
instance UniformComponent a => Uniform (Vertex3 a) where
uniform = makeUniformVar $ \location (Vertex3 x y z) -> uniform3 location x y z
uniformv location count = uniform3v location count . (castPtr :: Ptr (Vertex3 b) -> Ptr b)
instance UniformComponent a => Uniform (Vertex4 a) where
uniform = makeUniformVar $ \location (Vertex4 x y z w) -> uniform4 location x y z w
uniformv location count = uniform4v location count . (castPtr :: Ptr (Vertex4 b) -> Ptr b)
instance UniformComponent a => Uniform (TexCoord1 a) where
uniform = makeUniformVar $ \location (TexCoord1 s) -> uniform1 location s
uniformv location count = uniform1v location count . (castPtr :: Ptr (TexCoord1 b) -> Ptr b)
instance UniformComponent a => Uniform (TexCoord2 a) where
uniform = makeUniformVar $ \location (TexCoord2 s t) -> uniform2 location s t
uniformv location count = uniform2v location count . (castPtr :: Ptr (TexCoord2 b) -> Ptr b)
instance UniformComponent a => Uniform (TexCoord3 a) where
uniform = makeUniformVar $ \location (TexCoord3 s t r) -> uniform3 location s t r
uniformv location count = uniform3v location count . (castPtr :: Ptr (TexCoord3 b) -> Ptr b)
instance UniformComponent a => Uniform (TexCoord4 a) where
uniform = makeUniformVar $ \location (TexCoord4 s t r q) -> uniform4 location s t r q
uniformv location count = uniform4v location count . (castPtr :: Ptr (TexCoord4 b) -> Ptr b)
instance UniformComponent a => Uniform (Normal3 a) where
uniform = makeUniformVar $ \location (Normal3 x y z) -> uniform3 location x y z
uniformv location count = uniform3v location count . (castPtr :: Ptr (Normal3 b) -> Ptr b)
instance UniformComponent a => Uniform (FogCoord1 a) where
uniform = makeUniformVar $ \location (FogCoord1 c) -> uniform1 location c
uniformv location count = uniform1v location count . (castPtr :: Ptr (FogCoord1 b) -> Ptr b)
instance UniformComponent a => Uniform (Color3 a) where
uniform = makeUniformVar $ \location (Color3 r g b) -> uniform3 location r g b
uniformv location count = uniform3v location count . (castPtr :: Ptr (Color3 b) -> Ptr b)
instance UniformComponent a => Uniform (Color4 a) where
uniform = makeUniformVar $ \location (Color4 r g b a) -> uniform4 location r g b a
uniformv location count = uniform4v location count . (castPtr :: Ptr (Color4 b) -> Ptr b)
instance UniformComponent a => Uniform (Index1 a) where
uniform = makeUniformVar $ \location (Index1 i) -> uniform1 location i
uniformv location count = uniform1v location count . (castPtr :: Ptr (Index1 b) -> Ptr b)
maxVertexTextureImageUnits :: GettableStateVar GLsizei
maxVertexTextureImageUnits = getLimit GetMaxVertexTextureImageUnits
maxTextureImageUnits :: GettableStateVar GLsizei
maxTextureImageUnits = getLimit GetMaxTextureImageUnits
maxCombinedTextureImageUnits :: GettableStateVar GLsizei
maxCombinedTextureImageUnits = getLimit GetMaxCombinedTextureImageUnits
maxTextureCoords :: GettableStateVar GLsizei
maxTextureCoords = getLimit GetMaxTextureCoords
maxVertexUniformComponents :: GettableStateVar GLsizei
maxVertexUniformComponents = getLimit GetMaxVertexUniformComponents
maxFragmentUniformComponents :: GettableStateVar GLsizei
maxFragmentUniformComponents = getLimit GetMaxFragmentUniformComponents
maxVertexAttribs :: GettableStateVar GLsizei
maxVertexAttribs = getLimit GetMaxVertexAttribs
maxVaryingFloats :: GettableStateVar GLsizei
maxVaryingFloats = getLimit GetMaxVaryingFloats
getLimit :: GetPName -> GettableStateVar GLsizei
getLimit = makeGettableStateVar . getSizei1 id