{-# LANGUAGE TypeSynonymInstances #-}
module Graphics.Rendering.OpenGL.GL.Shaders.Uniform (
UniformLocation(..), uniformLocation, activeUniforms, Uniform(..),
UniformComponent,
) where
import Data.Maybe
import Data.StateVar
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import Graphics.Rendering.OpenGL.GL.ByteString
import Graphics.Rendering.OpenGL.GL.CoordTrans
import Graphics.Rendering.OpenGL.GL.GLboolean
import Graphics.Rendering.OpenGL.GL.MatrixComponent
import Graphics.Rendering.OpenGL.GL.Shaders.Program
import Graphics.Rendering.OpenGL.GL.Shaders.ProgramObjects
import Graphics.Rendering.OpenGL.GL.Shaders.Variables
import Graphics.Rendering.OpenGL.GL.Tensor
import Graphics.Rendering.OpenGL.GL.VertexSpec
import Graphics.GL
numActiveUniforms :: Program -> GettableStateVar GLuint
numActiveUniforms = programVar1 fromIntegral ActiveUniforms
activeUniformMaxLength :: Program -> GettableStateVar GLsizei
activeUniformMaxLength = programVar1 fromIntegral ActiveUniformMaxLength
newtype UniformLocation = UniformLocation GLint
deriving ( Eq, Ord, Show )
uniformLocation :: Program -> String -> GettableStateVar UniformLocation
uniformLocation (Program program) name =
makeGettableStateVar $
fmap UniformLocation $
withGLstring name $
glGetUniformLocation program
activeUniforms :: Program -> GettableStateVar [(GLint,VariableType,String)]
activeUniforms =
activeVars
numActiveUniforms
activeUniformMaxLength
glGetActiveUniform
unmarshalVariableType
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) => GLuint -> GLint -> 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 ()
instance UniformComponent GLint where
uniform1 (UniformLocation ul) = glUniform1i ul
uniform2 (UniformLocation ul) = glUniform2i ul
uniform3 (UniformLocation ul) = glUniform3i ul
uniform4 (UniformLocation ul) = glUniform4i ul
getUniform p ul = glGetUniformiv p ul . castPtr
uniform1v (UniformLocation ul) = glUniform1iv ul
uniform2v (UniformLocation ul) = glUniform2iv ul
uniform3v (UniformLocation ul) = glUniform3iv ul
uniform4v (UniformLocation ul) = glUniform4iv ul
instance UniformComponent GLuint where
uniform1 (UniformLocation ul) = glUniform1ui ul
uniform2 (UniformLocation ul) = glUniform2ui ul
uniform3 (UniformLocation ul) = glUniform3ui ul
uniform4 (UniformLocation ul) = glUniform4ui ul
getUniform p ul = glGetUniformuiv p ul . castPtr
uniform1v (UniformLocation ul) = glUniform1uiv ul
uniform2v (UniformLocation ul) = glUniform2uiv ul
uniform3v (UniformLocation ul) = glUniform3uiv ul
uniform4v (UniformLocation ul) = glUniform4uiv ul
instance UniformComponent GLfloat where
uniform1 (UniformLocation ul) = glUniform1f ul
uniform2 (UniformLocation ul) = glUniform2f ul
uniform3 (UniformLocation ul) = glUniform3f ul
uniform4 (UniformLocation ul) = glUniform4f ul
getUniform p ul = glGetUniformfv p ul . castPtr
uniform1v (UniformLocation ul) = glUniform1fv ul
uniform2v (UniformLocation ul) = glUniform2fv ul
uniform3v (UniformLocation ul) = glUniform3fv ul
uniform4v (UniformLocation ul) = glUniform4fv ul
instance UniformComponent GLdouble where
uniform1 (UniformLocation ul) = glUniform1d ul
uniform2 (UniformLocation ul) = glUniform2d ul
uniform3 (UniformLocation ul) = glUniform3d ul
uniform4 (UniformLocation ul) = glUniform4d ul
getUniform p ul = glGetUniformdv p ul . castPtr
uniform1v (UniformLocation ul) = glUniform1dv ul
uniform2v (UniformLocation ul) = glUniform2dv ul
uniform3v (UniformLocation ul) = glUniform3dv ul
uniform4v (UniformLocation ul) = glUniform4dv ul
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 = allocaBytes maxUniformBufferSize $ \buf -> do
getUniformWith getUniform location buf
peek buf
single :: (UniformLocation -> StateVar (Vertex1 a))
-> (UniformLocation -> StateVar a)
single var location = makeStateVar (do Vertex1 x <- get (var location); return x)
(\x -> var location $= Vertex1 x)
instance Uniform GLfloat where
uniform = single uniform
uniformv = uniform1v
instance Uniform GLint where
uniform = single uniform
uniformv = uniform1v
instance Uniform GLuint where
uniform = single uniform
uniformv = uniform1v
instance Uniform GLdouble where
uniform = single uniform
uniformv = uniform1v
instance UniformComponent a => Uniform (Vertex1 a) where
uniform = makeUniformVar $ \location (Vertex1 x) -> uniform1 location x
uniformv location count = uniform1v location count . (castPtr :: Ptr (Vertex1 b) -> Ptr b)
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 (Vector1 a) where
uniform = makeUniformVar $ \location (Vector1 x) -> uniform1 location x
uniformv location count = uniform1v location count . (castPtr :: Ptr (Vector1 b) -> Ptr b)
instance UniformComponent a => Uniform (Vector2 a) where
uniform = makeUniformVar $ \location (Vector2 x y) -> uniform2 location x y
uniformv location count = uniform2v location count . (castPtr :: Ptr (Vector2 b) -> Ptr b)
instance UniformComponent a => Uniform (Vector3 a) where
uniform = makeUniformVar $ \location (Vector3 x y z) -> uniform3 location x y z
uniformv location count = uniform3v location count . (castPtr :: Ptr (Vector3 b) -> Ptr b)
instance UniformComponent a => Uniform (Vector4 a) where
uniform = makeUniformVar $ \location (Vector4 x y z w) -> uniform4 location x y z w
uniformv location count = uniform4v location count . (castPtr :: Ptr (Vector4 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)
instance Uniform TextureUnit where
uniform loc = makeStateVar getter setter
where getter = allocaBytes (sizeOf (undefined :: GLint)) $ \buf -> do
getUniformWith glGetUniformiv loc buf
fmap (TextureUnit . fromIntegral) $ peek buf
setter (TextureUnit tu) = uniform1 loc (fromIntegral tu :: GLint)
uniformv location count = uniform1v location count . (castPtr :: Ptr TextureUnit -> Ptr GLint)
instance MatrixComponent a => Uniform (GLmatrix a) where
uniform loc@(UniformLocation ul) = makeStateVar getter setter
where getter = withNewMatrix ColumnMajor $ getUniformWith getUniformv loc
setter m = withMatrix m $ uniformMatrix4v ul 1 . isRowMajor
uniformv (UniformLocation ul) count buf =
uniformMatrix4v ul count (marshalGLboolean False) (castPtr buf `asTypeOf` elemType buf)
where elemType = undefined :: MatrixComponent c => Ptr (GLmatrix c) -> Ptr c
isRowMajor :: MatrixOrder -> GLboolean
isRowMajor = marshalGLboolean . (RowMajor ==)
getUniformWith :: (GLuint -> GLint -> Ptr a -> IO ()) -> UniformLocation -> Ptr a -> IO ()
getUniformWith getter (UniformLocation ul) buf = do
program <- fmap (programID . fromJust) $ get currentProgram
getter program ul buf