aboutsummaryrefslogtreecommitdiff
path: root/Spear/GLSL/VAO.hs
blob: f1216363d8e12dfe4417cb7bc39c529c66e8f5ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module Spear.GLSL.VAO
(
    VAO
    -- * Creation and destruction
,   newVAO
,   releaseVAO
    -- * Manipulation
,   bindVAO
,   enableVAOAttrib
,   attribVAOPointer
    -- * Rendering
,   drawArrays
,   drawElements
)
where


import Spear.Setup
import Control.Monad.Trans.Class (lift)
import Foreign.Marshal.Utils as Foreign (with)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Storable (peek)
import Foreign.Ptr
import Unsafe.Coerce
import Graphics.Rendering.OpenGL.Raw.Core31


-- | Represents a vertex array object.
data VAO = VAO
    { getVAO :: GLuint
    , rkey   :: Resource
    }


instance Eq VAO where
    vao1 == vao2 = getVAO vao1 == getVAO vao2


instance Ord VAO where
    vao1 < vao2 = getVAO vao1 < getVAO vao2


-- | Create a new 'VAO'.
newVAO :: Setup VAO
newVAO = do
    h <- setupIO . alloca $ \ptr -> do
        glGenVertexArrays 1 ptr
        peek ptr
    
    rkey <- register $ deleteVAO h
    return $ VAO h rkey


-- | Release the given 'VAO'.
releaseVAO :: VAO -> Setup ()
releaseVAO = release . rkey


-- | Delete the given 'VAO'.
deleteVAO :: GLuint -> IO ()
deleteVAO vao = Foreign.with vao $ glDeleteVertexArrays 1


-- | Bind the given 'VAO'.
bindVAO :: VAO -> IO ()
bindVAO = glBindVertexArray . getVAO


-- | Enable the given vertex attribute of the bound 'VAO'.
enableVAOAttrib :: GLuint -> IO ()
enableVAOAttrib = glEnableVertexAttribArray


-- | Bind the bound buffer to the given point.
attribVAOPointer :: GLuint -> GLint -> GLenum -> Bool -> GLsizei -> Int -> IO ()
attribVAOPointer idx ncomp dattype normalise stride off =
    glVertexAttribPointer idx ncomp dattype (unsafeCoerce normalise) stride (unsafeCoerce off)


-- | Draw the bound 'VAO'.
drawArrays :: GLenum -> Int -> Int -> IO ()
drawArrays mode first count = glDrawArrays mode (unsafeCoerce first) (unsafeCoerce count)


-- | Draw the bound 'VAO', indexed mode.
drawElements :: GLenum -> Int -> GLenum -> Ptr a -> IO ()
drawElements mode count t idxs = glDrawElements mode (unsafeCoerce count) t idxs