packages feed

lowgl (empty) → 0.1.0.0

raw patch · 4 files changed

+1511/−0 lines, 4 filesdep +basedep +data-defaultdep +glsetup-changed

Dependencies added: base, data-default, gl, linear, vector

Files

+ Graphics/GL/Low.hs view
@@ -0,0 +1,1409 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE PatternSynonyms #-}+module Graphics.GL.Low (++  -- * In a Nutshell+  --+  -- ** Overview+  -- | OpenGL is a graphics rendering interface. This library exposes a vastly+  -- simplified subset of OpenGL that is hopefully still complete enough for+  -- many purposes, such as following tutorials, making simple games, and+  -- demos. In particular the intention is to concentrate on a subset of+  -- OpenGL 3.2 (Core Profile) roughly corresponding to ES 2.0.+  --+  -- A second primary purpose is to document the complex model behind the+  -- interface in a way that is more elaborate than tutorials and more concise+  -- than the spec. As such, this is an experimental project to aid my own+  -- process of understanding OpenGL. It seems that understanding the entire+  -- picture up-front is the only way to get started, so this should also serve+  -- as a quick reference guide to the core commands and concepts.+  --+  -- This library uses the `gl' package for raw bindings to OpenGL and the+  -- `linear' package for matrices.+  --+  -- (include link to example programs)++  -- ** Objects+  -- | Objects may be created and destroyed by client code. They include:+  --+  -- - Vertex Array Object ('VAO')+  -- - Buffer Objects ('VBO', 'ElementArray')+  -- - Textures ('Tex2D', 'CubeMap')+  -- - Shader 'Program's+  -- - Framebuffer Objects ('FBO')+  -- - Renderbuffer Objects ('RBO')++  -- ** Binding Targets+  -- | Objects are referenced with integers (called names in GL), so binding+  -- targets can be thought of as global variables to put those references.+  -- Many operations implicitly read from these globals to determine what the+  -- target object of the operation is. They include:+  --+  -- - Vertex array binding target (for VAO)+  -- - Buffer binding targets (ARRAY_BUFFER and ELEMENT_ARRAY_BUFFER)+  -- - Texture binding targets (TEXTURE_2D and TEXTURE_CUBE_MAP)+  -- - Framebuffer binding target (for FBO)+  --+  -- (not binding targets but similar)+  --+  -- - Shader program "in use"+  -- - Texture units+  -- - Current active texture unit+  -- - Image attachment points of an FBO++  -- ** Shader Programs+  -- | The role of the second half of a program, the fragment shader, is to+  -- compute the color and depth of pixels covered by rasterized primitives+  -- (points, lines, and triangles) in the process of rendering. The role of+  -- the /first/ half of the program (vertex program) is to arrange the vertices+  -- of those primitives somewhere in clip space. Where these vertices and+  -- their attributes come from in the first place is determined by the VAO+  -- bound to the vertex array binding target. The program may also make use+  -- of uniform variables and texture units assigned by client code before+  -- rendering (but in a process separate from configuring the VAO). At most+  -- one Program can be "in use" at a time.++  -- ** VAO+  -- | The VAO is essential. At least one VAO must be created and bound to the+  -- vertex array binding target before rendering, before configuring a+  -- program's vertex attributes. Here is why: the VAO stores the association+  -- between input variables in the program and a VBO from which to pipe input+  -- from. It also stores the format of the VBO data, which is otherwise just+  -- a big blob. Finally, the VAO stores the state of the element array binding+  -- target used for indexed rendering.+  --+  -- After installing a program with 'useProgram' and binding a source VBO+  -- to the array buffer binding target ('bindVBO') then the bound VAO can be+  -- updated ('setVertexAttributeLayout') with new vertex attribute information.+  -- After this, the VBO can be rebound to configure a different set of inputs+  -- with a different source. Many VAOs can be created and swapped out to pipe+  -- vertex data in different ways to different programs (or the same program).+  --+  -- When a VAO is bound it restores the state of the element array binding+  -- target. For this reason you can think of that binding target as simply+  -- being a function of the VAO itself rather than a separate global state.++  -- ** Uniforms and Samplers (Textures)+  -- | Programs may have uniform variables and "sampler uniforms" as input.+  -- Uniforms are accessible from the vertex or fragment shader part of the+  -- program but their values are fixed during the course of a rendering command.+  -- They can be set and reset with the setUniform family (ex. 'setUniform1f'),+  -- which updates a program object with new uniform values. Among other+  -- things, updating the uniforms each frame is the main way to animate a+  -- scene.+  --+  -- Samplers are textures that the shader can interpolate to get "in between"+  -- values. The texture a sampler uses is determined by the contents of the+  -- texture unit that that sampler points to. The sampler is a uniform with+  -- an integer type. This integer is the texture unit to use. The word texture+  -- should not be construed to mean a color image. Shaders can make use of+  -- many kinds of multi-dimensional data that happen to be available through+  -- the samplers.++  -- ** Texture Objects and Texture Units+  -- | Before a shader can use a texture it must be assigned to a texture unit.+  -- First set the active texture unit to the desired unit number+  -- ('setActiveTextureUnit') then bind the texture object to one of the+  -- two texture binding targets, depending on what kind of texture it is (2D+  -- or cubemap). Binding a texture has the side effect of assigning it to the+  -- active texture unit.++  -- ** Custom Framebuffers+  -- | It is possible (and important to many techniques) to utilize an+  -- off-screen render target. To do this create an FBO ('newFBO'), bind it to+  -- the framebuffer binding target ('bindFramebuffer') and attach a color+  -- /image/ object (texture or renderbuffer object). If necessary a depth+  -- image or combination depth-stencil image can be attached as well. If no+  -- color image is attached then the FBO is incomplete and rendering will be+  -- an error.  After rendering to an FBO any textures that were attached can+  -- be used for a second pass by assigning them to a texture unit. Watch out+  -- for feedback loops accidentally sampling a texture that is also being+  -- rendered to at the same time!+  --+  -- A renderbuffer object is a minor character to be used when you do not+  -- expect to use the results of rendering but need an image anyway. For+  -- example you may need a depth buffer to do depth testing, or you may want+  -- to ignore the (required for rendering to work at all) color buffer.++  -- ** Images and Image Formats+  -- | FBOs have attachment points for /images/. A texture serves as an image+  -- and a renderbuffer object serves as an image. Images have an "internal+  -- format" which describes the size and interpretation of pixel components.+  -- There are seven internal formats, five of which are color image formats+  -- such as grayscale and RGB. The other two are the depth buffer format and+  -- the combination depth-stencil format. RBOs ('newRBO') and empty textures+  -- ('newEmptyTexture2D', 'newEmptyCubeMap') can be created with any of these+  -- formats.+  --+  -- (The above is a gross simplification of OpenGL's image formats. I should+  -- probably revise, because it may greatly improve performance to use some+  -- of the 16-bit color formats rather than 32.)++  -- ** Depth Testing, Stencil Testing, Scissor Testing, Facet Culling+  -- | The depth buffer and stencil buffers, if present in the current+  -- framebuffer, can be used to avoid rendering to points of the screen by+  -- testing against the value stored at those points. For example if commanded+  -- to show a triangle in a region of the framebuffer with a depth greater+  -- than current depth buffer values, then the triangle may not be rendered to+  -- the color buffer or anywhere else (depending on settings). There are many+  -- global settings to switch on and off these tests and the ability to+  -- modify the buffers involved. The stencil test in particular is highly+  -- configurable. The scissor test is the simplest: when activated nothing+  -- outside the scissor box (in screen space) will be rendered. The only+  -- other configuration is to set that scissor box ('setScissorBox').+  -- Polygons facing toward or away from the viewer can be dropped (or culled)+  -- from rendering with 'enableCulling'.++  -- ** Coordinate Systems+  -- | - Screen space is simply the 2D coordinate system of your window.+  -- The viewport transformation (see 'setViewport') determines where in the+  -- window the mapping of the NDS cube (see below) will appear.+  -- - NDS, normalized device coordinates, or sometimes viewport space is a+  -- cube 2x2x2 centered at the origin the inside of which is your final scene,+  -- before it is mapped to the screen via the viewport setting (see+  -- 'setViewport'). If an orthographic projection was used to put the scene in+  -- clip space then clip space and NDS are the same.+  -- - Clip space is the destination of vertices transformed by the+  -- vertex program. Objects here are mapped to NDS using the perspective+  -- division technique to account for the case that the vertex shader used+  -- a perspective matrix.+  -- - Model space is the name for positions of raw vertices as present in+  -- the VBOs. The vertex program will want to somehow move these vertexes+  -- into clip space, representing generally the position and direction the+  -- user is viewing the scene from.++  -- ** Rendering Points, Lines, and Triangles+  -- | The draw family (ex. 'drawTriangles') of commands commissions the+  -- rendering of a certain number of vertices worth of primitives. The+  -- current program will get input from the current VAO, the current texture+  -- units, and execute on all the potentially affected pixels in the current+  -- framebuffer. Vertexes are consumed in the order they appear in their+  -- respective source VBOs. If the VAO is missing, the program is missing, or+  -- the current framebuffer has no color attachment, then rendering will not+  -- work.+  --+  -- The drawIndexed family (ex. 'drawIndexedTriangles') of commands carries+  -- out the same effects as the non-indexed rendering commands but traverses+  -- vertices in an order determined by the sequence of indexes packed in the+  -- ElementArray currently bound to the element array binding target. This+  -- mainly allows a huge reuse of vertex data in the case that the object+  -- being rendered forms a closed mesh.+++++  -- * VAO+  VAO,+  newVAO,+  bindVAO,+  deleteVAO,++  -- * Buffer Objects+  -- ** VBO+  VBO,+  UsageHint(..),+  newVBO,+  bindVBO,+  updateVBO,+  deleteVBO,++  -- ** Element Array+  ElementArray,+  IndexFormat(..),+  newElementArray,+  bindElementArray,+  updateElementArray,+  deleteElementArray,++  -- * Shader Program+  Program,+  ProgramError(..),+  newProgram,+  newProgramSafe,+  useProgram,+  deleteProgram,++  -- ** Vertex Attributes+  VertexAttributeLayout(..),+  LayoutElement(..),+  ComponentFormat(..),+  setVertexAttributeLayout,++  -- ** Uniform Variables+  --+  -- | Set uniform variables for the current program. To set an array of+  -- uniforms pass a list of more than one value.++  -- *** Float Uniforms+  -- | These call glUniformNfv.+  setUniform1f, +  setUniform2f,+  setUniform3f,+  setUniform4f,++  -- *** Int Uniforms+  -- | These call glUniformNiv.+  setUniform1i,+  setUniform2i,+  setUniform3i,+  setUniform4i,++  -- *** Matrix Uniforms+  -- | These call glUniformMatrixNfv.+  setUniform22,+  setUniform33,+  setUniform44,++  -- * Textures+  Tex2D,+  CubeMap,+  Dimensions(..),+  Cube(..),+  Side,+  newTexture2D,+  newCubeMap,+  newEmptyTexture2D,+  newEmptyCubeMap,+  deleteTexture,+  setActiveTextureUnit,+  bindTexture2D,+  bindTextureCubeMap,+  Filtering(..),+  setTex2DFiltering,+  setCubeMapFiltering,+  Wrapping(..),+  setTex2DWrapping,+  setCubeMapWrapping,++  -- * Rendering++  -- ** Primitives+  -- | Draw primitives to the framebuffer currently bound to the framebuffer+  -- binding target. Each primitive drawing command takes the number of vertices+  -- in the VBOs to render. The vertices are traversed in order.+  drawPoints,+  drawLines,+  drawLineStrip,+  drawLineLoop,+  drawTriangles,+  drawTriangleStrip,+  drawTriangleFan,++  -- ** Primitives by Index+  -- | Draw primitives as above, but use the order of vertices defined in+  -- the ElementArray currently bound to the element array buffer binding+  -- target.+  drawIndexedPoints,+  drawIndexedLines,+  drawIndexedLineStrip,+  drawIndexedLineLoop,+  drawIndexedTriangles,+  drawIndexedTriangleStrip,+  drawIndexedTriangleFan,++  -- ** Color Buffer+  enableColorWriting,+  disableColorWriting,+  clearColorBuffer,++  -- ** Depth Test+  enableDepthTest,+  disableDepthTest,+  clearDepthBuffer,+  enableDepthWriting,+  disableDepthWriting,++  -- ** Stencil Test+  enableStencilTest,+  disableStencilTest,+  clearStencilBuffer,+  enableStencilWriting,+  disableStencilWriting,++  -- ** Scissor Test+  setScissorBox,+  enableScissorTest,+  disableScissorTest,++  -- ** Facet Culling+  Culling(..),+  enableCulling,+  disableCulling,++  -- ** Blending+  -- | When blending is enabled, colors written to the color buffer will be+  -- blended with the color already there using a formula. The three options+  -- for the formula are ('setBlendEquation'):+  --+  -- - Xs + Yd (FuncAdd, the default)+  -- - Xs - Yd (FuncSub)+  -- - Yd - Xs (FuncReverseSubtract)+  --+  -- where X and Y are source and destination color components respetively.+  -- The factors s and d are blending factors which can be configured+  -- ('setBlendFactors') and should depend on the alpha channel to get a correct+  -- transparency effect. The typical choice is+  --+  -- @+  -- setBlendFactors BlendSourceAlpha BlendOneMinusSourceAlpha+  -- @+  --+  -- When using blending the order of rendering matters. The farther away+  -- primitives should be rendered first to get transparent materials to look+  -- right. This means a depth test is unhelpful when using this technique.+  -- Also blending many layers of transparent primitives can significantly+  -- degrade performance. For these reasons transparency effects may be better+  -- accomplished with an off-screen rendering pass followed by a suitable shader.++  BlendFactor(..),+  BlendEquation(..),+  enableBlending,+  disableBlending,+  setBlendFactors,+  setBlendEquation,++  -- ** Viewport+  Viewport(..),+  setViewport,++  -- * Framebuffers+  DefaultFramebuffer,+  FBO,+  bindFramebuffer,+  newFBO,+  attachTex2D,+  attachCubeMap,+  attachRBO,+  deleteFBO,++  -- * Renderbuffers+  RBO,+  newRBO,+  deleteRBO,++  -- * Errors+  GLError(..),+  getGLError,++  -- * Image Formats+  Alpha,+  Luminance,+  LuminanceAlpha,+  RGB,+  RGBA,+  Depth24,+  Depth24Stencil8,++  -- * Classes+  InternalFormat(..),+  Framebuffer(..),+  Texture(..),+  Attachable(..)++) where++import Prelude hiding (sum)+import Control.Exception+import Data.Typeable+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal+import Foreign.C.String+import Data.Vector.Storable (Vector, unsafeWith)+import qualified Data.Vector.Storable as V (length)+import Control.Monad hiding (forM_)+import Data.Word+import Data.Int+import Data.Functor+import Control.Applicative+import Data.Traversable+import Data.Foldable+import Data.Default++import Linear+import Graphics.GL++-- | A VAO stores vertex attribute layouts and the VBO source of vertices+-- for those attributes. It also stores the state of the element array binding+-- target. The vertex array binding target admits one VAO at a time.+newtype VAO = VAO GLuint deriving Show++-- | A Program object is the combination of a compiled vertex shader and fragment+-- shader. Programs have three kinds of inputs: vertex attributes, uniforms,+-- and samplers. Programs have two outputs: fragment color and fragment depth.+-- At most one program can be "in use" at a time. Same idea as binding targets+-- it's just not called that.+newtype Program = Program GLuint deriving Show++-- | A VBO is a buffer object which has vertex data. Shader programs use VBOs+-- as input to their vertex attributes according to the configuration of the+-- bound VAO.+data VBO = VBO GLuint deriving Show++-- | A buffer object which has a packed sequence of vertex indices. Indexed+-- rendering uses the ElementArray bound to the element array binding target.+data ElementArray = ElementArray GLuint deriving Show++-- | A 2D texture. A program can sample a texture if it has been bound to+-- the appropriate texture unit.+newtype Tex2D a = Tex2D GLuint deriving Show++-- | A cubemap texture is just six 2D textures. A program can sample a cubemap+-- texture if it has been bound to the appropriate texture unit.+newtype CubeMap a = CubeMap GLuint deriving Show++-- | A framebuffer object is an alternative rendering destination. Once an FBO+-- is bound to framebuffer binding target, it is possible to attach images+-- (textures or RBOs) for color, depth, or stencil rendering.+newtype FBO = FBO GLuint deriving Show+++-- | Texture filtering modes.+data Filtering =+  Nearest | -- ^ No interpolation.+  Linear    -- ^ Linear interpolation.+    deriving Show++instance ToGL Filtering where+  toGL Nearest = GL_NEAREST+  toGL Linear = GL_LINEAR++-- | Texture wrapping modes.+data Wrapping =+  Repeat         | -- ^ Tile the texture past the boundary.+  MirroredRepeat | -- ^ Tile the texture but mirror every other tile.+  ClampToEdge      -- ^ Use the edge color for anything past the boundary.+    deriving Show++instance ToGL Wrapping where+  toGL Repeat = GL_REPEAT+  toGL MirroredRepeat = GL_MIRRORED_REPEAT+  toGL ClampToEdge = GL_CLAMP_TO_EDGE++-- | Facet culling modes.+data Culling =+  CullFront |+  CullBack |+  CullFrontAndBack+    deriving Show++instance ToGL Culling where+  toGL CullFront = GL_FRONT+  toGL CullBack = GL_BACK+  toGL CullFrontAndBack = GL_FRONT_AND_BACK++-- | The name of a vertex input to a program combined with the+-- component format and number of components for that attribute in the+-- vertex data. Alternatively the size of an unused section of the data+-- in bytes.+data LayoutElement =+  Attrib String Int ComponentFormat | -- ^ Name, component count and component format of a vertex attribute.+  Unused Int -- ^ Size in bytes of an unused section of the vertex data.+    deriving Show++-- | The layout of interleaved vertex attribute data.+type VertexAttributeLayout = [LayoutElement]++-- | The size and interpretation of a vertex attribute component. Normalized+-- components will be mapped to floats in the range [0, 1].+data ComponentFormat =+  VFloat | -- ^ 4-byte float+  VByte | +  VUByte | +  VByteNormalized | +  VUByteNormalized |+  VShort | -- ^ 2-byte signed integer+  VUShort | -- ^ 2-byte unsigned integer+  VShortNormalized |+  VUShortNormalized |+  VInt | -- ^ 4-byte signed integer+  VUInt | -- ^ 4-byte unsigned integer+  VIntNormalized |+  VUIntNormalized+    deriving (Eq, Show)++instance ToGL ComponentFormat where+  toGL VFloat = GL_FLOAT+  toGL VByte = GL_BYTE+  toGL VUByte = GL_UNSIGNED_BYTE+  toGL VByteNormalized = GL_BYTE+  toGL VUByteNormalized = GL_UNSIGNED_BYTE+  toGL VShort = GL_SHORT+  toGL VUShort = GL_UNSIGNED_SHORT+  toGL VShortNormalized = GL_SHORT+  toGL VUShortNormalized = GL_UNSIGNED_SHORT+  toGL VInt = GL_INT+  toGL VUInt = GL_UNSIGNED_INT+  toGL VIntNormalized = GL_INT+  toGL VUIntNormalized = GL_UNSIGNED_INT+  ++-- | Usage hint for allocation of buffer object storage.+data UsageHint = StaticDraw  -- ^ Data will seldomly change.+               | DynamicDraw -- ^ Data will change.+               | StreamDraw  -- ^ Data will change very often.+                 deriving Show++instance ToGL UsageHint where+  toGL StaticDraw  = GL_STATIC_DRAW+  toGL DynamicDraw = GL_DYNAMIC_DRAW+  toGL StreamDraw  = GL_STREAM_DRAW+++-- | 1-byte alpha channel only.+data Alpha = Alpha deriving Show++-- | 1-byte grayscale pixel format.+data Luminance = Luminance deriving Show++-- | 2-byte luminance and alpha channel format.+data LuminanceAlpha = Luminancealpha deriving Show++-- | 3-byte true color pixel format.+data RGB = RGB deriving Show++-- | 4-byte true color plus alpha channel format.+data RGBA = RGBA deriving Show++-- | 24-bit depth format.+data Depth24 = Depth24 deriving Show++-- | Combination depth and stencil format.+data Depth24Stencil8 = Depth24Stencil8 deriving Show++-- | OpenGL internal image formats.+class InternalFormat a where+  internalFormat :: (Eq b, Num b) => proxy a -> b+instance InternalFormat RGB where+  internalFormat _ = GL_RGB8+instance InternalFormat RGBA where+  internalFormat _ = GL_RGBA+instance InternalFormat Alpha where+  internalFormat _ = GL_ALPHA+instance InternalFormat Luminance where+  internalFormat _ = GL_LUMINANCE+instance InternalFormat LuminanceAlpha where+  internalFormat _ = GL_LUMINANCE_ALPHA+instance InternalFormat Depth24 where+  internalFormat _ = GL_DEPTH_COMPONENT24+instance InternalFormat Depth24Stencil8 where+  internalFormat _ = GL_DEPTH24_STENCIL8++-- | The allowed attachment point for images with an internal format.+class InternalFormat a => Attachable a where+  attachPoint :: (Eq b, Num b) => proxy a -> b+instance Attachable RGB where+  attachPoint _ = GL_COLOR_ATTACHMENT0+instance Attachable RGBA where+  attachPoint _ = GL_COLOR_ATTACHMENT0+instance Attachable Luminance where+  attachPoint _ = GL_COLOR_ATTACHMENT0+instance Attachable LuminanceAlpha where+  attachPoint _ = GL_COLOR_ATTACHMENT0+instance Attachable Alpha where+  attachPoint _ = GL_COLOR_ATTACHMENT0+instance Attachable Depth24 where+  attachPoint _ = GL_DEPTH_ATTACHMENT+instance Attachable Depth24Stencil8 where+  attachPoint _ = GL_DEPTH_STENCIL_ATTACHMENT++-- | How indices are packed in an ElementArray buffer object.+data IndexFormat =+  UByteIndices  | -- ^ Each index is one unsigned byte.+  UShortIndices | -- ^ Each index is a two byte unsigned int.+  UIntIndices     -- ^ Each index is a four byte unsigned int.+    deriving Show++instance ToGL IndexFormat where+  toGL UByteIndices  = GL_UNSIGNED_BYTE+  toGL UShortIndices = GL_UNSIGNED_SHORT+  toGL UIntIndices   = GL_UNSIGNED_INT+++-- | An RBO is a kind of image object used for rendering. The only thing+-- you can do with an RBO is attach it to an FBO.+data RBO a = RBO { unRBO :: GLuint } deriving Show++-- | A rectangular section of the window.+data Viewport = Viewport+  { viewportX :: Int+  , viewportY :: Int+  , viewportW :: Int+  , viewportH :: Int }+    deriving (Eq, Show)++-- | The size of an image in pixels, parameterized by an image format type.+data Dimensions = Dimensions+  { imageWidth :: Int+  , imageHeight :: Int }+    deriving (Show)++-- | Six values, one on each side.+data Cube a = Cube+  { cubeRight  :: a+  , cubeLeft   :: a+  , cubeTop    :: a+  , cubeBottom :: a+  , cubeFront  :: a+  , cubeBack   :: a }+    deriving (Show, Functor, Foldable, Traversable)++-- | A type to pick one of the sides of a cube. See the accessors of the+-- type 'Cube'.+type Side = forall a . Cube a -> a++instance Applicative Cube where+  pure x = Cube x x x x x x+  (Cube f1 f2 f3 f4 f5 f6) <*> (Cube x1 x2 x3 x4 x5 x6) =+    Cube (f1 x1) (f2 x2) (f3 x3) (f4 x4) (f5 x5) (f6 x6)++-- | Either a vertex shader or a fragment shader.+data ShaderType = VertexShader | FragmentShader deriving Show++instance ToGL ShaderType where+  toGL VertexShader = GL_VERTEX_SHADER+  toGL FragmentShader = GL_FRAGMENT_SHADER++-- | The error message emitted by the driver when shader compilation or+-- linkage fails.+data ProgramError =+  VertexShaderError String |+  FragmentShaderError String |+  LinkError String+    deriving (Show, Typeable)+  +instance Exception ProgramError++-- | Detectable errors.+data GLError =+  InvalidEnum | -- ^ Enum argument out of range.+  InvalidValue | -- ^ Integer argument out of range.+  InvalidOperation | -- ^ Operation illegal in current state.+  InvalidFramebufferOperation | -- ^ Framebuffer is not complete.+  OutOfMemory+    deriving Typeable++instance Exception GLError++instance Show GLError where+  show InvalidEnum = "INVALID_ENUM enum argument out of range"+  show InvalidValue = "INVALID_VALUE Numeric argument out of range"+  show InvalidOperation = "INVALID_OPERATION Illegal in current state"+  show InvalidFramebufferOperation = "INVALID_FRAMEBUFFER_OPERATION Framebuffer object is not complete"+  show OutOfMemory = "Not enough memory left to execute command"++class ToGL a where+  toGL :: (Num b, Eq b) => a -> b++-- | Textures have an internal numeric name.+class Texture a where+  textureName :: Num b => a -> b++instance Texture (Tex2D a) where+  textureName (Tex2D n) = fromIntegral n++instance Texture (CubeMap a) where+  textureName (CubeMap n) = fromIntegral n+++-- | Blending functions for alpha blending.+data BlendEquation =+  FuncAdd | -- ^ the default+  FuncSubtract |+  FuncReverseSubtract+    deriving Show++instance Default BlendEquation where+  def = FuncAdd++instance ToGL BlendEquation where+  toGL FuncAdd = GL_FUNC_ADD+  toGL FuncSubtract = GL_FUNC_SUBTRACT+  toGL FuncReverseSubtract = GL_FUNC_REVERSE_SUBTRACT+++-- | Blending factors.+data BlendFactor =+  BlendOne |+  BlendZero |+  BlendSourceAlpha |+  BlendOneMinusSourceAlpha+    deriving Show++instance ToGL BlendFactor where+  toGL BlendOne = GL_ONE+  toGL BlendZero = GL_ZERO+  toGL BlendSourceAlpha = GL_SRC_ALPHA+  toGL BlendOneMinusSourceAlpha = GL_ONE_MINUS_SRC_ALPHA++-- | The default framebuffer. Bind this to render to the screen as usual.+-- Use the Default instance method 'def' to construct it.+data DefaultFramebuffer = DefaultFramebuffer deriving Show++instance Default DefaultFramebuffer where+  def = DefaultFramebuffer++-- | Framebuffers can be bound to the framebuffer binding target. There is+-- a default framebuffer and the client may create an arbitrary number of+-- new framebuffer objects.+class Framebuffer a where+  framebufferName :: Num b => a -> b++instance Framebuffer DefaultFramebuffer where+  framebufferName _ = 0++instance Framebuffer FBO where+  framebufferName (FBO 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+++-- | Create a buffer object from a blob of bytes. The usage argument hints+-- at how often you will modify the data.+newVBO :: Vector Word8 -> UsageHint -> IO VBO+newVBO src usage = do+  n <- alloca (\ptr -> glGenBuffers 1 ptr >> peek ptr)+  let len = V.length src+  glBindBuffer GL_ARRAY_BUFFER n+  unsafeWith src $ \ptr -> glBufferData+    GL_ARRAY_BUFFER+    (fromIntegral len)+    (castPtr ptr)+    (toGL usage)+  return (VBO n)++-- | Delete a VBO.+deleteVBO :: VBO -> IO ()+deleteVBO (VBO n) = withArray [n] (\ptr -> glDeleteBuffers 1 ptr)++-- | Modify the data in the currently bound VBO starting from the specified+-- index in bytes.+updateVBO :: Vector Word8 -> Int -> IO ()+updateVBO src offset = do+  let len = V.length src+  unsafeWith src $ \ptr -> glBufferSubData+    GL_ARRAY_BUFFER +    (fromIntegral offset)+    (fromIntegral len)+    (castPtr ptr)++-- | Bind a VBO to the array buffer binding target. The buffer object bound+-- there will be replaced, if any.+bindVBO :: VBO -> IO ()+bindVBO (VBO n) = glBindBuffer GL_ARRAY_BUFFER n+++-- | Create a new ElementArray buffer object from the blob of packed indices.+-- The usage argument hints at how often you plan to modify the data.+newElementArray :: Vector Word8 -> UsageHint -> IO ElementArray+newElementArray bytes usage = do+  n <- alloca (\ptr -> glGenBuffers 1 ptr >> peek ptr)+  glBindBuffer GL_ELEMENT_ARRAY_BUFFER n+  let len = V.length bytes+  unsafeWith bytes $ \ptr -> do+    glBufferData+      GL_ELEMENT_ARRAY_BUFFER+      (fromIntegral len)+      (castPtr ptr)+      (toGL usage)+  return (ElementArray n)++-- | Delete an ElementArray+deleteElementArray :: ElementArray -> IO ()+deleteElementArray (ElementArray n) = withArray [n] (\ptr -> glDeleteBuffers 1 ptr)+  +-- | Modify contents in the currently bound ElementArray starting at the+-- specified index in bytes.+updateElementArray :: Vector Word8 -> Int -> IO ()+updateElementArray bytes offset = unsafeWith bytes $ \ptr -> do+  glBufferSubData+    GL_ELEMENT_ARRAY_BUFFER+    (fromIntegral offset)+    (fromIntegral (V.length bytes))+    (castPtr ptr)+++-- | Assign an ElementArray to the element array binding target. It will+-- replace the ElementArray already bound there, if any. Note that the state+-- of the element array binding target is a function of the current VAO.+bindElementArray :: ElementArray -> IO ()+bindElementArray (ElementArray n) = glBindBuffer GL_ELEMENT_ARRAY_BUFFER n+++-- | Same as 'newProgram' but does not throw exceptions.+newProgramSafe :: String -> String -> IO (Either ProgramError Program)+newProgramSafe vcode fcode = try $ newProgram vcode fcode++-- | Delete a program.+deleteProgram :: Program -> IO ()+deleteProgram (Program n) = glDeleteProgram n++-- | Compile the code for a vertex shader and a fragment shader, then link+-- them into a new program. If the compiler or linker fails it will throw+-- a ProgramError.+newProgram :: String -- ^ vertex shader source code+           -> String -- ^ fragment shader source code+           -> IO Program+newProgram vcode fcode = do+  vertexShaderId <- compileShader vcode VertexShader+  fragmentShaderId <- compileShader fcode FragmentShader+  programId <- glCreateProgram+  glAttachShader programId vertexShaderId+  glAttachShader programId fragmentShaderId+  glLinkProgram programId+  result <- alloca $ \ptr ->+    glGetProgramiv programId GL_LINK_STATUS ptr >> peek ptr+  when (result == GL_FALSE) $ do+    len <- fmap fromIntegral $ alloca $ \ptr ->+      glGetProgramiv programId GL_INFO_LOG_LENGTH ptr >> peek ptr+    errors <- allocaArray len $ \ptr -> do+      glGetProgramInfoLog programId (fromIntegral len) nullPtr ptr+      peekCString ptr+    throwIO (LinkError errors)+  glDeleteShader vertexShaderId+  glDeleteShader fragmentShaderId+  return (Program programId)++-- | Install a program into the rendering pipeline. Replaces the program+-- already in use, if any.+useProgram :: Program -> IO ()+useProgram (Program n) = glUseProgram n++compileShader :: String -> ShaderType -> IO GLuint+compileShader code vertOrFrag = do+  shaderId <- glCreateShader (toGL vertOrFrag)+  withCString code $ \ptr -> with ptr $ \pptr -> do+    glShaderSource shaderId 1 pptr nullPtr+    glCompileShader shaderId+  result <- with GL_FALSE $ \ptr ->+    glGetShaderiv shaderId GL_COMPILE_STATUS ptr >> peek ptr+  when (result == GL_FALSE) $ do+    len <- fmap fromIntegral $ alloca $ \ptr ->+      glGetShaderiv shaderId GL_INFO_LOG_LENGTH ptr >> peek ptr+    errors <- allocaArray len $ \ptr -> do+      glGetShaderInfoLog shaderId (fromIntegral len) nullPtr ptr+      peekCString ptr+    case vertOrFrag of+      VertexShader -> throwIO (VertexShaderError errors)+      FragmentShader -> throwIO (FragmentShaderError errors)+  return shaderId+++-- | This configures the currently bound VAO. It calls glVertexAttribPointer+-- and glEnableVertexAttribArray.+setVertexAttributeLayout :: Program -> VertexAttributeLayout -> IO ()+setVertexAttributeLayout (Program p) layout = do+  let layout' = elaborateLayout 0 layout+  let total = totalLayout layout+  forM_ layout' $ \(name, size, offset, fmt) -> do+    attrib <- withCString name $ \ptr -> glGetAttribLocation p (castPtr ptr)+    let norm = isNormalized fmt+    glVertexAttribPointer+      (fromIntegral attrib)+      (fromIntegral size)+      (toGL fmt)+      (fromIntegral . fromEnum $ norm)+      (fromIntegral offset)+      (castPtr (nullPtr `plusPtr` offset))+    glEnableVertexAttribArray (fromIntegral attrib)++elaborateLayout :: Int -> VertexAttributeLayout -> [(String, Int, Int, ComponentFormat)]+elaborateLayout here layout = case layout of+  [] -> []+  (Unused n):xs -> elaborateLayout (here+n) xs+  (Attrib name n fmt):xs ->+    let size = n * sizeOfVertexComponent fmt in+    (name, n, here, fmt) : elaborateLayout (here+size) xs++totalLayout :: VertexAttributeLayout -> Int+totalLayout layout = sum (map arraySize layout) where+  arraySize (Unused n) = n+  arraySize (Attrib _ n fmt) = n * sizeOfVertexComponent fmt++sizeOfVertexComponent :: ComponentFormat -> Int+sizeOfVertexComponent c = case c of+  VByte -> 1+  VUByte -> 1+  VByteNormalized -> 1+  VUByteNormalized -> 1+  VShort -> 2+  VUShort -> 2+  VShortNormalized -> 2+  VUShortNormalized -> 2+  VInt -> 4+  VUInt -> 4+  VIntNormalized -> 4+  VUIntNormalized -> 4+  VFloat -> 4++isNormalized :: ComponentFormat -> Bool+isNormalized c = case c of+  VByte -> False+  VUByte -> False+  VByteNormalized -> True+  VUByteNormalized -> True+  VShort -> False+  VUShort -> False+  VShortNormalized -> True+  VUShortNormalized -> True+  VInt -> False+  VUInt -> False+  VIntNormalized -> True+  VUIntNormalized -> True+  VFloat -> False+++setUniform1f :: Program -> String -> [Float] -> IO ()+setUniform1f = setUniform glUniform1fv++setUniform2f :: Program -> String -> [V2 Float] -> IO ()+setUniform2f = setUniform+  (\loc cnt val -> glUniform2fv loc cnt (castPtr val))++setUniform3f :: Program -> String -> [V3 Float] -> IO ()+setUniform3f = setUniform+  (\loc cnt val -> glUniform3fv loc cnt (castPtr val))++setUniform4f :: Program -> String -> [V4 Float] -> IO ()+setUniform4f = setUniform+  (\loc cnt val -> glUniform4fv loc cnt (castPtr val))++setUniform1i :: Program -> String -> [Int] -> IO ()+setUniform1i = setUniform+  (\loc cnt val -> glUniform1iv loc cnt (castPtr val))++setUniform2i :: Program -> String -> [V2 Int] -> IO ()+setUniform2i = setUniform +  (\loc cnt val -> glUniform2iv loc cnt (castPtr val))++setUniform3i :: Program -> String -> [V3 Int] -> IO ()+setUniform3i = setUniform+  (\loc cnt val -> glUniform3iv loc cnt (castPtr val))++setUniform4i :: Program -> String -> [V4 Int] -> IO ()+setUniform4i = setUniform+  (\loc cnt val -> glUniform4iv loc cnt (castPtr val))++setUniform44 :: Program -> String -> [M44 Float] -> IO ()+setUniform44 = setUniform+  (\loc cnt val -> glUniformMatrix4fv loc cnt GL_FALSE (castPtr val))++setUniform33 :: Program -> String -> [M33 Float] -> IO ()+setUniform33 = setUniform+  (\loc cnt val -> glUniformMatrix3fv loc cnt GL_FALSE (castPtr val))++setUniform22 :: Program -> String -> [M22 Float] -> IO ()+setUniform22 = setUniform+  (\loc cnt val -> glUniformMatrix2fv loc cnt GL_FALSE (castPtr val))++setUniform :: Storable a => (GLint -> GLsizei -> Ptr a -> IO ())+           -> Program -> String -> [a]+           -> IO ()+setUniform glAction (Program p) name xs = withArrayLen xs $ \n bytes -> do+  loc <- withCString name (\ptr -> glGetUniformLocation p ptr)+  glAction loc (fromIntegral n) bytes+  ++  ++drawPoints :: Int -> IO ()+drawPoints = drawArrays GL_POINTS++drawLines :: Int -> IO ()+drawLines = drawArrays GL_LINES++drawLineStrip :: Int -> IO ()+drawLineStrip = drawArrays GL_LINE_STRIP++drawLineLoop :: Int -> IO ()+drawLineLoop = drawArrays GL_LINE_LOOP++drawTriangles :: Int -> IO ()+drawTriangles = drawArrays GL_TRIANGLES++drawTriangleStrip :: Int -> IO ()+drawTriangleStrip = drawArrays GL_TRIANGLE_STRIP++drawTriangleFan :: Int -> IO ()+drawTriangleFan = drawArrays GL_TRIANGLE_FAN++drawArrays :: GLenum -> Int -> IO ()+drawArrays mode n = glDrawArrays mode (fromIntegral n) 0++drawIndexedPoints :: Int -> IndexFormat -> IO ()+drawIndexedPoints = drawIndexed GL_POINTS++drawIndexedLines :: Int -> IndexFormat -> IO ()+drawIndexedLines = drawIndexed GL_LINES++drawIndexedLineStrip :: Int -> IndexFormat -> IO ()+drawIndexedLineStrip = drawIndexed GL_LINE_STRIP++drawIndexedLineLoop :: Int -> IndexFormat -> IO ()+drawIndexedLineLoop = drawIndexed GL_LINE_LOOP++drawIndexedTriangles :: Int -> IndexFormat -> IO ()+drawIndexedTriangles = drawIndexed GL_TRIANGLES++drawIndexedTriangleStrip :: Int -> IndexFormat -> IO ()+drawIndexedTriangleStrip = drawIndexed GL_TRIANGLE_STRIP++drawIndexedTriangleFan :: Int -> IndexFormat -> IO ()+drawIndexedTriangleFan = drawIndexed GL_TRIANGLE_FAN++drawIndexed :: GLenum -> Int -> IndexFormat -> IO ()+drawIndexed mode n fmt = glDrawElements mode (fromIntegral n) (toGL fmt) nullPtr++-- | Create a new 2D texture from a blob and its image format.+-- Dimensions should be powers of two.+newTexture2D :: InternalFormat a => Vector Word8 -> Dimensions -> IO (Tex2D a)+newTexture2D bytes (Dimensions w h)  = do+  n <- alloca (\ptr -> glGenTextures 1 ptr >> peek ptr)+  glBindTexture GL_TEXTURE_2D n+  tex <- return (Tex2D n)+  unsafeWith bytes $ \ptr -> glTexImage2D+    GL_TEXTURE_2D+    0+    (internalFormat tex)+    (fromIntegral w)+    (fromIntegral h)+    0+    (internalFormat tex)+    GL_UNSIGNED_BYTE+    (castPtr ptr)+  return tex++-- | Delete a texture.+deleteTexture :: Texture a => a -> IO ()+deleteTexture x = withArray [textureName x] (\ptr -> glDeleteTextures 1 ptr)++-- | Create a new cube map texture from six blobs and their respective formats.+-- Dimensions should be powers of two.+newCubeMap :: InternalFormat a+           => Cube (Vector Word8, Dimensions)+           -> IO (CubeMap a)+newCubeMap images = do+  n <- alloca (\ptr -> glGenTextures 1 ptr >> peek ptr)+  glBindTexture GL_TEXTURE_CUBE_MAP n+  cm <- return (CubeMap n)+  let fmt = internalFormat cm+  sequenceA (liftA2 (loadCubeMapSide fmt) images cubeSideCodes)+  return cm+  +loadCubeMapSide :: GLenum -> (Vector Word8, Dimensions) -> GLenum -> IO ()+loadCubeMapSide fmt (bytes, (Dimensions w h)) side = do+  unsafeWith bytes $ \ptr -> glTexImage2D+    side+    0+    (fromIntegral fmt)+    (fromIntegral w)+    (fromIntegral h)+    0+    fmt+    GL_UNSIGNED_BYTE+    (castPtr ptr)++-- | Create an empty texture with the specified dimensions and format.+newEmptyTexture2D :: InternalFormat a => Int -> Int -> IO (Tex2D a)+newEmptyTexture2D w h = do+  let w' = fromIntegral w+  let h' = fromIntegral h+  n <- alloca (\ptr -> glGenTextures 1 ptr >> peek ptr)+  tex <- return (Tex2D n)+  let fmt = internalFormat tex+  let fmt' = internalFormat tex+  glBindTexture GL_TEXTURE_2D n+  glTexImage2D GL_TEXTURE_2D 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  return tex++-- | Create a cubemap texture where each of the six sides has the specified+-- dimensions and format.+newEmptyCubeMap :: InternalFormat a => Int -> Int -> IO (CubeMap a)+newEmptyCubeMap w h = do+  let w' = fromIntegral w+  let h' = fromIntegral h+  n <- alloca (\ptr -> glGenTextures 1 ptr >> peek ptr)+  tex <- return (CubeMap n)+  let fmt = internalFormat tex+  let fmt' = internalFormat tex+  glBindTexture GL_TEXTURE_CUBE_MAP n+  glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_X 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  glTexImage2D GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  glTexImage2D GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0 fmt w' h' 0 fmt' GL_UNSIGNED_BYTE nullPtr+  return tex+  ++-- | Bind a 2D texture to the 2D texture binding target and the currently+-- active texture unit.+bindTexture2D :: Tex2D a -> IO ()+bindTexture2D (Tex2D n) = glBindTexture GL_TEXTURE_2D n++-- | Bind a cubemap texture to the cubemap texture binding target and+-- the currently active texture unit.+bindTextureCubeMap :: CubeMap a -> IO ()+bindTextureCubeMap (CubeMap n) = glBindTexture GL_TEXTURE_CUBE_MAP n++-- | Set the active texture unit. The default is zero.+setActiveTextureUnit :: Enum a => a -> IO ()+setActiveTextureUnit n =+  (glActiveTexture . fromIntegral) (GL_TEXTURE0 + fromEnum n)++-- | Set the filtering for the 2D texture currently bound to the 2D texture+-- binding target.+setTex2DFiltering :: Filtering -> IO ()+setTex2DFiltering filt = do+  glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER (toGL filt)+  glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER (toGL filt)++-- | Set the filtering for the cubemap texture currently bound to the cubemap+-- texture binding target.+setCubeMapFiltering :: Filtering -> IO ()+setCubeMapFiltering filt = do+  glTexParameteri GL_TEXTURE_CUBE_MAP GL_TEXTURE_MIN_FILTER (toGL filt)+  glTexParameteri GL_TEXTURE_CUBE_MAP GL_TEXTURE_MAG_FILTER (toGL filt)++-- | Set the wrapping mode for the 2D texture currently bound to the 2D+-- texture binding target.+setTex2DWrapping :: Wrapping -> IO ()+setTex2DWrapping wrap = do+  glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S (toGL wrap)+  glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_T (toGL wrap)++-- | Set the wrapping mode for the cubemap texture currently bound to the+-- cubemap texture binding target. Because no blending occurs between cube+-- faces you probably want ClampToEdge.+setCubeMapWrapping :: Wrapping -> IO ()+setCubeMapWrapping wrap = do+  glTexParameteri GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_S (toGL wrap)+  glTexParameteri GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_T (toGL wrap)+  glTexParameteri GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_R (toGL wrap)++  ++-- | Allow rendering commands to modify the color buffer of the current+-- framebuffer.+enableColorWriting :: IO ()+enableColorWriting = glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE++-- | Disable rendering to color buffer.+disableColorWriting :: IO ()+disableColorWriting = glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE++-- | Clear the color buffer of the current framebuffer with the specified+-- color. Has no effect if writing to the color buffer is disabled.+clearColorBuffer :: (Float, Float, Float) -> IO ()+clearColorBuffer (r, g, b) = do+  glClearColor (realToFrac r) (realToFrac g) (realToFrac b) 1.0+  glClear GL_COLOR_BUFFER_BIT++-- | Enable the depth test. Attempting to render pixels with a depth value+-- greater than the depth buffer at those pixels will have no effect.+enableDepthTest :: IO ()+enableDepthTest = glEnable GL_DEPTH_TEST++-- | Disable the depth test. Rendering will not be affected by the depth.+-- Use this to render graphics even if they are behind something.+disableDepthTest :: IO ()+disableDepthTest = glDisable GL_DEPTH_TEST++-- | Enable writing depth values to the depth buffer of the current framebuffer.+-- It is enabled by default.+enableDepthWriting :: IO ()+enableDepthWriting = glDepthMask GL_TRUE++-- | Disable writing to the depth buffer.+disableDepthWriting :: IO ()+disableDepthWriting = glDepthMask GL_FALSE++-- | Clear the depth buffer with the maximum depth value.+clearDepthBuffer :: IO ()+clearDepthBuffer = glClear GL_DEPTH_BUFFER_BIT++-- | Enable the stencil test. Any pixels rendered to the screen where the+-- stencil buffer is 1 will not be rendered. This disables writing to the+-- stencil buffer.+enableStencilTest :: IO ()+enableStencilTest = do+  glStencilFunc GL_LESS 1 maxBound+  glStencilOp GL_KEEP GL_KEEP GL_KEEP+  glEnable GL_STENCIL_TEST++-- | Disable the stencil test.+disableStencilTest :: IO ()+disableStencilTest = glDisable GL_STENCIL_TEST++-- | Clear the stencil buffer with all zeros.+clearStencilBuffer :: IO ()+clearStencilBuffer = glClear GL_STENCIL_BUFFER_BIT++-- | Allow rendering to modify the stencil buffer. Any pixels rendered to+-- the screen will set the stencil buffer to 1 at that location.+enableStencilWriting :: IO ()+enableStencilWriting = do+  glStencilFunc GL_ALWAYS 1 maxBound+  glStencilOp GL_KEEP GL_KEEP GL_REPLACE+  glStencilMask 1++-- | Disable rendering to the stencil buffer.+disableStencilWriting :: IO ()+disableStencilWriting = glStencilMask 0++++-- | Set the scissor box. Graphics outside this box will not be rendered as+-- long as the scissor test is enabled.+setScissorBox :: Viewport -> IO ()+setScissorBox (Viewport x y w h) =+  glScissor (fromIntegral x) (fromIntegral y) (fromIntegral w) (fromIntegral h)++-- | Enable the scissor test. Graphics outside the scissor box will not be+-- rendered.+enableScissorTest :: IO ()+enableScissorTest = glEnable GL_SCISSOR_TEST++-- | Disable the scissor test.+disableScissorTest :: IO ()+disableScissorTest = glDisable GL_SCISSOR_TEST+++-- | Enable facet culling. The argument specifies whether front faces, back+-- faces, or both will be omitted from rendering. If both front and back+-- faces are culled you can still render points and lines.+enableCulling :: Culling -> IO ()+enableCulling c = do+  case c of+    CullFront -> glCullFace GL_FRONT+    CullBack -> glCullFace GL_BACK+    CullFrontAndBack -> glCullFace GL_FRONT_AND_BACK+  glEnable GL_CULL_FACE++-- | Disable facet culling. Front and back faces will now be rendered.+disableCulling :: IO ()+disableCulling = glDisable GL_CULL_FACE++-- | Set the viewport. The default viewport simply covers the entire window.+setViewport :: Viewport -> IO ()+setViewport (Viewport x y w h) =+  glViewport (fromIntegral x) (fromIntegral y) (fromIntegral w) (fromIntegral h)++-- | Binds an FBO or the default framebuffer to the framebuffer binding target.+-- Replaces the framebuffer already bound there.+bindFramebuffer :: Framebuffer a => a -> IO ()+bindFramebuffer x = glBindFramebuffer GL_FRAMEBUFFER (framebufferName x)++-- | Create a new framebuffer object. Before the framebuffer can be used for+-- rendering it must have a color image attachment.+newFBO :: IO FBO+newFBO = do+  n <- alloca (\ptr -> glGenFramebuffers 1 ptr >> peek ptr)+  return (FBO n)++-- | Delete an FBO.+deleteFBO :: FBO -> IO ()+deleteFBO (FBO n) = withArray [n] (\ptr -> glDeleteFramebuffers 1 ptr)++-- | Attach a 2D texture to the FBO currently bound to the+-- framebuffer binding target.+attachTex2D :: Attachable a => Tex2D a -> IO ()+attachTex2D t@(Tex2D n) =+  glFramebufferTexture2D GL_FRAMEBUFFER (attachPoint t) GL_TEXTURE_2D n 0++-- | Attach one of the sides of a cubemap texture to the FBO currently bound+-- to the framebuffer binding target.+attachCubeMap :: Attachable a => CubeMap a -> Side -> IO ()+attachCubeMap cm@(CubeMap n) side =+  glFramebufferTexture2D+    GL_FRAMEBUFFER+    (attachPoint cm)+    (side cubeSideCodes)+    n+    0++cubeSideCodes :: Cube GLenum+cubeSideCodes = Cube+  { cubeLeft   = GL_TEXTURE_CUBE_MAP_NEGATIVE_X+  , cubeRight  = GL_TEXTURE_CUBE_MAP_POSITIVE_X+  , cubeTop    = GL_TEXTURE_CUBE_MAP_POSITIVE_Y+  , cubeBottom = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y+  , cubeFront  = GL_TEXTURE_CUBE_MAP_POSITIVE_Z+  , cubeBack   = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }++-- | Attach an RBO to the FBO currently bound to the framebuffer binding+-- target.+attachRBO :: Attachable a => RBO a -> IO ()+attachRBO rbo = glFramebufferRenderbuffer+  GL_FRAMEBUFFER (attachPoint rbo) GL_RENDERBUFFER (unRBO rbo)++-- | Create a new renderbuffer with the specified dimensions.+newRBO :: InternalFormat a => Int -> Int -> IO (RBO a)+newRBO w h = do+  n <- alloca (\ptr -> glGenRenderbuffers 1 ptr >> peek ptr)+  rbo <- return (RBO n)+  glBindRenderbuffer GL_RENDERBUFFER n+  glRenderbufferStorage+    GL_RENDERBUFFER+    (internalFormat rbo)+    (fromIntegral w)+    (fromIntegral h)+  return rbo++-- | Delete an RBO.+deleteRBO :: RBO a -> IO ()+deleteRBO (RBO n) = withArray [n] (\ptr -> glDeleteRenderbuffers 1 ptr)+++-- | Enable alpha blending.+enableBlending :: IO ()+enableBlending = glEnable GL_BLEND++-- | Disable alpha blending.+disableBlending :: IO ()+disableBlending = glDisable GL_BLEND++-- | Set the computation for source and destination blending factors.+setBlendFactors :: BlendFactor -> BlendFactor -> IO ()+setBlendFactors s d = glBlendFunc (toGL s) (toGL d)++-- | Set the overall blending function.+setBlendEquation :: BlendEquation -> IO ()+setBlendEquation e = glBlendEquation (toGL e)++++-- | Check for a GL Error.+getGLError :: IO (Maybe GLError)+getGLError = do+  n <- glGetError+  return $ case n of+    GL_NO_ERROR -> Nothing+    GL_INVALID_ENUM -> Just InvalidEnum+    GL_INVALID_VALUE -> Just InvalidValue+    GL_INVALID_OPERATION -> Just InvalidOperation+    GL_INVALID_FRAMEBUFFER_OPERATION -> Just InvalidFramebufferOperation+    GL_OUT_OF_MEMORY -> Just OutOfMemory+    _ -> error ("unknown GL error " ++ show n)
+ LICENSE view
@@ -0,0 +1,24 @@+Copyright (c) 2015 Evan Rinehart++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ lowgl.cabal view
@@ -0,0 +1,76 @@+-- Initial lowgl.cabal generated by cabal init.  For further documentation,+--  see http://haskell.org/cabal/users-guide/++-- The name of the package.+name:                lowgl++-- The package version.  See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary:      +-+------- breaking API changes+--                   | | +----- non-breaking API additions+--                   | | | +--- code changes with no API change+version:             0.1.0.0++-- A short (one-line) description of the package.+synopsis:            Basic gl wrapper and reference++-- A longer description of the package.+description:         This library exposes a vastly simplified subset of OpenGL that is hopefully still complete enough for many purposes, such as following tutorials, making simple games, and demos.++-- The license under which the package is released.+license:             BSD2++-- The file containing the license text.+license-file:        LICENSE++-- The package author(s).+author:              Evan Rinehart++-- An email address to which users can send suggestions, bug reports, and +-- patches.+maintainer:          evanrinehart@gmail.com++-- A copyright notice.+-- copyright:           ++category:            Graphics++build-type:          Simple++-- Extra files to be distributed with the package, such as examples or a +-- README.+-- extra-source-files:  ++-- Constraint on the version of Cabal needed to build this package.+cabal-version:       >=1.10+++library+  -- Modules exported by the library.+  exposed-modules:     Graphics.GL.Low+  +  -- Modules included in this library but not exported.+  -- other-modules:       +  +  -- LANGUAGE extensions used by modules in this package.+  -- other-extensions:    +  +  -- Other library packages from which modules are imported.+  build-depends:       base >=4.7 && <4.8, vector >=0.10 && <0.11, linear >=1.16 && <1.17, gl >=0.6 && <0.7, data-default+  +  -- Directories containing source files.+  -- hs-source-dirs:      +  +  -- Base language which the package is written in.+  default-language:    Haskell2010+  +  +source-repository head+  type: git+  location: https://github.com/evanrinehart/lowgl++source-repository this+  type: git+  location: https://github.com/evanrinehart/lowgl+  tag: 0.1.0.0