aboutsummaryrefslogtreecommitdiff
path: root/Spear/GL.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Spear/GL.hs')
-rw-r--r--Spear/GL.hs1449
1 files changed, 729 insertions, 720 deletions
diff --git a/Spear/GL.hs b/Spear/GL.hs
index b5b4dfb..f5cfe4e 100644
--- a/Spear/GL.hs
+++ b/Spear/GL.hs
@@ -1,720 +1,729 @@
1{-# LANGUAGE FlexibleInstances #-} 1{-# LANGUAGE FlexibleInstances #-}
2module Spear.GL 2module Spear.GL
3( 3(
4 -- * Programs 4 -- * Programs
5 GLSLProgram 5 GLSLProgram
6, newProgram 6, newProgram
7, linkProgram 7, linkProgram
8, useProgram 8, useProgram
9, unuseProgram 9, unuseProgram
10, withGLSLProgram 10, withGLSLProgram
11 -- ** Locations 11 -- ** Locations
12, attribLocation 12, attribLocation
13, fragLocation 13, fragLocation
14, uniformLocation 14, uniformLocation
15 -- ** Uniforms 15 -- ** Uniforms
16, Uniform(..) 16, Uniform(..)
17 -- * Shaders 17 -- * Shaders
18, GLSLShader 18, GLSLShader
19, ShaderType(..) 19, ShaderType(..)
20, attachShader 20, attachShader
21, detachShader 21, detachShader
22, loadShader 22, loadShader
23, newShader 23, newShader
24 -- ** Source loading 24 -- ** Source loading
25, loadSource 25, loadSource
26, shaderSource 26, shaderSource
27, readSource 27, readSource
28, compile 28, compile
29 -- * Helper functions 29 -- * Helper functions
30, ($=) 30, ($=)
31, Data.StateVar.get 31, Data.StateVar.get
32 -- * VAOs 32 -- * VAOs
33, VAO 33, VAO
34, newVAO 34, newVAO
35, bindVAO 35, bindVAO
36, unbindVAO 36, unbindVAO
37, enableVAOAttrib 37, enableVAOAttrib
38, attribVAOPointer 38, attribVAOPointer
39 -- ** Rendering 39 -- ** Rendering
40, drawArrays 40, drawArrays
41, drawElements 41, drawElements
42 -- * Buffers 42 -- * Buffers
43, GLBuffer 43, GLBuffer
44, TargetBuffer(..) 44, TargetBuffer(..)
45, BufferUsage(..) 45, BufferUsage(..)
46, newBuffer 46, newBuffer
47, bindBuffer 47, bindBuffer
48, unbindBuffer 48, unbindBuffer
49, BufferData(..) 49, BufferData(..)
50, bufferData' 50, bufferData'
51, withGLBuffer 51, withGLBuffer
52 -- * Textures 52 -- * Textures
53, Texture 53, Texture
54, SettableStateVar 54, SettableStateVar
55, ($) 55, ($)
56 -- ** Creation and destruction 56 -- ** Creation and destruction
57, newTexture 57, newTexture
58, loadTextureImage 58, loadTextureImage
59 -- ** Manipulation 59 -- ** Manipulation
60, bindTexture 60, bindTexture
61, unbindTexture 61, unbindTexture
62, loadTextureData 62, loadTextureData
63, texParami 63, texParami
64, texParamf 64, texParamf
65, activeTexture 65, activeTexture
66 -- * Error Handling 66 -- * Error Handling
67, getGLError 67, getGLError
68, printGLError 68, printGLError
69, assertGL 69, assertGL
70 -- * OpenGL 70 -- * OpenGL
71, module Graphics.Rendering.OpenGL.Raw.Core32 71, module Graphics.Rendering.OpenGL.Raw.Core32
72, Ptr 72, Ptr
73, nullPtr 73, nullPtr
74) 74)
75where 75where
76 76
77import Spear.Assets.Image 77import Spear.Assets.Image
78import Spear.Game 78import Spear.Game
79import Spear.Math.Matrix3 (Matrix3) 79import Spear.Math.Matrix3 (Matrix3)
80import Spear.Math.Matrix4 (Matrix4) 80import Spear.Math.Matrix4 (Matrix4)
81import Spear.Math.Vector 81import Spear.Math.Vector
82 82
83import Control.Monad 83import Control.Monad
84import Control.Monad.Trans.Class 84import Control.Monad.Trans.Class
85import Control.Monad.Trans.Error 85import Control.Monad.Trans.Error
86import Control.Monad.Trans.State as State 86import Control.Monad.Trans.State as State
87import qualified Data.ByteString.Char8 as B 87import qualified Data.ByteString.Char8 as B
88import Data.StateVar 88import Data.StateVar
89import Data.Word 89import Data.Word
90import Foreign.C.String 90import Foreign.C.String
91import Foreign.C.Types 91import Foreign.C.Types
92import Foreign.Ptr 92import Foreign.Ptr
93import Foreign.Storable 93import Foreign.Storable
94import Foreign.Marshal.Utils as Foreign (with) 94import Foreign.Marshal.Utils as Foreign (with)
95import Foreign.Marshal.Alloc (alloca) 95import Foreign.Marshal.Alloc (alloca)
96import Foreign.Marshal.Array (withArray) 96import Foreign.Marshal.Array (withArray)
97import Foreign.Storable (peek) 97import Foreign.Storable (peek)
98import Graphics.Rendering.OpenGL.Raw.Core32 98import Graphics.Rendering.OpenGL.Raw.Core32
99import System.Directory (doesFileExist, getCurrentDirectory, setCurrentDirectory) 99import System.Directory (doesFileExist, getCurrentDirectory, setCurrentDirectory)
100import System.IO (hPutStrLn, stderr) 100import System.IO (hPutStrLn, stderr)
101import Unsafe.Coerce 101import Unsafe.Coerce
102 102
103-- 103--
104-- MANAGEMENT 104-- MANAGEMENT
105-- 105--
106 106
107-- | A GLSL shader handle. 107-- | A GLSL shader handle.
108data GLSLShader = GLSLShader 108data GLSLShader = GLSLShader
109 { getShader :: GLuint 109 { getShader :: GLuint
110 , getShaderKey :: Resource 110 , getShaderKey :: Resource
111 } 111 }
112 112
113instance ResourceClass GLSLShader where 113instance ResourceClass GLSLShader where
114 getResource = getShaderKey 114 getResource = getShaderKey
115 115
116-- | A GLSL program handle. 116-- | A GLSL program handle.
117data GLSLProgram = GLSLProgram 117data GLSLProgram = GLSLProgram
118 { getProgram :: GLuint 118 { getProgram :: GLuint
119 , getProgramKey :: Resource 119 , getProgramKey :: Resource
120 } 120 }
121 121
122instance ResourceClass GLSLProgram where 122instance ResourceClass GLSLProgram where
123 getResource = getProgramKey 123 getResource = getProgramKey
124 124
125-- | Supported shader types. 125-- | Supported shader types.
126data ShaderType = VertexShader | FragmentShader | GeometryShader deriving (Eq, Show) 126data ShaderType = VertexShader | FragmentShader | GeometryShader deriving (Eq, Show)
127 127
128toGLShader :: ShaderType -> GLenum 128toGLShader :: ShaderType -> GLenum
129toGLShader VertexShader = gl_VERTEX_SHADER 129toGLShader VertexShader = gl_VERTEX_SHADER
130toGLShader FragmentShader = gl_FRAGMENT_SHADER 130toGLShader FragmentShader = gl_FRAGMENT_SHADER
131toGLShader GeometryShader = gl_GEOMETRY_SHADER 131toGLShader GeometryShader = gl_GEOMETRY_SHADER
132 132
133-- | Apply the given function to the program's id. 133-- | Apply the given function to the program's id.
134withGLSLProgram :: GLSLProgram -> (GLuint -> a) -> a 134withGLSLProgram :: GLSLProgram -> (GLuint -> a) -> a
135withGLSLProgram prog f = f $ getProgram prog 135withGLSLProgram prog f = f $ getProgram prog
136 136
137-- | Get the location of the given uniform variable within the given program. 137-- | Get the location of the given uniform variable within the given program.
138uniformLocation :: GLSLProgram -> String -> GettableStateVar GLint 138uniformLocation :: GLSLProgram -> String -> GettableStateVar GLint
139uniformLocation prog var = makeGettableStateVar $ 139uniformLocation prog var = makeGettableStateVar $
140 withCString var $ \str -> glGetUniformLocation (getProgram prog) (unsafeCoerce str) 140 withCString var $ \str -> glGetUniformLocation (getProgram prog) (unsafeCoerce str)
141 141
142-- | Get or set the location of the given variable to a fragment shader colour number. 142-- | Get or set the location of the given variable to a fragment shader colour number.
143fragLocation :: GLSLProgram -> String -> StateVar GLint 143fragLocation :: GLSLProgram -> String -> StateVar GLint
144fragLocation prog var = makeStateVar get set 144fragLocation prog var = makeStateVar get set
145 where 145 where
146 get = withCString var $ \str -> glGetFragDataLocation (getProgram prog) (unsafeCoerce str) 146 get = withCString var $ \str -> glGetFragDataLocation (getProgram prog) (unsafeCoerce str)
147 set idx = withCString var $ \str -> 147 set idx = withCString var $ \str ->
148 glBindFragDataLocation (getProgram prog) (unsafeCoerce idx) (unsafeCoerce str) 148 glBindFragDataLocation (getProgram prog) (unsafeCoerce idx) (unsafeCoerce str)
149 149
150-- | Get or set the location of the given attribute within the given program. 150-- | Get or set the location of the given attribute within the given program.
151attribLocation :: GLSLProgram -> String -> StateVar GLint 151attribLocation :: GLSLProgram -> String -> StateVar GLint
152attribLocation prog var = makeStateVar get set 152attribLocation prog var = makeStateVar get set
153 where 153 where
154 get = withCString var $ \str -> glGetAttribLocation (getProgram prog) (unsafeCoerce str) 154 get = withCString var $ \str -> glGetAttribLocation (getProgram prog) (unsafeCoerce str)
155 set idx = withCString var $ \str -> 155 set idx = withCString var $ \str ->
156 glBindAttribLocation (getProgram prog) (unsafeCoerce idx) (unsafeCoerce str) 156 glBindAttribLocation (getProgram prog) (unsafeCoerce idx) (unsafeCoerce str)
157 157
158-- | Create a new program. 158-- | Create a new program.
159newProgram :: [GLSLShader] -> Game s GLSLProgram 159newProgram :: [GLSLShader] -> Game s GLSLProgram
160newProgram shaders = do 160newProgram shaders = do
161 h <- gameIO glCreateProgram 161 h <- gameIO glCreateProgram
162 when (h == 0) $ gameError "glCreateProgram failed" 162 when (h == 0) $ gameError "glCreateProgram failed"
163 rkey <- register $ deleteProgram h 163 rkey <- register $ deleteProgram h
164 let program = GLSLProgram h rkey 164 let program = GLSLProgram h rkey
165 mapM_ (gameIO . attachShader program) shaders 165 mapM_ (gameIO . attachShader program) shaders
166 linkProgram program 166 linkProgram program
167 return program 167 return program
168 168
169-- Delete the program. 169-- Delete the program.
170deleteProgram :: GLuint -> IO () 170deleteProgram :: GLuint -> IO ()
171--deleteProgram = glDeleteProgram 171--deleteProgram = glDeleteProgram
172deleteProgram prog = do 172deleteProgram prog = do
173 putStrLn $ "Deleting shader program " ++ show prog 173 putStrLn $ "Deleting shader program " ++ show prog
174 glDeleteProgram prog 174 glDeleteProgram prog
175 175
176-- | Link the program. 176-- | Link the program.
177linkProgram :: GLSLProgram -> Game s () 177linkProgram :: GLSLProgram -> Game s ()
178linkProgram prog = do 178linkProgram prog = do
179 let h = getProgram prog 179 let h = getProgram prog
180 err <- gameIO $ do 180 err <- gameIO $ do
181 glLinkProgram h 181 glLinkProgram h
182 alloca $ \statptr -> do 182 alloca $ \statptr -> do
183 glGetProgramiv h gl_LINK_STATUS statptr 183 glGetProgramiv h gl_LINK_STATUS statptr
184 status <- peek statptr 184 status <- peek statptr
185 case status of 185 case status of
186 0 -> getStatus glGetProgramiv glGetProgramInfoLog h 186 0 -> getStatus glGetProgramiv glGetProgramInfoLog h
187 _ -> return "" 187 _ -> return ""
188 188
189 case length err of 189 case length err of
190 0 -> return () 190 0 -> return ()
191 _ -> gameError err 191 _ -> gameError err
192 192
193-- | Use the program. 193-- | Use the program.
194useProgram :: GLSLProgram -> IO () 194useProgram :: GLSLProgram -> IO ()
195useProgram prog = glUseProgram $ getProgram prog 195useProgram prog = glUseProgram $ getProgram prog
196 196
197-- | Deactivate the active program. 197-- | Deactivate the active program.
198unuseProgram :: IO () 198unuseProgram :: IO ()
199unuseProgram = glUseProgram 0 199unuseProgram = glUseProgram 0
200 200
201-- | Attach the given shader to the given program. 201-- | Attach the given shader to the given program.
202attachShader :: GLSLProgram -> GLSLShader -> IO () 202attachShader :: GLSLProgram -> GLSLShader -> IO ()
203attachShader prog shader = glAttachShader (getProgram prog) (getShader shader) 203attachShader prog shader = glAttachShader (getProgram prog) (getShader shader)
204 204
205-- | Detach the given GLSL from the given program. 205-- | Detach the given GLSL from the given program.
206detachShader :: GLSLProgram -> GLSLShader -> IO () 206detachShader :: GLSLProgram -> GLSLShader -> IO ()
207detachShader prog shader = glDetachShader (getProgram prog) (getShader shader) 207detachShader prog shader = glDetachShader (getProgram prog) (getShader shader)
208 208
209-- | Load a shader from the file specified by the given string. 209-- | Load a shader from the file specified by the given string.
210-- 210--
211-- This function creates a new shader. To load source code into an existing shader, 211-- This function creates a new shader. To load source code into an existing shader,
212-- see 'loadSource', 'shaderSource' and 'readSource'. 212-- see 'loadSource', 'shaderSource' and 'readSource'.
213loadShader :: ShaderType -> FilePath -> Game s GLSLShader 213loadShader :: ShaderType -> FilePath -> Game s GLSLShader
214loadShader shaderType file = do 214loadShader shaderType file = do
215 shader <- newShader shaderType 215 shader <- newShader shaderType
216 loadSource file shader 216 loadSource file shader
217 compile file shader 217 compile file shader
218 return shader 218 return shader
219 219
220-- | Create a new shader. 220-- | Create a new shader.
221newShader :: ShaderType -> Game s GLSLShader 221newShader :: ShaderType -> Game s GLSLShader
222newShader shaderType = do 222newShader shaderType = do
223 h <- gameIO $ glCreateShader (toGLShader shaderType) 223 h <- gameIO $ glCreateShader (toGLShader shaderType)
224 case h of 224 case h of
225 0 -> gameError "glCreateShader failed" 225 0 -> gameError "glCreateShader failed"
226 _ -> do 226 _ -> do
227 rkey <- register $ deleteShader h 227 rkey <- register $ deleteShader h
228 return $ GLSLShader h rkey 228 return $ GLSLShader h rkey
229 229
230-- | Free the shader. 230-- | Free the shader.
231deleteShader :: GLuint -> IO () 231deleteShader :: GLuint -> IO ()
232--deleteShader = glDeleteShader 232--deleteShader = glDeleteShader
233deleteShader shader = do 233deleteShader shader = do
234 putStrLn $ "Deleting shader " ++ show shader 234 putStrLn $ "Deleting shader " ++ show shader
235 glDeleteShader shader 235 glDeleteShader shader
236 236
237-- | Load a shader source from the file specified by the given string 237-- | Load a shader source from the file specified by the given string
238-- into the shader. 238-- into the shader.
239loadSource :: FilePath -> GLSLShader -> Game s () 239loadSource :: FilePath -> GLSLShader -> Game s ()
240loadSource file h = do 240loadSource file h = do
241 exists <- gameIO $ doesFileExist file 241 exists <- gameIO $ doesFileExist file
242 case exists of 242 case exists of
243 False -> gameError "the specified shader file does not exist" 243 False -> gameError "the specified shader file does not exist"
244 True -> gameIO $ do 244 True -> gameIO $ do
245 code <- readSource file 245 code <- readSource file
246 withCString code $ shaderSource h 246 withCString code $ shaderSource h
247 247
248-- | Load the given shader source into the shader. 248-- | Load the given shader source into the shader.
249shaderSource :: GLSLShader -> CString -> IO () 249shaderSource :: GLSLShader -> CString -> IO ()
250shaderSource shader str = 250shaderSource shader str =
251 let ptr = unsafeCoerce str 251 let ptr = unsafeCoerce str
252 in withArray [ptr] $ flip (glShaderSource (getShader shader) 1) nullPtr 252 in withArray [ptr] $ flip (glShaderSource (getShader shader) 1) nullPtr
253 253
254-- | Compile the shader. 254-- | Compile the shader.
255compile :: FilePath -> GLSLShader -> Game s () 255compile :: FilePath -> GLSLShader -> Game s ()
256compile file shader = do 256compile file shader = do
257 let h = getShader shader 257 let h = getShader shader
258 258
259 -- Compile 259 -- Compile
260 gameIO $ glCompileShader h 260 gameIO $ glCompileShader h
261 261
262 -- Verify status 262 -- Verify status
263 err <- gameIO $ alloca $ \statusPtr -> do 263 err <- gameIO $ alloca $ \statusPtr -> do
264 glGetShaderiv h gl_COMPILE_STATUS statusPtr 264 glGetShaderiv h gl_COMPILE_STATUS statusPtr
265 result <- peek statusPtr 265 result <- peek statusPtr
266 case result of 266 case result of
267 0 -> getStatus glGetShaderiv glGetShaderInfoLog h 267 0 -> getStatus glGetShaderiv glGetShaderInfoLog h
268 _ -> return "" 268 _ -> return ""
269 269
270 case length err of 270 case length err of
271 0 -> return () 271 0 -> return ()
272 _ -> gameError $ "Unable to compile shader " ++ file ++ ":\n" ++ err 272 _ -> gameError $ "Unable to compile shader " ++ file ++ ":\n" ++ err
273 273
274type StatusCall = GLuint -> GLenum -> Ptr GLint -> IO () 274type StatusCall = GLuint -> GLenum -> Ptr GLint -> IO ()
275type LogCall = GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO () 275type LogCall = GLuint -> GLsizei -> Ptr GLsizei -> Ptr GLchar -> IO ()
276 276
277getStatus :: StatusCall -> LogCall -> GLuint -> IO String 277getStatus :: StatusCall -> LogCall -> GLuint -> IO String
278getStatus getStatus getLog h = do 278getStatus getStatus getLog h = do
279 alloca $ \lenPtr -> do 279 alloca $ \lenPtr -> do
280 getStatus h gl_INFO_LOG_LENGTH lenPtr 280 getStatus h gl_INFO_LOG_LENGTH lenPtr
281 len <- peek lenPtr 281 len <- peek lenPtr
282 case len of 282 case len of
283 0 -> return "" 283 0 -> return ""
284 _ -> withCString (replicate (unsafeCoerce len) '\0') $ getErrorString getLog h (unsafeCoerce len) 284 _ -> withCString (replicate (unsafeCoerce len) '\0') $ getErrorString getLog h (unsafeCoerce len)
285 285
286getErrorString :: LogCall -> GLuint -> GLsizei -> CString -> IO String 286getErrorString :: LogCall -> GLuint -> GLsizei -> CString -> IO String
287getErrorString getLog h len str = do 287getErrorString getLog h len str = do
288 let ptr = unsafeCoerce str 288 let ptr = unsafeCoerce str
289 getLog h len nullPtr ptr 289 getLog h len nullPtr ptr
290 peekCString str 290 peekCString str
291 291
292-- | Load the shader source specified by the given file. 292-- | Load the shader source specified by the given file.
293-- 293--
294-- This function implements an #include mechanism, so the given file can 294-- This function implements an #include mechanism, so the given file can
295-- refer to other files. 295-- refer to other files.
296readSource :: FilePath -> IO String 296readSource :: FilePath -> IO String
297readSource = fmap B.unpack . readSource' 297readSource = fmap B.unpack . readSource'
298 298
299readSource' :: FilePath -> IO B.ByteString 299readSource' :: FilePath -> IO B.ByteString
300readSource' file = do 300readSource' file = do
301 let includeB = B.pack "#include" 301 let includeB = B.pack "#include"
302 newLineB = B.pack "\n" 302 newLineB = B.pack "\n"
303 isInclude = ((==) includeB) . B.take 8 303 isInclude = ((==) includeB) . B.take 8
304 clean = B.dropWhile (\c -> c == ' ') 304 clean = B.dropWhile (\c -> c == ' ')
305 cleanInclude = B.filter (\c -> c /= '"') . B.dropWhile (\c -> c /= ' ') 305 cleanInclude = B.filter (\c -> c /= '"') . B.dropWhile (\c -> c /= ' ')
306 toLines = B.splitWith (\c -> c == '\n' || c == '\r') 306 toLines = B.splitWith (\c -> c == '\n' || c == '\r')
307 addNewLine s = if (B.last s /= '\n') then B.append s newLineB else s 307 addNewLine s = if (B.last s /= '\n') then B.append s newLineB else s
308 parse = fmap B.concat . (fmap . fmap $ flip B.append newLineB) . sequence . 308 parse = fmap B.concat . (fmap . fmap $ flip B.append newLineB) . sequence .
309 fmap (processLine . clean) . toLines 309 fmap (processLine . clean) . toLines
310 processLine l = 310 processLine l =
311 if isInclude l 311 if isInclude l
312 then readSource' $ B.unpack . clean . cleanInclude $ l 312 then readSource' $ B.unpack . clean . cleanInclude $ l
313 else return l 313 else return l
314 314
315 contents <- B.readFile file 315 contents <- B.readFile file
316 316
317 dir <- getCurrentDirectory 317 dir <- getCurrentDirectory
318 let dir' = dir ++ "/" ++ (reverse . dropWhile (\c -> c /= '/') . reverse) file 318 let dir' = dir ++ "/" ++ (reverse . dropWhile (\c -> c /= '/') . reverse) file
319 319
320 setCurrentDirectory dir' 320 setCurrentDirectory dir'
321 code <- parse contents 321 code <- parse contents
322 setCurrentDirectory dir 322 setCurrentDirectory dir
323 323
324 return code 324 return code
325 325
326class Uniform a where 326class Uniform a where
327 -- | Load a list of uniform values. 327 -- | Load a list of uniform values.
328 uniform :: GLint -> a -> IO () 328 uniform :: GLint -> a -> IO ()
329 329
330instance Uniform Int where uniform loc a = glUniform1i loc (fromIntegral a) 330instance Uniform Int where uniform loc a = glUniform1i loc (fromIntegral a)
331instance Uniform Float where uniform loc a = glUniform1f loc (unsafeCoerce a) 331instance Uniform Float where uniform loc a = glUniform1f loc (unsafeCoerce a)
332 332instance Uniform CFloat where uniform loc a = glUniform1f loc a
333instance Uniform (Int,Int) where 333
334 uniform loc (x,y) = glUniform2i loc (fromIntegral x) (fromIntegral y) 334instance Uniform (Int,Int) where
335 335 uniform loc (x,y) = glUniform2i loc (fromIntegral x) (fromIntegral y)
336instance Uniform (Float,Float) where 336
337 uniform loc (x,y) = glUniform2f loc (unsafeCoerce x) (unsafeCoerce y) 337instance Uniform (Float,Float) where
338 338 uniform loc (x,y) = glUniform2f loc (unsafeCoerce x) (unsafeCoerce y)
339instance Uniform (Int,Int,Int) where 339
340 uniform loc (x,y,z) = glUniform3i loc (fromIntegral x) (fromIntegral y) (fromIntegral z) 340instance Uniform (Int,Int,Int) where
341 341 uniform loc (x,y,z) = glUniform3i loc (fromIntegral x) (fromIntegral y) (fromIntegral z)
342instance Uniform (Float,Float,Float) where 342
343 uniform loc (x,y,z) = glUniform3f loc (unsafeCoerce x) (unsafeCoerce y) (unsafeCoerce z) 343instance Uniform (Float,Float,Float) where
344 344 uniform loc (x,y,z) = glUniform3f loc (unsafeCoerce x) (unsafeCoerce y) (unsafeCoerce z)
345instance Uniform (Int,Int,Int,Int) where 345
346 uniform loc (x,y,z,w) = glUniform4i loc 346instance Uniform (Int,Int,Int,Int) where
347 (fromIntegral x) (fromIntegral y) (fromIntegral z) (fromIntegral w) 347 uniform loc (x,y,z,w) = glUniform4i loc
348 348 (fromIntegral x) (fromIntegral y) (fromIntegral z) (fromIntegral w)
349instance Uniform (Float,Float,Float,Float) where 349
350 uniform loc (x,y,z,w) = glUniform4f loc 350instance Uniform (Float,Float,Float,Float) where
351 (unsafeCoerce x) (unsafeCoerce y) (unsafeCoerce z) (unsafeCoerce w) 351 uniform loc (x,y,z,w) = glUniform4f loc
352 352 (unsafeCoerce x) (unsafeCoerce y) (unsafeCoerce z) (unsafeCoerce w)
353instance Uniform Vector2 where 353
354 uniform loc v = glUniform2f loc x' y' 354instance Uniform Vector2 where
355 where x' = unsafeCoerce $ x v 355 uniform loc v = glUniform2f loc x' y'
356 y' = unsafeCoerce $ y v 356 where x' = unsafeCoerce $ x v
357 357 y' = unsafeCoerce $ y v
358instance Uniform Vector3 where 358
359 uniform loc v = glUniform3f loc x' y' z' 359instance Uniform Vector3 where
360 where x' = unsafeCoerce $ x v 360 uniform loc v = glUniform3f loc x' y' z'
361 y' = unsafeCoerce $ y v 361 where x' = unsafeCoerce $ x v
362 z' = unsafeCoerce $ z v 362 y' = unsafeCoerce $ y v
363 363 z' = unsafeCoerce $ z v
364instance Uniform Vector4 where 364
365 uniform loc v = glUniform4f loc x' y' z' w' 365instance Uniform Vector4 where
366 where x' = unsafeCoerce $ x v 366 uniform loc v = glUniform4f loc x' y' z' w'
367 y' = unsafeCoerce $ y v 367 where x' = unsafeCoerce $ x v
368 z' = unsafeCoerce $ z v 368 y' = unsafeCoerce $ y v
369 w' = unsafeCoerce $ w v 369 z' = unsafeCoerce $ z v
370 370 w' = unsafeCoerce $ w v
371instance Uniform Matrix3 where 371
372 uniform loc mat = 372instance Uniform Matrix3 where
373 with mat $ \ptrMat -> 373 uniform loc mat =
374 glUniformMatrix3fv loc 1 (toEnum 0) (unsafeCoerce ptrMat) 374 with mat $ \ptrMat ->
375 375 glUniformMatrix3fv loc 1 (toEnum 0) (unsafeCoerce ptrMat)
376instance Uniform Matrix4 where 376
377 uniform loc mat = 377instance Uniform Matrix4 where
378 with mat $ \ptrMat -> 378 uniform loc mat =
379 glUniformMatrix4fv loc 1 (toEnum 0) (unsafeCoerce ptrMat) 379 with mat $ \ptrMat ->
380 380 glUniformMatrix4fv loc 1 (toEnum 0) (unsafeCoerce ptrMat)
381instance Uniform [Float] where 381
382 uniform loc vals = withArray (map unsafeCoerce vals) $ \ptr -> 382instance Uniform [Float] where
383 case length vals of 383 uniform loc vals = withArray (map unsafeCoerce vals) $ \ptr ->
384 1 -> glUniform1fv loc 1 ptr 384 case length vals of
385 2 -> glUniform2fv loc 1 ptr 385 1 -> glUniform1fv loc 1 ptr
386 3 -> glUniform3fv loc 1 ptr 386 2 -> glUniform2fv loc 1 ptr
387 4 -> glUniform4fv loc 1 ptr 387 3 -> glUniform3fv loc 1 ptr
388 388 4 -> glUniform4fv loc 1 ptr
389instance Uniform [Int] where 389
390 uniform loc vals = withArray (map fromIntegral vals) $ \ptr -> 390instance Uniform [CFloat] where
391 case length vals of 391 uniform loc vals = withArray vals $ \ptr ->
392 1 -> glUniform1iv loc 1 ptr 392 case length vals of
393 2 -> glUniform2iv loc 1 ptr 393 1 -> glUniform1fv loc 1 ptr
394 3 -> glUniform3iv loc 1 ptr 394 2 -> glUniform2fv loc 1 ptr
395 4 -> glUniform4iv loc 1 ptr 395 3 -> glUniform3fv loc 1 ptr
396 396 4 -> glUniform4fv loc 1 ptr
397-- 397
398-- VAOs 398instance Uniform [Int] where
399-- 399 uniform loc vals = withArray (map fromIntegral vals) $ \ptr ->
400 400 case length vals of
401-- | A vertex array object. 401 1 -> glUniform1iv loc 1 ptr
402data VAO = VAO 402 2 -> glUniform2iv loc 1 ptr
403 { getVAO :: GLuint 403 3 -> glUniform3iv loc 1 ptr
404 , vaoKey :: Resource 404 4 -> glUniform4iv loc 1 ptr
405 } 405
406 406--
407instance ResourceClass VAO where 407-- VAOs
408 getResource = vaoKey 408--
409 409
410instance Eq VAO where 410-- | A vertex array object.
411 vao1 == vao2 = getVAO vao1 == getVAO vao2 411data VAO = VAO
412 412 { getVAO :: GLuint
413instance Ord VAO where 413 , vaoKey :: Resource
414 vao1 < vao2 = getVAO vao1 < getVAO vao2 414 }
415 415
416-- | Create a new vao. 416instance ResourceClass VAO where
417newVAO :: Game s VAO 417 getResource = vaoKey
418newVAO = do 418
419 h <- gameIO . alloca $ \ptr -> do 419instance Eq VAO where
420 glGenVertexArrays 1 ptr 420 vao1 == vao2 = getVAO vao1 == getVAO vao2
421 peek ptr 421
422 422instance Ord VAO where
423 rkey <- register $ deleteVAO h 423 vao1 < vao2 = getVAO vao1 < getVAO vao2
424 return $ VAO h rkey 424
425 425-- | Create a new vao.
426-- | Delete the vao. 426newVAO :: Game s VAO
427deleteVAO :: GLuint -> IO () 427newVAO = do
428deleteVAO vao = Foreign.with vao $ glDeleteVertexArrays 1 428 h <- gameIO . alloca $ \ptr -> do
429 429 glGenVertexArrays 1 ptr
430-- | Bind the vao. 430 peek ptr
431bindVAO :: VAO -> IO () 431
432bindVAO = glBindVertexArray . getVAO 432 rkey <- register $ deleteVAO h
433 433 return $ VAO h rkey
434-- | Unbind the bound vao. 434
435unbindVAO :: IO () 435-- | Delete the vao.
436unbindVAO = glBindVertexArray 0 436deleteVAO :: GLuint -> IO ()
437 437deleteVAO vao = Foreign.with vao $ glDeleteVertexArrays 1
438-- | Enable the given vertex attribute of the bound vao. 438
439-- 439-- | Bind the vao.
440-- See also 'bindVAO'. 440bindVAO :: VAO -> IO ()
441enableVAOAttrib :: GLuint -- ^ Attribute index. 441bindVAO = glBindVertexArray . getVAO
442 -> IO () 442
443enableVAOAttrib = glEnableVertexAttribArray 443-- | Unbind the bound vao.
444 444unbindVAO :: IO ()
445-- | Bind the bound buffer to the given point. 445unbindVAO = glBindVertexArray 0
446attribVAOPointer 446
447 :: GLuint -- ^ The index of the generic vertex attribute to be modified. 447-- | Enable the given vertex attribute of the bound vao.
448 -> GLint -- ^ The number of components per generic vertex attribute. Must be 1,2,3,4. 448--
449 -> GLenum -- ^ The data type of each component in the array. 449-- See also 'bindVAO'.
450 -> Bool -- ^ Whether fixed-point data values should be normalized. 450enableVAOAttrib :: GLuint -- ^ Attribute index.
451 -> GLsizei -- ^ Stride. Byte offset between consecutive generic vertex attributes. 451 -> IO ()
452 -> Int -- ^ Offset to the first component in the array. 452enableVAOAttrib = glEnableVertexAttribArray
453 -> IO () 453
454attribVAOPointer idx ncomp dattype normalise stride off = 454-- | Bind the bound buffer to the given point.
455 glVertexAttribPointer idx ncomp dattype normalise' stride (unsafeCoerce off) 455attribVAOPointer
456 where normalise' = if normalise then 1 else 0 456 :: GLuint -- ^ The index of the generic vertex attribute to be modified.
457 457 -> GLint -- ^ The number of components per generic vertex attribute. Must be 1,2,3,4.
458-- | Draw the bound vao. 458 -> GLenum -- ^ The data type of each component in the array.
459drawArrays 459 -> Bool -- ^ Whether fixed-point data values should be normalized.
460 :: GLenum -- ^ The kind of primitives to render. 460 -> GLsizei -- ^ Stride. Byte offset between consecutive generic vertex attributes.
461 -> Int -- ^ Starting index in the enabled arrays. 461 -> Int -- ^ Offset to the first component in the array.
462 -> Int -- ^ The number of indices to be rendered. 462 -> IO ()
463 -> IO () 463attribVAOPointer idx ncomp dattype normalise stride off =
464drawArrays mode first count = glDrawArrays mode (unsafeCoerce first) (unsafeCoerce count) 464 glVertexAttribPointer idx ncomp dattype normalise' stride (unsafeCoerce off)
465 465 where normalise' = if normalise then 1 else 0
466-- | Draw the bound vao, indexed mode. 466
467drawElements 467-- | Draw the bound vao.
468 :: GLenum -- ^ The kind of primitives to render. 468drawArrays
469 -> Int -- ^ The number of elements to be rendered. 469 :: GLenum -- ^ The kind of primitives to render.
470 -> GLenum -- ^ The type of the index values. Must be one of gl_UNSIGNED_BYTE, gl_UNSIGNED_SHORT, or gl_UNSIGNED_INT. 470 -> Int -- ^ Starting index in the enabled arrays.
471 -> Ptr a -- ^ Pointer to the location where indices are stored, or offset into the index array when there is a bound ElementArrayBuffer. 471 -> Int -- ^ The number of indices to be rendered.
472 -> IO () 472 -> IO ()
473drawElements mode count t idxs = glDrawElements mode (unsafeCoerce count) t idxs 473drawArrays mode first count = glDrawArrays mode (unsafeCoerce first) (unsafeCoerce count)
474 474
475-- 475-- | Draw the bound vao, indexed mode.
476-- BUFFER 476drawElements
477-- 477 :: GLenum -- ^ The kind of primitives to render.
478 478 -> Int -- ^ The number of elements to be rendered.
479-- | An OpenGL buffer. 479 -> GLenum -- ^ The type of the index values. Must be one of gl_UNSIGNED_BYTE, gl_UNSIGNED_SHORT, or gl_UNSIGNED_INT.
480data GLBuffer = GLBuffer 480 -> Ptr a -- ^ Pointer to the location where indices are stored, or offset into the index array when there is a bound ElementArrayBuffer.
481 { getBuffer :: GLuint 481 -> IO ()
482 , rkey :: Resource 482drawElements mode count t idxs = glDrawElements mode (unsafeCoerce count) t idxs
483 } 483
484 484--
485instance ResourceClass GLBuffer where 485-- BUFFER
486 getResource = rkey 486--
487 487
488-- | The type of target buffer. 488-- | An OpenGL buffer.
489data TargetBuffer 489data GLBuffer = GLBuffer
490 = ArrayBuffer 490 { getBuffer :: GLuint
491 | ElementArrayBuffer 491 , rkey :: Resource
492 | PixelPackBuffer 492 }
493 | PixelUnpackBuffer 493
494 deriving (Eq, Show) 494instance ResourceClass GLBuffer where
495 495 getResource = rkey
496fromTarget :: TargetBuffer -> GLenum 496
497fromTarget ArrayBuffer = gl_ARRAY_BUFFER 497-- | The type of target buffer.
498fromTarget ElementArrayBuffer = gl_ELEMENT_ARRAY_BUFFER 498data TargetBuffer
499fromTarget PixelPackBuffer = gl_PIXEL_PACK_BUFFER 499 = ArrayBuffer
500fromTarget PixelUnpackBuffer = gl_PIXEL_UNPACK_BUFFER 500 | ElementArrayBuffer
501 501 | PixelPackBuffer
502-- | A buffer usage. 502 | PixelUnpackBuffer
503data BufferUsage 503 deriving (Eq, Show)
504 = StreamDraw 504
505 | StreamRead 505fromTarget :: TargetBuffer -> GLenum
506 | StreamCopy 506fromTarget ArrayBuffer = gl_ARRAY_BUFFER
507 | StaticDraw 507fromTarget ElementArrayBuffer = gl_ELEMENT_ARRAY_BUFFER
508 | StaticRead 508fromTarget PixelPackBuffer = gl_PIXEL_PACK_BUFFER
509 | StaticCopy 509fromTarget PixelUnpackBuffer = gl_PIXEL_UNPACK_BUFFER
510 | DynamicDraw 510
511 | DynamicRead 511-- | A buffer usage.
512 | DynamicCopy 512data BufferUsage
513 deriving (Eq, Show) 513 = StreamDraw
514 514 | StreamRead
515fromUsage :: BufferUsage -> GLenum 515 | StreamCopy
516fromUsage StreamDraw = gl_STREAM_DRAW 516 | StaticDraw
517fromUsage StreamRead = gl_STREAM_READ 517 | StaticRead
518fromUsage StreamCopy = gl_STREAM_COPY 518 | StaticCopy
519fromUsage StaticDraw = gl_STATIC_DRAW 519 | DynamicDraw
520fromUsage StaticRead = gl_STATIC_READ 520 | DynamicRead
521fromUsage StaticCopy = gl_STATIC_COPY 521 | DynamicCopy
522fromUsage DynamicDraw = gl_DYNAMIC_DRAW 522 deriving (Eq, Show)
523fromUsage DynamicRead = gl_DYNAMIC_READ 523
524fromUsage DynamicCopy = gl_DYNAMIC_COPY 524fromUsage :: BufferUsage -> GLenum
525 525fromUsage StreamDraw = gl_STREAM_DRAW
526-- | Create a new buffer. 526fromUsage StreamRead = gl_STREAM_READ
527newBuffer :: Game s GLBuffer 527fromUsage StreamCopy = gl_STREAM_COPY
528newBuffer = do 528fromUsage StaticDraw = gl_STATIC_DRAW
529 h <- gameIO . alloca $ \ptr -> do 529fromUsage StaticRead = gl_STATIC_READ
530 glGenBuffers 1 ptr 530fromUsage StaticCopy = gl_STATIC_COPY
531 peek ptr 531fromUsage DynamicDraw = gl_DYNAMIC_DRAW
532 532fromUsage DynamicRead = gl_DYNAMIC_READ
533 rkey <- register $ deleteBuffer h 533fromUsage DynamicCopy = gl_DYNAMIC_COPY
534 return $ GLBuffer h rkey 534
535 535-- | Create a new buffer.
536-- | Delete the buffer. 536newBuffer :: Game s GLBuffer
537deleteBuffer :: GLuint -> IO () 537newBuffer = do
538deleteBuffer buf = Foreign.with buf $ glDeleteBuffers 1 538 h <- gameIO . alloca $ \ptr -> do
539 539 glGenBuffers 1 ptr
540-- | Bind the buffer. 540 peek ptr
541bindBuffer :: GLBuffer -> TargetBuffer -> IO () 541
542bindBuffer buf target = glBindBuffer (fromTarget target) $ getBuffer buf 542 rkey <- register $ deleteBuffer h
543 543 return $ GLBuffer h rkey
544-- | Unbind the bound buffer. 544
545unbindBuffer :: TargetBuffer -> IO () 545-- | Delete the buffer.
546unbindBuffer target = glBindBuffer (fromTarget target) 0 546deleteBuffer :: GLuint -> IO ()
547 547deleteBuffer buf = Foreign.with buf $ glDeleteBuffers 1
548class Storable a => BufferData a where 548
549 -- | Set the buffer's data. 549-- | Bind the buffer.
550 bufferData :: TargetBuffer -> [a] -> BufferUsage -> IO () 550bindBuffer :: TargetBuffer -> GLBuffer -> IO ()
551 bufferData tgt vals usage = 551bindBuffer target buf = glBindBuffer (fromTarget target) $ getBuffer buf
552 let n = sizeOf (head vals) * length vals 552
553 in withArray vals $ \ptr -> bufferData' tgt n ptr usage 553-- | Unbind the bound buffer.
554 554unbindBuffer :: TargetBuffer -> IO ()
555instance BufferData Word8 555unbindBuffer target = glBindBuffer (fromTarget target) 0
556instance BufferData Word16 556
557instance BufferData Word32 557class Storable a => BufferData a where
558instance BufferData CChar 558 -- | Set the buffer's data.
559instance BufferData CInt 559 bufferData :: TargetBuffer -> [a] -> BufferUsage -> IO ()
560instance BufferData CFloat 560 bufferData tgt vals usage =
561instance BufferData CDouble 561 let n = sizeOf (head vals) * length vals
562instance BufferData Int 562 in withArray vals $ \ptr -> bufferData' tgt n ptr usage
563instance BufferData Float 563
564instance BufferData Double 564instance BufferData Word8
565 565instance BufferData Word16
566{-bufferData :: Storable a 566instance BufferData Word32
567 => TargetBuffer 567instance BufferData CChar
568 -> Int -- ^ The size in bytes of an element in the data list. 568instance BufferData CInt
569 -> [a] -- ^ The data list. 569instance BufferData CFloat
570 -> BufferUsage 570instance BufferData CDouble
571 -> IO () 571instance BufferData Int
572bufferData target n bufData usage = withArray bufData $ 572instance BufferData Float
573 \ptr -> bufferData target (n * length bufData) ptr usage-} 573instance BufferData Double
574 574
575-- | Set the buffer's data. 575{-bufferData :: Storable a
576bufferData' :: TargetBuffer 576 => TargetBuffer
577 -> Int -- ^ Buffer size in bytes. 577 -> Int -- ^ The size in bytes of an element in the data list.
578 -> Ptr a 578 -> [a] -- ^ The data list.
579 -> BufferUsage 579 -> BufferUsage
580 -> IO () 580 -> IO ()
581bufferData' target n bufData usage = glBufferData (fromTarget target) (unsafeCoerce n) bufData (fromUsage usage) 581bufferData target n bufData usage = withArray bufData $
582 582 \ptr -> bufferData target (n * length bufData) ptr usage-}
583-- | Apply the given function the buffer's id. 583
584withGLBuffer :: GLBuffer -> (GLuint -> a) -> a 584-- | Set the buffer's data.
585withGLBuffer buf f = f $ getBuffer buf 585bufferData' :: TargetBuffer
586 586 -> Int -- ^ Buffer size in bytes.
587-- 587 -> Ptr a
588-- TEXTURE 588 -> BufferUsage
589-- 589 -> IO ()
590 590bufferData' target n bufData usage = glBufferData (fromTarget target) (unsafeCoerce n) bufData (fromUsage usage)
591-- | Represents a texture resource. 591
592data Texture = Texture 592-- | Apply the given function the buffer's id.
593 { getTex :: GLuint 593withGLBuffer :: GLBuffer -> (GLuint -> a) -> a
594 , texKey :: Resource 594withGLBuffer buf f = f $ getBuffer buf
595 } 595
596 596--
597instance Eq Texture where 597-- TEXTURE
598 t1 == t2 = getTex t1 == getTex t2 598--
599 599
600instance Ord Texture where 600-- | Represents a texture resource.
601 t1 < t2 = getTex t1 < getTex t2 601data Texture = Texture
602 602 { getTex :: GLuint
603instance ResourceClass Texture where 603 , texKey :: Resource
604 getResource = texKey 604 }
605 605
606-- | Create a new texture. 606instance Eq Texture where
607newTexture :: Game s Texture 607 t1 == t2 = getTex t1 == getTex t2
608newTexture = do 608
609 tex <- gameIO . alloca $ \ptr -> do 609instance Ord Texture where
610 glGenTextures 1 ptr 610 t1 < t2 = getTex t1 < getTex t2
611 peek ptr 611
612 612instance ResourceClass Texture where
613 rkey <- register $ deleteTexture tex 613 getResource = texKey
614 return $ Texture tex rkey 614
615 615-- | Create a new texture.
616-- | Delete the texture. 616newTexture :: Game s Texture
617deleteTexture :: GLuint -> IO () 617newTexture = do
618--deleteTexture tex = with tex $ glDeleteTextures 1 618 tex <- gameIO . alloca $ \ptr -> do
619deleteTexture tex = do 619 glGenTextures 1 ptr
620 putStrLn $ "Releasing texture " ++ show tex 620 peek ptr
621 with tex $ glDeleteTextures 1 621
622 622 rkey <- register $ deleteTexture tex
623-- | Load the 'Texture' specified by the given file. 623 return $ Texture tex rkey
624loadTextureImage :: FilePath 624
625 -> GLenum -- ^ Texture's min filter. 625-- | Delete the texture.
626 -> GLenum -- ^ Texture's mag filter. 626deleteTexture :: GLuint -> IO ()
627 -> Game s Texture 627--deleteTexture tex = with tex $ glDeleteTextures 1
628loadTextureImage file minFilter magFilter = do 628deleteTexture tex = do
629 image <- loadImage file 629 putStrLn $ "Releasing texture " ++ show tex
630 tex <- newTexture 630 with tex $ glDeleteTextures 1
631 gameIO $ do 631
632 let w = width image 632-- | Load the 'Texture' specified by the given file.
633 h = height image 633loadTextureImage :: FilePath
634 pix = pixels image 634 -> GLenum -- ^ Texture's min filter.
635 rgb = fromIntegral . fromEnum $ gl_RGB 635 -> GLenum -- ^ Texture's mag filter.
636 636 -> Game s Texture
637 bindTexture tex 637loadTextureImage file minFilter magFilter = do
638 loadTextureData gl_TEXTURE_2D 0 rgb w h 0 gl_RGB gl_UNSIGNED_BYTE pix 638 image <- loadImage file
639 texParami gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $= minFilter 639 tex <- newTexture
640 texParami gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $= magFilter 640 gameIO $ do
641 641 let w = width image
642 return tex 642 h = height image
643 643 pix = pixels image
644-- | Bind the texture. 644 rgb = fromIntegral . fromEnum $ gl_RGB
645bindTexture :: Texture -> IO () 645
646bindTexture = glBindTexture gl_TEXTURE_2D . getTex 646 bindTexture tex
647 647 loadTextureData gl_TEXTURE_2D 0 rgb w h 0 gl_RGB gl_UNSIGNED_BYTE pix
648-- | Unbind the bound texture. 648 texParami gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $= minFilter
649unbindTexture :: IO () 649 texParami gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $= magFilter
650unbindTexture = glBindTexture gl_TEXTURE_2D 0 650
651 651 return tex
652-- | Load data onto the bound texture. 652
653-- 653-- | Bind the texture.
654-- See also 'bindTexture'. 654bindTexture :: Texture -> IO ()
655loadTextureData :: GLenum 655bindTexture = glBindTexture gl_TEXTURE_2D . getTex
656 -> Int -- ^ Target 656
657 -> Int -- ^ Level 657-- | Unbind the bound texture.
658 -> Int -- ^ Internal format 658unbindTexture :: IO ()
659 -> Int -- ^ Width 659unbindTexture = glBindTexture gl_TEXTURE_2D 0
660 -> Int -- ^ Height 660
661 -> GLenum -- ^ Border 661-- | Load data onto the bound texture.
662 -> GLenum -- ^ Texture type 662--
663 -> Ptr a -- ^ Texture data 663-- See also 'bindTexture'.
664 -> IO () 664loadTextureData :: GLenum
665loadTextureData target level internalFormat width height border format texType texData = do 665 -> Int -- ^ Target
666 glTexImage2D target 666 -> Int -- ^ Level
667 (fromIntegral level) 667 -> Int -- ^ Internal format
668 (fromIntegral internalFormat) 668 -> Int -- ^ Width
669 (fromIntegral width) 669 -> Int -- ^ Height
670 (fromIntegral height) 670 -> GLenum -- ^ Border
671 (fromIntegral border) 671 -> GLenum -- ^ Texture type
672 (fromIntegral format) 672 -> Ptr a -- ^ Texture data
673 texType 673 -> IO ()
674 texData 674loadTextureData target level internalFormat width height border format texType texData = do
675 675 glTexImage2D target
676-- | Set the bound texture's parameter to the given value. 676 (fromIntegral level)
677texParami :: GLenum -> GLenum -> SettableStateVar GLenum 677 (fromIntegral internalFormat)
678texParami target param = makeSettableStateVar $ \val -> glTexParameteri target param $ fromIntegral . fromEnum $ val 678 (fromIntegral width)
679 679 (fromIntegral height)
680-- | Set the bound texture's parameter to the given value. 680 (fromIntegral border)
681texParamf :: GLenum -> GLenum -> SettableStateVar Float 681 (fromIntegral format)
682texParamf target param = makeSettableStateVar $ \val -> glTexParameterf target param (unsafeCoerce val) 682 texType
683 683 texData
684-- | Set the active texture unit. 684
685activeTexture :: SettableStateVar GLenum 685-- | Set the bound texture's parameter to the given value.
686activeTexture = makeSettableStateVar glActiveTexture 686texParami :: GLenum -> GLenum -> SettableStateVar GLenum
687 687texParami target param = makeSettableStateVar $ \val -> glTexParameteri target param $ fromIntegral . fromEnum $ val
688-- 688
689-- ERROR 689-- | Set the bound texture's parameter to the given value.
690-- 690texParamf :: GLenum -> GLenum -> SettableStateVar Float
691 691texParamf target param = makeSettableStateVar $ \val -> glTexParameterf target param (unsafeCoerce val)
692-- | Get the last OpenGL error. 692
693getGLError :: IO (Maybe String) 693-- | Set the active texture unit.
694getGLError = fmap translate glGetError 694activeTexture :: SettableStateVar GLenum
695 where 695activeTexture = makeSettableStateVar glActiveTexture
696 translate err 696
697 | err == gl_NO_ERROR = Nothing 697--
698 | err == gl_INVALID_ENUM = Just "Invalid enum" 698-- ERROR
699 | err == gl_INVALID_VALUE = Just "Invalid value" 699--
700 | err == gl_INVALID_OPERATION = Just "Invalid operation" 700
701 | err == gl_OUT_OF_MEMORY = Just "Out of memory" 701-- | Get the last OpenGL error.
702 | otherwise = Just "Unknown error" 702getGLError :: IO (Maybe String)
703 703getGLError = fmap translate glGetError
704-- | Print the last OpenGL error. 704 where
705printGLError :: IO () 705 translate err
706printGLError = getGLError >>= \err -> case err of 706 | err == gl_NO_ERROR = Nothing
707 Nothing -> return () 707 | err == gl_INVALID_ENUM = Just "Invalid enum"
708 Just str -> hPutStrLn stderr str 708 | err == gl_INVALID_VALUE = Just "Invalid value"
709 709 | err == gl_INVALID_OPERATION = Just "Invalid operation"
710-- | Run the given setup action and check for OpenGL errors. 710 | err == gl_OUT_OF_MEMORY = Just "Out of memory"
711-- 711 | otherwise = Just "Unknown error"
712-- If an OpenGL error is produced, an exception is thrown containing 712
713-- the given string appended to the string describing the error. 713-- | Print the last OpenGL error.
714assertGL :: Game s a -> String -> Game s a 714printGLError :: IO ()
715assertGL action err = do 715printGLError = getGLError >>= \err -> case err of
716 result <- action 716 Nothing -> return ()
717 status <- gameIO getGLError 717 Just str -> hPutStrLn stderr str
718 case status of 718
719 Just str -> gameError $ "OpenGL error raised: " ++ err ++ "; " ++ str 719-- | Run the given setup action and check for OpenGL errors.
720 Nothing -> return result 720--
721-- If an OpenGL error is produced, an exception is thrown containing
722-- the given string appended to the string describing the error.
723assertGL :: Game s a -> String -> Game s a
724assertGL action err = do
725 result <- action
726 status <- gameIO getGLError
727 case status of
728 Just str -> gameError $ "OpenGL error raised: " ++ err ++ "; " ++ str
729 Nothing -> return result