module Linear.OpenGL.MatrixUniforms () where
import Data.Maybe (fromJust)
import Data.Proxy
import Foreign
import Graphics.Rendering.OpenGL.GL hiding (Proxy)
#if MIN_VERSION_OpenGLRaw(3,2,0)
import Graphics.GL.Core31
#else
import Graphics.Rendering.OpenGL.Raw.Core31
#endif
import Data.Distributive
import Linear
#if MIN_VERSION_OpenGLRaw(3,2,0)
gl_CURRENT_PROGRAM :: GLenum
gl_CURRENT_PROGRAM = GL_CURRENT_PROGRAM
#endif
maxComponentSize :: Int
maxComponentSize = sizeOf (undefined :: GLint) `max` sizeOf (undefined :: GLfloat)
maxNumComponents :: Int
maxNumComponents = 16
maxUniformBufferSize :: Int
maxUniformBufferSize = maxComponentSize * maxNumComponents
class UniformMatrix f where
setUniformMatrix :: Proxy (f (f a)) -> GLint -> GLsizei -> GLboolean -> Ptr GLfloat -> IO ()
instance UniformMatrix V2 where
setUniformMatrix _ = glUniformMatrix2fv
instance UniformMatrix V3 where
setUniformMatrix _ = glUniformMatrix3fv
instance UniformMatrix V4 where
setUniformMatrix _ = glUniformMatrix4fv
getInteger1 :: GLenum -> IO GLint
getInteger1 e = alloca $ \buf -> do
glGetIntegeri_v e 1 buf
peek buf
uniformMat :: forall f a.
( Storable (f (f a)), UniformMatrix f
, Distributive f, Conjugate a)
=> UniformLocation -> StateVar (f (f a))
uniformMat (UniformLocation loc) = makeStateVar getter setter
where
getter = do
p <- fromIntegral `fmap` getInteger1 gl_CURRENT_PROGRAM
allocaBytes maxUniformBufferSize $ \buf -> do
glGetUniformfv p loc (castPtr buf)
adjoint `fmap` peek buf
setter mat = do
program <- fmap fromJust $ get currentProgram
allocaBytes maxUniformBufferSize $ \buf -> do
poke buf (adjoint mat)
setUniformMatrix (Proxy :: Proxy (f (f a))) loc 1 0 (castPtr buf)
uniformvMat :: forall f a. UniformMatrix f
=> UniformLocation -> GLsizei -> Ptr (f (f a)) -> IO ()
uniformvMat (UniformLocation loc) count ptr =
setUniformMatrix (Proxy :: Proxy (f (f a))) loc count 0 (castPtr ptr)
instance Uniform (V2 (V2 GLfloat)) where
uniform = uniformMat
uniformv = uniformvMat
instance Uniform (V3 (V3 GLfloat)) where
uniform = uniformMat
uniformv = uniformvMat
instance Uniform (V4 (V4 GLfloat)) where
uniform = uniformMat
uniformv = uniformvMat