module Graphics.GL.Low.VAO ( -- | Vertex Array Objects (VAO). Despite having almost no operations of its -- own, the VAO mechanism is one of the most complex pieces of OpenGL. A VAO -- has mutable state which associates vertex shader input variables (actually -- the integer location of the variable) with three things: -- -- - The VBO to read from. -- - The position in the each vertex array (in the VBO) to read from. -- - The interpretation of the bytes found there (32-bit float, 16-bit int, etc). -- -- You set these VAO parameters with the following dance: -- -- - Bind a VAO -- - Bind a VBO -- - Use a Program -- - call 'Graphics.GL.Low.VertexAttrib.setVertexLayout' which will -- lookup the position of the input variables and issue the appropriate -- glVertexAttribPointer calls. -- -- After a VAO is configured against a Program, either can be swapped in or -- out freely and they will still work when both are swapped in again together. -- -- An "in-use" program will use whatever VAO is bound for getting its vertex -- inputs. It is up to the programmer to ensure that the VAO has been -- configured with the right variable positions for the current program. Two -- ways to do this are to use a consistent set of variables for all shaders or -- restrict a set of VAOs to only be allowed with specific Program objects. -- -- The currently bound VBO is not remembered or restored by binding a VAO, but -- the currently bound ElementArray is. This detail won't affect you if you -- always explicitly bind an ElementArray after binding a VAO. Alternatively -- you can exploit this to bundle particular models and their element arrays -- as a VAO. -- -- Diagram of possible VAO contents: -- -- <> -- -- The above VAO would be compatible with the following vertex program: -- -- @ -- #version 150 -- -- in vec2 position; -- in vec3 color; -- -- out vec3 Color; -- -- void main() -- { -- gl_Position = vec4(position, 0.0, 1.0); -- Color = color; -- } -- @ newVAO, deleteVAO, bindVAO, VAO ) where import Foreign.Storable import Foreign.Marshal import Graphics.GL import Graphics.GL.Low.Classes -- | Handle to a VAO. newtype VAO = VAO GLuint deriving Show instance GLObject VAO where glObjectName (VAO n) = fromIntegral n -- | Create a new VAO. The only thing you can do with a VAO is bind it to -- the vertex array binding target. newVAO :: IO VAO newVAO = do n <- alloca (\ptr -> glGenVertexArrays 1 ptr >> peek ptr) return (VAO n) -- | Delete a VAO. deleteVAO :: VAO -> IO () deleteVAO (VAO n) = withArray [n] (\ptr -> glDeleteVertexArrays 1 ptr) -- | Assign the VAO to the vertex array binding target. The VAO already bound -- will be replaced, if any. bindVAO :: VAO -> IO () bindVAO (VAO n) = glBindVertexArray n