packages feed

lowgl 0.3.1.0 → 0.3.1.1

raw patch · 12 files changed

+934/−728 lines, 12 filesdep ~basedep ~linear

Dependency ranges changed: base, linear

Files

Graphics/GL/Low.hs view
@@ -14,285 +14,45 @@   -- 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.+  -- "Graphics.GL.Low.EntirePictureUpFront"   --   -- This library uses the `gl' package for raw bindings to OpenGL and the   -- `linear' package for matrices.--  -- * Example   ---  -- | The hello world program shows a white triangle on a black background.-  -- It uses the packages `GLFW-b' and `monad-loops'. Note that it forces a-  -- 3.2 core profile when setting up the context through GLFW.   ---  -- @-  -- module Main where-  ---  -- import Control.Monad.Loops (whileM_)-  -- import Data.Functor ((\<$\>))-  -- import qualified Data.Vector.Storable as V-  -- -  -- import qualified Graphics.UI.GLFW as GLFW-  -- import Graphics.GL.Low-  -- -  -- -- GLFW will be the shell of the demo-  -- main = do-  --   GLFW.init-  --   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)-  --   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)-  --   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)-  --   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)-  --   mwin <- GLFW.createWindow 640 480 \"Hello World\" Nothing Nothing-  --   case mwin of-  --     Nothing  -> putStrLn "createWindow failed"-  --     Just win -> do-  --       GLFW.makeContextCurrent (Just win)-  --       GLFW.swapInterval 1-  --       (vao, prog) <- setup -- load and configure objects-  --       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do-  --         GLFW.pollEvents-  --         draw vao prog -- render-  --         GLFW.swapBuffers win-  -- -  -- setup = do-  --   -- establish a VAO-  --   vao <- newVAO-  --   bindVAO vao-  --   -- load shader program-  --   vsource <- readFile "hello.vert"-  --   fsource <- readFile "hello.frag"-  --   prog <- newProgram vsource fsource-  --   useProgram prog-  --   -- load vertex data: three 2D vertex positions-  --   let blob = V.fromList-  --         [ -0.5, -0.5-  --         ,    0,  0.5-  --         ,  0.5, -0.5 ] :: V.Vector Float-  --   vbo <- newVBO blob StaticDraw-  --   bindVBO vbo-  --   -- connect program to vertex data via the VAO-  --   setVertexLayout [Attrib "position" 2 GLFloat]-  --   return (vao, prog)-  -- -  -- draw vao prog = do-  --   clearColorBuffer (0,0,0)-  --   bindVAO vao-  --   useProgram prog-  --   drawTriangles 3-  -- @-  ---  -- The vertex shader file looks like-  ---  -- @-  -- #version 150-  ---  -- in vec2 position;-  ---  -- void main()-  -- {-  --    gl_Position = vec4(position, 0.0, 1.0);-  -- }-  -- @-  ---  -- And the corresponding fragment shader file-  ---  -- @-  -- #version 150-  ---  -- out vec4 outColor;-  ---  -- void main()-  -- {-  --   outColor = vec4(1.0, 1.0, 1.0, 1.0);-  -- }-  -- @-  ---  -- And the output should look like-  ---  -- <<hello_world.png Hello World>>--  -- * OpenGL API Basically-  ---  -- | <https://www.opengl.org/registry/doc/glspec32.core.20090803.pdf The spec>-  -- for OpenGL 3.2 is actually quite readable and is worth reviewing.-  -- The following is my synopsis of things which roughly coincide with the-  -- simplified OpenGL ES 2.0.--  -- ** 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:+  -- See specific modules for topic-specific docs and example code   ---  -- - 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)+  -- @"Graphics.GL.Low.VAO"@   ---  -- (not binding targets but similar)+  -- @"Graphics.GL.Low.BufferObject"@   ---  -- - Shader program "in use"-  -- - Texture units-  -- - Current active texture unit-  -- - Image attachment points of an FBO--  -- ** Shader Programs-  -- | See "Graphics.GL.Low.Shader"--  -- ** 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 vertex inputs 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.+  -- @"Graphics.GL.Low.Shader"@   ---  -- 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 ('setVertexLayout') 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).+  -- @"Graphics.GL.Low.VertexAttrib"@   ---  -- When a VAO is bound ('bindVAO') 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 also 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 the current program object with new uniform-  -- values. Among other things, updating the uniforms each frame is the main-  -- way to animate a scene.+  -- @"Graphics.GL.Low.Texture"@   ---  -- 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 in 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 in 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!+  -- @"Graphics.GL.Low.Render"@   ---  -- 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.+  -- @"Graphics.GL.Low.Color"@   ---  -- (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. Also HDR color format.)--  -- ** Depth Testing and Stencil Testing-  -- | The depth test and stencil test use extra buffers in parallel with the-  -- color buffer to cause regions of pixels to not show. It does this by-  -- making a comparison between the depth each pixel and the value present-  -- in those buffers, then updating the buffers as necessary. The stencil-  -- test in particular has many configurable options. See the respective-  -- modules for the "Graphics.GL.Low.Depth" and "Graphics.GL.Low.Stencil"-  -- tests. --  -- ** Scissor Test-  -- | The scissor test, if enabled ('enableScissorTest'), disallows all-  -- rendering outside of a rectangle region of the window called the scissor-  -- box.--  -- ** Coordinate Systems (Mappings)-  -- | There are three transformation mechanisms which work together to get raw-  -- vertex data from VBOs to rasterized primitives somewhere on the window.-  -- You can imagine four coordinate systems between these three transformations-  -- if you want to.+  -- @"Graphics.GL.Low.Depth"@+  -- +  -- @"Graphics.GL.Low.Stencil"@   ---  -- - The __vertex shader__ takes vertex positions as specified in vertex-  -- attributes to clip space. This is how the client code specifies a camera,-  -- movement of objects, and perspective.-  -- - The __perspective division__ or ""W-divide"" takes vertices from clip-  -- space and maps them to normalized device coordinates (NDC) by dividing all-  -- the components of the vertex by that vertex's W component. This allows a-  -- perspective effect to be accomplished in the shader by modifying the W-  -- components. You can't configure this W-division; it just happens.  Note-  -- that if W = 1 for all vertices then this step has no effect. This is-  -- useful for orthographic projections. The resulting geometry will be-  -- clipped to a 2x2x2 cube centered around the origin. You can think of an XY-  -- plane of this cube as the viewport of the final 2D image.-  -- - The configurable __viewport transformation__ ('setViewport') will then-  -- position the viewport somewhere in the window.  This step is necessary-  -- because your window is probably not a 2x2 square.  The viewport-  -- transformation is configured by specifying a rectangular region of your-  -- window where you want the image to map to. The default setting for this is-  -- to fill the entire window with the viewport.  If you didn't previously-  -- account for your aspect ratio then this will have the effect of squishing-  -- the scene, so you need to compensate in the vertex shader.--  -- ** 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.+  -- @"Graphics.GL.Low.Blending"@   ---  -- 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.-+  -- @"Graphics.GL.Low.Framebuffer"@    -- * VAO-  -- | See also "Graphics.GL.Low.VAO"+  -- | See also "Graphics.GL.Low.VAO".   newVAO,   bindVAO,   deleteVAO,   VAO,    -- * Buffer Objects-  -- | See also "Graphics.GL.Low.BufferObject"+  -- | See also "Graphics.GL.Low.BufferObject".   newVBO,   newElementArray,   bindVBO,@@ -303,10 +63,9 @@   VBO,   ElementArray,   UsageHint(..),-  IndexFormat(..),    -- * Shader Program-  -- | See also "Graphics.GL.Low.Shader"+  -- | See also "Graphics.GL.Low.Shader".   newProgram,   newProgramSafe,   useProgram,@@ -326,14 +85,14 @@   ProgramError(..),    -- ** Vertex Attributes-  -- | See also "Graphics.GL.Low.VertexAttrib"+  -- | See also "Graphics.GL.Low.VertexAttrib".   setVertexLayout,   VertexLayout(..),   DataType(..),     -- * Textures-  -- | See also "Graphics.GL.Low.Texture"+  -- | See also "Graphics.GL.Low.Texture".   newTexture2D,   newCubeMap,   newEmptyTexture2D,@@ -355,12 +114,9 @@   Wrapping(..),    -- * Rendering-  -- | See also "Graphics.GL.Low.Render"-+  --   -- ** 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.+  -- | See also "Graphics.GL.Low.Render".   drawPoints,   drawLines,   drawLineStrip,@@ -368,11 +124,6 @@   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,@@ -380,15 +131,23 @@   drawIndexedTriangles,   drawIndexedTriangleStrip,   drawIndexedTriangleFan,+  setViewport,+  enableScissorTest,+  disableScissorTest,+  enableCulling,+  disableCulling,+  Viewport(..),+  Culling(..),+  IndexFormat(..),    -- ** Color Buffer-  -- | See also "Graphics.GL.Low.Color"+  -- | See also "Graphics.GL.Low.Color".   enableColorWriting,   disableColorWriting,   clearColorBuffer,    -- ** Depth Test-  -- | See also "Graphics.GL.Low.Depth"+  -- | See also "Graphics.GL.Low.Depth".   enableDepthTest,   disableDepthTest,   clearDepthBuffer,@@ -403,15 +162,6 @@   StencilFunc(..),   StencilOp(..), -  -- ** Scissor Test-  enableScissorTest,-  disableScissorTest,--  -- ** Facet Culling-  Culling(..),-  enableCulling,-  disableCulling,-   -- ** Blending   -- | See also "Graphics.GL.Low.Blending". @@ -422,12 +172,8 @@   BlendFactor(..),   BlendEquation(..), -  -- ** Viewport-  Viewport(..),-  setViewport,-   -- * Framebuffers-  -- | See also "Graphics.GL.Low.Framebuffer"+  -- | See also "Graphics.GL.Low.Framebuffer".   DefaultFramebuffer(..),   FBO,   bindFramebuffer,
Graphics/GL/Low/Blending.hs view
@@ -1,5 +1,6 @@--- | = Blending--- When blending is enabled, colors written to the color buffer will be+module Graphics.GL.Low.Blending (++-- | When blending is enabled, colors written to the color buffer will be -- blended using a formula with the color already there. The three options -- for the formula are: --@@ -11,136 +12,16 @@ -- factors s and d are computed blending factors which can depend on the alpha -- component of the source pixel, the destination pixel, or a specified -- constant color. See 'basicBlending' for a common choice.------ = Example------ @--- module Main where--- --- import Control.Monad.Loops (whileM_)--- import Data.Functor ((\<$\>))--- import qualified Data.Vector.Storable as V--- import Control.Concurrent.STM--- --- import qualified Graphics.UI.GLFW as GLFW--- import Linear--- import Graphics.GL.Low--- --- main = do---   GLFW.init---   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)---   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)---   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)---   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)---   mwin <- GLFW.createWindow 640 480 \"Blending\" Nothing Nothing---   case mwin of---     Nothing  -> putStrLn "createWindow failed"---     Just win -> do---       GLFW.makeContextCurrent (Just win)---       GLFW.swapInterval 1---       shouldSwap <- newTVarIO False---       (GLFW.setKeyCallback win . Just)---         (\_ _ _ _ _ -> atomically (modifyTVar shouldSwap not))---       (vao, prog) <- setup---       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do---         GLFW.pollEvents---         draw vao prog shouldSwap---         GLFW.swapBuffers win--- --- setup = do---   vao <- newVAO---   bindVAO vao---   vsource <- readFile "blending.vert"---   fsource <- readFile "blending.frag"---   prog <- newProgram vsource fsource---   useProgram prog---   let blob = V.fromList---         [ -0.5,  0.5---         ,  0.5,    0---         , -0.5, -0.5 ] :: V.Vector Float---   vbo <- newVBO blob StaticDraw---   bindVBO vbo---   setVertexLayout [Attrib "position" 2 GLFloat]---   enableBlending basicBlending---   return (vao, prog)--- --- draw vao prog shouldSwap = do---   clearColorBuffer (0,0,0)---   yes <- readTVarIO shouldSwap---   if yes---     then sequence [drawRed, drawGreen]---     else sequence [drawGreen, drawRed]--- --- drawGreen = do---   setUniform3f "color" [V3 0 1 0]---   setUniform1f "alpha" [0.5]---   setUniform44 "move" [eye4]---   drawTriangles 3--- --- drawRed = do---   let ninety = pi/2---   let move = mkTransformation (axisAngle (V3 0 0 1) ninety) (V3 0.25 0.5 0)---   setUniform3f "color" [V3 1 0 0]---   setUniform1f "alpha" [0.5]---   setUniform44 "move" [transpose move]---   drawTriangles 3--- @--- --- blending.vert------ @--- #version 150--- --- in vec3 Color;--- in float Alpha;--- out vec4 outColor;--- --- void main()--- {---     outColor = vec4(Color, Alpha);--- }--- @------ blending.frag------ @--- #version 150--- --- uniform vec3 color;--- uniform float alpha;--- uniform mat4 move;--- --- in vec2 position;--- out vec3 Color;--- out float Alpha;--- --- void main()--- {---     gl_Position = move * vec4(position, 0.0, 1.0);---     Color = color;---     Alpha = alpha;--- }--- @------ This program draws two half-transparent shapes. When you press a key they--- are rendered in the opposite order. This makes one appear as if it were in--- front of the other. Because the depth test (see "Graphics.GL.Low.Depth")--- must be disabled while using this kind of blending, there may be significant--- overdraw in areas with many blending layers. This can harm performance.--- Also the order-dependency can make using alpha blending in a 3D scene--- complex or impossible. It may make more sense to use an off-screen render--- pass (see "Graphics.GL.Low.Framebuffer") and an appropriate shader to--- simulate transparency effects.------ <<blending1.png Blending Before>> <<blending2.png Blending After>> -module Graphics.GL.Low.Blending (   enableBlending,   disableBlending,   basicBlending,   Blending(..),   BlendFactor(..),   BlendEquation(..)++  -- * Example+  -- $example ) where  import Data.Default@@ -243,3 +124,124 @@   toGL BlendOneMinusConstantAlpha = GL_ONE_MINUS_CONSTANT_ALPHA  +-- $example+--+-- <<blending1.png Blending Before>> <<blending2.png Blending After>>+--+-- This program draws two half-transparent shapes. When you press a key they+-- are rendered in the opposite order. This makes one appear as if it were in+-- front of the other. Because the depth test (see "Graphics.GL.Low.Depth")+-- must be disabled while using this kind of blending, there may be significant+-- overdraw in areas with many blending layers. This can harm performance.+-- Also the order-dependency can make using alpha blending in a 3D scene+-- complex or impossible. It may make more sense to use an off-screen render+-- pass (see "Graphics.GL.Low.Framebuffer") and an appropriate shader to+-- simulate transparency effects.+--+-- @+-- module Main where+-- +-- import Control.Monad.Loops (whileM_)+-- import Data.Functor ((\<$\>))+-- import qualified Data.Vector.Storable as V+-- import Control.Concurrent.STM+-- +-- import qualified Graphics.UI.GLFW as GLFW+-- import Linear+-- import Graphics.GL.Low+-- +-- main = do+--   GLFW.init+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)+--   mwin <- GLFW.createWindow 640 480 \"Blending\" Nothing Nothing+--   case mwin of+--     Nothing  -> putStrLn "createWindow failed"+--     Just win -> do+--       GLFW.makeContextCurrent (Just win)+--       GLFW.swapInterval 1+--       shouldSwap <- newTVarIO False+--       (GLFW.setKeyCallback win . Just)+--         (\_ _ _ _ _ -> atomically (modifyTVar shouldSwap not))+--       (vao, prog) <- setup+--       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do+--         GLFW.pollEvents+--         draw vao prog shouldSwap+--         GLFW.swapBuffers win+-- +-- setup = do+--   vao <- newVAO+--   bindVAO vao+--   vsource <- readFile "blending.vert"+--   fsource <- readFile "blending.frag"+--   prog <- newProgram vsource fsource+--   useProgram prog+--   let blob = V.fromList+--         [ -0.5,  0.5+--         ,  0.5,    0+--         , -0.5, -0.5 ] :: V.Vector Float+--   vbo <- newVBO blob StaticDraw+--   bindVBO vbo+--   setVertexLayout [Attrib "position" 2 GLFloat]+--   enableBlending basicBlending+--   return (vao, prog)+-- +-- draw vao prog shouldSwap = do+--   clearColorBuffer (0,0,0)+--   yes <- readTVarIO shouldSwap+--   if yes+--     then sequence [drawRed, drawGreen]+--     else sequence [drawGreen, drawRed]+-- +-- drawGreen = do+--   setUniform3f "color" [V3 0 1 0]+--   setUniform1f "alpha" [0.5]+--   setUniform44 "move" [eye4]+--   drawTriangles 3+-- +-- drawRed = do+--   let ninety = pi/2+--   let move = mkTransformation (axisAngle (V3 0 0 1) ninety) (V3 0.25 0.5 0)+--   setUniform3f "color" [V3 1 0 0]+--   setUniform1f "alpha" [0.5]+--   setUniform44 "move" [transpose move]+--   drawTriangles 3+-- @+-- +-- blending.vert+--+-- @+-- #version 150+-- +-- in vec3 Color;+-- in float Alpha;+-- out vec4 outColor;+-- +-- void main()+-- {+--     outColor = vec4(Color, Alpha);+-- }+-- @+--+-- blending.frag+--+-- @+-- #version 150+-- +-- uniform vec3 color;+-- uniform float alpha;+-- uniform mat4 move;+-- +-- in vec2 position;+-- out vec3 Color;+-- out float Alpha;+-- +-- void main()+-- {+--     gl_Position = move * vec4(position, 0.0, 1.0);+--     Color = color;+--     Alpha = alpha;+-- }+-- @
Graphics/GL/Low/BufferObject.hs view
@@ -2,13 +2,16 @@  -- | Buffer Objects are objects for holding arbitrary blobs of bytes. This -- library exposes two types of buffer objects: VBOs and ElementArrays.------ = VBO------ Vertex Buffer Objects (VBO) contain data for a sequence of vertices. A++module Graphics.GL.Low.BufferObject (++-- * VBO++-- | Vertex Buffer Objects (VBO) contain data for a sequence of vertices. A -- vertex shader interprets the data for each vertex by mapping the attributes -- of the vertex (position, normal vector, etc) to input variables using the--- VAO. /VBOs have the data which is used as input to the vertex shader according to the configuration of the VAO/.+-- VAO. VBOs have the data which is used as input to the vertex shader+-- according to the configuration of the VAO/. -- -- Example VBO contents: --@@ -16,10 +19,10 @@ -- -- The shader will interpret those parts of the VBO as illustrated only after -- appropiately configuring a VAO. See "Graphics.GL.Low.VAO".------ = ElementArray------ Element arrays are buffer objects that contain a sequence of indices. When++-- * ElementArray++-- | Element arrays are buffer objects that contain a sequence of indices. When -- using indexed rendering, the bound element array determines the order that -- the vertices in the VBOs are visited to construct primitives. This allows -- sharing vertices in cases that many vertices overlap with each other. OpenGL@@ -37,17 +40,18 @@ -- the primitive render commands will simply traverse the vertices in order -- specified in the VBOs. -module Graphics.GL.Low.BufferObject (-  VBO,-  ElementArray,-  UsageHint(..),+-- * Documentation+   newVBO,   updateVBO,   bindVBO,   newElementArray,   updateElementArray,   bindElementArray,-  deleteBufferObject+  deleteBufferObject,+  VBO,+  ElementArray,+  UsageHint(..) ) where  import Foreign.Ptr
+ Graphics/GL/Low/EntirePictureUpFront.hs view
@@ -0,0 +1,277 @@+module Graphics.GL.Low.EntirePictureUpFront (++  -- * OpenGL API Basically+  --+  -- | <https://www.opengl.org/registry/doc/glspec32.core.20090803.pdf The spec>+  -- for OpenGL 3.2 is actually quite readable and is worth reviewing.+  -- The following is my synopsis of things which roughly coincide with the+  -- simplified OpenGL ES 2.0.++  -- ** Objects+  -- | Objects may be created and destroyed by client code. They include:+  --+  -- - Vertex Array Object ('Graphics.GL.Low.VAO.VAO')+  -- - Buffer Objects ('Graphics.GL.Low.BufferObject.VBO', 'Graphics.GL.Low.BufferObject.ElementArray')+  -- - Textures ('Graphics.GL.Low.Texture.Tex2D', 'Graphics.GL.Low.Texture.CubeMap')+  -- - Shader 'Graphics.GL.Low.Shader.Program's+  -- - Framebuffer Objects ('Graphics.GL.Low.Framebuffer.FBO')+  -- - Renderbuffer Objects ('Graphics.GL.Low.Framebuffer.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+  -- | See "Graphics.GL.Low.Shader"++  -- ** 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 vertex inputs 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 'Graphics.GL.Low.Shader.useProgram' and+  -- binding a source VBO to the array buffer binding target+  -- ('Graphics.GL.Low.BufferObject.bindVBO') then the bound VAO can be updated+  -- ('Graphics.GL.Low.VertexAttrib.setVertexLayout') 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 ('Graphics.GL.Low.VAO.bindVAO') 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 also 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.+  -- 'Graphics.GL.Low.Shader.setUniform1f'), which updates the current 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+  -- ('Graphics.GL.Texture.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 in many techniques) to utilize an+  -- off-screen render target. To do this create an FBO+  -- ('Graphics.GL.Low.Framebuffer.newFBO'), bind it to the framebuffer binding+  -- target ('Graphics.GL.Low.Framebuffer.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 in 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+  -- ('Graphics.GL.Low.Framebuffer.newRBO') and empty textures+  -- ('Graphics.GL.Low.Texture.newEmptyTexture2D',+  -- 'Graphics.GL.Low.Texture.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. Also HDR color format.)++  -- ** Depth Testing and Stencil Testing+  -- | The depth test and stencil test use extra buffers in parallel with the+  -- color buffer to cause regions of pixels to not show. It does this by+  -- making a comparison between the depth each pixel and the value present+  -- in those buffers, then updating the buffers as necessary. The stencil+  -- test in particular has many configurable options. See the respective+  -- modules for the "Graphics.GL.Low.Depth" and "Graphics.GL.Low.Stencil"+  -- tests. ++  -- ** Scissor Test+  -- | The scissor test, if enabled+  -- ('Graphics.GL.Low.Render.enableScissorTest'), disallows all rendering+  -- outside of a rectangle region of the window called the scissor box.++  -- ** Coordinate Systems (Mappings)+  -- | There are three transformation mechanisms which work together to get raw+  -- vertex data from VBOs to rasterized primitives somewhere on the window.+  -- You can imagine four coordinate systems between these three transformations+  -- if you want to.+  --+  -- - The __vertex shader__ takes vertex positions as specified in vertex+  -- attributes to clip space. This is how the client code specifies a camera,+  -- movement of objects, and perspective.+  -- - The __perspective division__ or ""W-divide"" takes vertices from clip+  -- space and maps them to normalized device coordinates (NDC) by dividing all+  -- the components of the vertex by that vertex's W component. This allows a+  -- perspective effect to be accomplished in the shader by modifying the W+  -- components. You can't configure this W-division; it just happens.  Note+  -- that if W = 1 for all vertices then this step has no effect. This is+  -- useful for orthographic projections. The resulting geometry will be+  -- clipped to a 2x2x2 cube centered around the origin. You can think of an XY+  -- plane of this cube as the viewport of the final 2D image.+  -- - The configurable __viewport transformation__+  -- ('Graphics.GL.Low.Render.setViewport') will then position the viewport+  -- somewhere in the window.  This step is necessary because your window is+  -- probably not a 2x2 square.  The viewport transformation is configured by+  -- specifying a rectangular region of your window where you want the image to+  -- map to. The default setting for this is to fill the entire window with the+  -- viewport.  If you didn't previously account for your aspect ratio then+  -- this will have the effect of squishing the scene, so you need to+  -- compensate in the vertex shader.++  -- ** Rendering Points, Lines, and Triangles+  -- | The draw family (ex. 'Graphics.GL.Low.Render.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. 'Graphics.GL.Low.Render.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.++  -- * Example+  --+  -- | The hello world program shows a white triangle on a black background.+  -- It uses the packages `GLFW-b' and `monad-loops'. Note that it forces a+  -- 3.2 core profile when setting up the context through GLFW.+  --+  -- @+  -- module Main where+  --+  -- import Control.Monad.Loops (whileM_)+  -- import Data.Functor ((\<$\>))+  -- import qualified Data.Vector.Storable as V+  -- +  -- import qualified Graphics.UI.GLFW as GLFW+  -- import Graphics.GL.Low+  -- +  -- -- GLFW will be the shell of the demo+  -- main = do+  --   GLFW.init+  --   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)+  --   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)+  --   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)+  --   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)+  --   mwin <- GLFW.createWindow 640 480 \"Hello World\" Nothing Nothing+  --   case mwin of+  --     Nothing  -> putStrLn "createWindow failed"+  --     Just win -> do+  --       GLFW.makeContextCurrent (Just win)+  --       GLFW.swapInterval 1+  --       (vao, prog) <- setup -- load and configure objects+  --       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do+  --         GLFW.pollEvents+  --         draw vao prog -- render+  --         GLFW.swapBuffers win+  -- +  -- setup = do+  --   -- establish a VAO+  --   vao <- newVAO+  --   bindVAO vao+  --   -- load shader program+  --   vsource <- readFile "hello.vert"+  --   fsource <- readFile "hello.frag"+  --   prog <- newProgram vsource fsource+  --   useProgram prog+  --   -- load vertex data: three 2D vertex positions+  --   let blob = V.fromList+  --         [ -0.5, -0.5+  --         ,    0,  0.5+  --         ,  0.5, -0.5 ] :: V.Vector Float+  --   vbo <- newVBO blob StaticDraw+  --   bindVBO vbo+  --   -- connect program to vertex data via the VAO+  --   setVertexLayout [Attrib "position" 2 GLFloat]+  --   return (vao, prog)+  -- +  -- draw vao prog = do+  --   clearColorBuffer (0,0,0)+  --   bindVAO vao+  --   useProgram prog+  --   drawTriangles 3+  -- @+  --+  -- The vertex shader file looks like+  --+  -- @+  -- #version 150+  --+  -- in vec2 position;+  --+  -- void main()+  -- {+  --    gl_Position = vec4(position, 0.0, 1.0);+  -- }+  -- @+  --+  -- And the corresponding fragment shader file+  --+  -- @+  -- #version 150+  --+  -- out vec4 outColor;+  --+  -- void main()+  -- {+  --   outColor = vec4(1.0, 1.0, 1.0, 1.0);+  -- }+  -- @+  --+  -- And the output should look like+  --+  -- <<hello_world.png Hello World>>+++) where++
Graphics/GL/Low/Framebuffer.hs view
@@ -1,37 +1,31 @@--- | Framebuffers, FBO, RBO...------ == Example------ This example program renders an animating object to an off-screen--- framebuffer. The resulting texture is then show on a full-screen quad--- with an effect.------ @------ @------ The vertex shader for this program is------ @------ @------ The two fragment shaders, one for the object, one for the effect, are------ @+{-# LANGUAGE RankNTypes #-}+module Graphics.GL.Low.Framebuffer (++-- | By default, rendering commands output graphics to the default framebuffer.+-- This includes the color buffer, the depth buffer, and the stencil buffer. It+-- is possible to render to a texture instead. This is important for many+-- techniques. Rendering to a texture (either color, depth, or depth/stencil)+-- is accomplished by using a framebuffer object (FBO). ----- @+-- The following ritual sets up an FBO with a blank 256x256 color texture for+-- off-screen rendering: -- -- @---+-- do+--   fbo <- newFBO+--   tex <- newEmptyTexture2D 256 256 :: IO (Tex2D RGB)+--   bindFramebuffer fbo+--   attachTex2D tex+--   bindFramebuffer DefaultFramebuffer+--   return (fbo, tex) -- @ ----- And the output looks like------ <<framebuffer.gif Animated screenshot showing post-processing effect>>+-- After binding an FBO to the framebuffer binding target, rendering commands+-- will output to its color attachment and possible depth/stencil attachment+-- if present. An FBO must have a color attachment before rendering. If only+-- the depth results are needed, then you can attach a color RBO instead of+-- a texture to the color attachment point. -{-# LANGUAGE RankNTypes #-}-module Graphics.GL.Low.Framebuffer (   newFBO,   bindFramebuffer,   deleteFBO,@@ -42,7 +36,11 @@   deleteRBO,   FBO,   DefaultFramebuffer(..),-  RBO,+  RBO++  -- * Example+  -- $example+  ) where  import Foreign.Ptr@@ -145,3 +143,157 @@ -- | Delete an RBO. deleteRBO :: RBO a -> IO () deleteRBO (RBO n) = withArray [n] (\ptr -> glDeleteRenderbuffers 1 ptr)+++-- $example+--+-- <<framebuffer.gif Animated screenshot showing post-processing effect>>+--+-- This example program renders an animating object to an off-screen+-- framebuffer. The resulting texture is then shown on a full-screen quad+-- with an effect.+--+-- @+-- module Main where+-- +-- import Control.Monad.Loops (whileM_)+-- import Data.Functor ((\<$\>))+-- import qualified Data.Vector.Storable as V+-- import Data.Maybe (fromJust)+-- import Data.Default+-- import Data.Word+-- +-- import qualified Graphics.UI.GLFW as GLFW+-- import Linear+-- import Graphics.GL.Low+-- +-- main = do+--   GLFW.init+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)+--   mwin <- GLFW.createWindow 640 480 \"Framebuffer\" Nothing Nothing+--   case mwin of+--     Nothing  -> putStrLn "createWindow failed"+--     Just win -> do+--       GLFW.makeContextCurrent (Just win)+--       GLFW.swapInterval 1+--       (vao1, vao2, prog1, prog2, fbo, texture) <- setup+--       whileM_ (not <$> GLFW.windowShouldClose win) $ do+--         GLFW.pollEvents+--         t <- (realToFrac . fromJust) \<$\> GLFW.getTime+--         draw vao1 vao2 prog1 prog2 fbo texture t+--         GLFW.swapBuffers win+-- +-- setup = do+--   -- primary subject+--   vao1 <- newVAO+--   bindVAO vao1+--   let blob = V.fromList+--         [ -0.5, -0.5, 0, 0+--         ,  0,    0.5, 0, 1+--         ,  0.5, -0.5, 1, 1] :: V.Vector Float+--   vbo <- newVBO blob StaticDraw+--   bindVBO vbo+--   vsource  <- readFile "framebuffer.vert"+--   fsource1 <- readFile "framebuffer1.frag"+--   prog1 <- newProgram vsource fsource1+--   useProgram prog1+--   setVertexLayout+--     [ Attrib "position" 2 GLFloat+--     , Attrib "texcoord" 2 GLFloat ]+-- +--   -- full-screen quad to show the post-processed scene+--   vao2 <- newVAO+--   bindVAO vao2+--   let blob = V.fromList+--         [ -1, -1, 0, 0+--         , -1,  1, 0, 1+--         ,  1, -1, 1, 0+--         ,  1,  1, 1, 1] :: V.Vector Float+--   vbo <- newVBO blob StaticDraw+--   bindVBO vbo+--   indices <- newElementArray (V.fromList [0,1,2,3,2,1] :: V.Vector Word8) StaticDraw+--   bindElementArray indices+--   fsource2 <- readFile "framebuffer2.frag"+--   prog2 <- newProgram vsource fsource2+--   useProgram prog2+--   setVertexLayout+--     [ Attrib "position" 2 GLFloat+--     , Attrib "texcoord" 2 GLFloat ]+-- +--   -- create an FBO to render the primary scene on+--   fbo <- newFBO+--   bindFramebuffer fbo+--   texture <- newEmptyTexture2D 640 480 :: IO (Tex2D RGB)+--   bindTexture2D texture+--   setTex2DFiltering Linear+--   attachTex2D texture+--   return (vao1, vao2, prog1, prog2, fbo, texture)+-- +-- draw :: VAO -> VAO -> Program -> Program -> FBO -> Tex2D RGB -> Float -> IO ()+-- draw vao1 vao2 prog1 prog2 fbo texture t = do+--   -- render primary scene to fbo+--   bindVAO vao1+--   bindFramebuffer fbo+--   useProgram prog1+--   clearColorBuffer (0,0,0)+--   setUniform1f "time" [t]+--   drawTriangles 3+-- +--   -- render results to quad on main screen+--   bindVAO vao2+--   bindFramebuffer DefaultFramebuffer+--   useProgram prog2+--   bindTexture2D texture+--   clearColorBuffer (0,0,0)+--   setUniform1f "time" [t]+--   drawIndexedTriangles 6 UByteIndices+-- @+--+-- The vertex shader for this program is+--+-- @+-- #version 150+-- in vec2 position;+-- in vec2 texcoord;+-- out vec2 Texcoord;+-- void main()+-- {+--     gl_Position = vec4(position, 0.0, 1.0);+--     Texcoord = texcoord;+-- }+-- @+--+-- The two fragment shaders, one for the object, one for the effect, are+--+-- @+-- #version 150+-- uniform float time;+-- in vec2 Texcoord;+-- out vec4 outColor;+-- void main()+-- {+--   float t = time;+--   outColor = vec4(+--     fract(Texcoord.x*5) < 0.5 ? sin(t*0.145) : cos(t*0.567),+--     fract(Texcoord.y*5) < 0.5 ? cos(t*0.534) : sin(t*0.321),+--     0.0, 1.0+--   );+-- }+-- @+--+-- @+-- #version 150+-- uniform float time;+-- uniform sampler2D tex;+-- in vec2 Texcoord;+-- out vec4 outColor;+-- +-- void main()+-- {+--   float d = pow(10,(abs(cos(time))+1.5));+--   outColor c = texture(tex, floor(Texcoord*d)/d);+-- }+-- @
Graphics/GL/Low/Render.hs view
@@ -1,7 +1,11 @@ module Graphics.GL.Low.Render (-  Culling(..),-  Viewport(..),-  IndexFormat(..),++  -- * Primitives+  --+  -- | Render various kinds of primitives to the current framebuffer using+  -- the current shader program. The integer argument is the number of+  -- vertices to read from the VBOs via the current VAO.+  --   drawPoints,   drawLines,   drawLineStrip,@@ -9,6 +13,13 @@   drawTriangles,   drawTriangleStrip,   drawTriangleFan,++  -- * Primitives (by index)+  --+  -- | Render various kinds of primitives by traversing the vertices in the+  -- order specified in the current ElementArray. The format argument indicates+  -- the size of each index in the ElementArray.+  --   drawIndexedPoints,   drawIndexedLines,   drawIndexedLineStrip,@@ -16,11 +27,21 @@   drawIndexedTriangles,   drawIndexedTriangleStrip,   drawIndexedTriangleFan,++  -- * Scissor Test   enableScissorTest,   disableScissorTest,++  -- * Facet Culling   enableCulling,   disableCulling,-  setViewport++  -- * Viewport+  setViewport,++  Culling(..),+  Viewport(..),+  IndexFormat(..) ) where  import Foreign.Ptr
Graphics/GL/Low/Shader.hs view
@@ -1,3 +1,6 @@++{-# LANGUAGE DeriveDataTypeable #-}+module Graphics.GL.Low.Shader ( -- | A shader program is composed of two cooperating parts: the vertex program -- and the fragment program. The vertex program is executed once for each -- vertex. The fragment program is executed once for each pixel covered by@@ -28,159 +31,10 @@ -- - a color (this is more complicated in reality but close enough) -- - the depth of the pixel, gl_FragDepth, which will default to the pixel's Z. ----- = Example------ @--- module Main where--- --- import Control.Monad.Loops (whileM_)--- import Data.Functor ((\<$\>))--- import qualified Data.Vector.Storable as V--- import Data.Maybe (fromJust)--- --- import qualified Graphics.UI.GLFW as GLFW--- import Linear--- import Graphics.GL.Low--- --- main = do---   GLFW.init---   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)---   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)---   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)---   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)---   mwin <- GLFW.createWindow 640 480 \"Shaders\" Nothing Nothing---   case mwin of---     Nothing  -> putStrLn "createWindow failed"---     Just win -> do---       GLFW.makeContextCurrent (Just win)---       GLFW.swapInterval 1---       (vao, prog1, prog2, prog3) <- setup---       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do---         GLFW.pollEvents---         t <- (realToFrac . fromJust) \<$\> GLFW.getTime---         draw vao prog1 prog2 prog3 t---         GLFW.swapBuffers win--- --- setup = do---   vao <- newVAO---   bindVAO vao---   vsource <- readFile "shader.vert"---   fsource1 <- readFile "shader1.frag"---   fsource2 <- readFile "shader2.frag"---   fsource3 <- readFile "shader3.frag"---   prog1 <- newProgram vsource fsource1---   prog2 <- newProgram vsource fsource2---   prog3 <- newProgram vsource fsource3---   useProgram prog1---   let blob = V.fromList---         [ -0.4, -0.4, 0, 0---         ,  0,    0.4, 0, 1---         ,  0.4, -0.4, 1, 1] :: V.Vector Float---   vbo <- newVBO blob StaticDraw---   bindVBO vbo---   setVertexLayout---     [ Attrib "position" 2 GLFloat---     , Attrib "location" 2 GLFloat ]---   return (vao, prog1, prog2, prog3)--- --- draw vao prog1 prog2 prog3 t = do---   clearColorBuffer (0,0,0)---   bindVAO vao---   drawThing prog1 t (V3 (-0.5)   0.5    0.0)---   drawThing prog2 t (V3   0.5    0.5    0.0)---   drawThing prog3 t (V3   0.0  (-0.5) (-0.0))--- --- drawThing :: Program -> Float -> V3 Float -> IO ()--- drawThing prog t shift = do---   let angle = t / 5---   let move = mkTransformation (axisAngle (V3 0 0 1) angle) shift---   useProgram prog---   setUniform1f "time" [t]---   setUniform44 "move" [transpose move]---   drawTriangles 3--- @------ Where the vertex shader is------ @--- #version 150--- uniform mat4 move;--- in vec2 position;--- in vec2 location;--- out vec2 Location;--- void main()--- {---     gl_Position = move * vec4(position, 0.0, 1.0);---     Location = location;--- }--- @------ And the three fragment shaders are------ @--- #version 150--- uniform float time;--- in vec2 Location;--- out vec4 outColor;--- void main()--- {---   float x = gl_FragCoord.x / 640;---   float y = gl_FragCoord.y / 480;---   outColor = vec4(---     fract(x*25) < 0.5 ? 1.0 : 0.0,---     fract(y*25) < 0.5 ? 1.0 : 0.0,---     0.0, 1.0---   );--- }--- @------ @--- #version 150--- uniform float time;--- in vec2 Location;--- out vec4 outColor;--- void main()--- {---   outColor = vec4(---     fract(Location.x*10) < 0.5 ? 1.0 : 0.0,---     fract(Location.y*10) < 0.5 ? 1.0 : 0.0,---     0.0, 1.0---   );--- }--- @------ @--- #version 150--- uniform float time;--- in vec2 Location;--- out vec4 outColor;--- void main()--- {---   float t = time;---   outColor = vec4(---     fract(Location.x*5) < 0.5 ? sin(t*3.145) : cos(t*4.567),---     fract(Location.y*5) < 0.5 ? cos(t*6.534) : sin(t*4.321),---     0.0, 1.0---   );--- }--- @------ The output should look like------ <<shaders.gif 3 Different Shaders Animated Demo>>------ Where the window coordinates, the interpolated location on the triangle,--- and the elapsed time are used to color the triangle respectively.-----{-# LANGUAGE DeriveDataTypeable #-}-module Graphics.GL.Low.Shader (-  Program,-  ProgramError(..),-  newProgramSafe,-  deleteProgram,   newProgram,+  newProgramSafe,   useProgram,+  deleteProgram,   setUniform1f,   setUniform2f,   setUniform3f,@@ -191,7 +45,12 @@   setUniform4i,   setUniform44,   setUniform33,-  setUniform22+  setUniform22,+  Program,+  ProgramError(..)++  -- * Example+  -- $example ) where  import Foreign.Ptr@@ -345,3 +204,145 @@         else glAction loc (fromIntegral n) bytes  +-- $example+--+-- <<shaders.gif 3 Different Shaders Animated Demo>>+--+-- This example renders three differently-shaded triangles. The window+-- coordinates, the interpolated location on the triangle, and the elapsed time+-- are used to color the triangles respectively.+--+-- @+-- module Main where+-- +-- import Control.Monad.Loops (whileM_)+-- import Data.Functor ((\<$\>))+-- import qualified Data.Vector.Storable as V+-- import Data.Maybe (fromJust)+-- +-- import qualified Graphics.UI.GLFW as GLFW+-- import Linear+-- import Graphics.GL.Low+-- +-- main = do+--   GLFW.init+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)+--   mwin <- GLFW.createWindow 640 480 \"Shaders\" Nothing Nothing+--   case mwin of+--     Nothing  -> putStrLn "createWindow failed"+--     Just win -> do+--       GLFW.makeContextCurrent (Just win)+--       GLFW.swapInterval 1+--       (vao, prog1, prog2, prog3) <- setup+--       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do+--         GLFW.pollEvents+--         t <- (realToFrac . fromJust) \<$\> GLFW.getTime+--         draw vao prog1 prog2 prog3 t+--         GLFW.swapBuffers win+-- +-- setup = do+--   vao <- newVAO+--   bindVAO vao+--   vsource <- readFile "shader.vert"+--   fsource1 <- readFile "shader1.frag"+--   fsource2 <- readFile "shader2.frag"+--   fsource3 <- readFile "shader3.frag"+--   prog1 <- newProgram vsource fsource1+--   prog2 <- newProgram vsource fsource2+--   prog3 <- newProgram vsource fsource3+--   useProgram prog1+--   let blob = V.fromList+--         [ -0.4, -0.4, 0, 0+--         ,  0,    0.4, 0, 1+--         ,  0.4, -0.4, 1, 1] :: V.Vector Float+--   vbo <- newVBO blob StaticDraw+--   bindVBO vbo+--   setVertexLayout+--     [ Attrib "position" 2 GLFloat+--     , Attrib "location" 2 GLFloat ]+--   return (vao, prog1, prog2, prog3)+-- +-- draw vao prog1 prog2 prog3 t = do+--   clearColorBuffer (0,0,0)+--   bindVAO vao+--   drawThing prog1 t (V3 (-0.5)   0.5    0.0)+--   drawThing prog2 t (V3   0.5    0.5    0.0)+--   drawThing prog3 t (V3   0.0  (-0.5) (-0.0))+-- +-- drawThing :: Program -> Float -> V3 Float -> IO ()+-- drawThing prog t shift = do+--   let angle = t / 5+--   let move = mkTransformation (axisAngle (V3 0 0 1) angle) shift+--   useProgram prog+--   setUniform1f "time" [t]+--   setUniform44 "move" [transpose move]+--   drawTriangles 3+-- @+--+-- Where the vertex shader is+--+-- @+-- #version 150+-- uniform mat4 move;+-- in vec2 position;+-- in vec2 location;+-- out vec2 Location;+-- void main()+-- {+--     gl_Position = move * vec4(position, 0.0, 1.0);+--     Location = location;+-- }+-- @+--+-- And the three fragment shaders are+--+-- @+-- #version 150+-- uniform float time;+-- in vec2 Location;+-- out vec4 outColor;+-- void main()+-- {+--   float x = gl_FragCoord.x / 640;+--   float y = gl_FragCoord.y / 480;+--   outColor = vec4(+--     fract(x*25) < 0.5 ? 1.0 : 0.0,+--     fract(y*25) < 0.5 ? 1.0 : 0.0,+--     0.0, 1.0+--   );+-- }+-- @+--+-- @+-- #version 150+-- uniform float time;+-- in vec2 Location;+-- out vec4 outColor;+-- void main()+-- {+--   outColor = vec4(+--     fract(Location.x*10) < 0.5 ? 1.0 : 0.0,+--     fract(Location.y*10) < 0.5 ? 1.0 : 0.0,+--     0.0, 1.0+--   );+-- }+-- @+--+-- @+-- #version 150+-- uniform float time;+-- in vec2 Location;+-- out vec4 outColor;+-- void main()+-- {+--   float t = time;+--   outColor = vec4(+--     fract(Location.x*5) < 0.5 ? sin(t*3.145) : cos(t*4.567),+--     fract(Location.y*5) < 0.5 ? cos(t*6.534) : sin(t*4.321),+--     0.0, 1.0+--   );+-- }+-- @
Graphics/GL/Low/Stencil.hs view
@@ -1,3 +1,5 @@+module Graphics.GL.Low.Stencil (+ -- | The stencil test is like a configurable depth test with a dedicated -- additional buffer. Like the depth test, if the stencil test fails then the -- pixel being tested will not be rendered. The stencil test happens before the@@ -17,7 +19,6 @@ -- - When the stencil test passes then the depth test fails or -- - When both tests pass. -module Graphics.GL.Low.Stencil (   enableStencil,   disableStencil,   clearStencilBuffer,
Graphics/GL/Low/Texture.hs view
@@ -1,3 +1,5 @@+module Graphics.GL.Low.Texture (+ -- | Textures are objects that contain image data that can be sampled by -- a shader. While an obvious application of this is texture mapping, there -- are many other uses for textures (the image data doesn't have to be an@@ -11,113 +13,7 @@ -- points to by setting it using the 'Graphics.GL.Low.Shader.setUniform1i' -- command. You can avoid dealing with active texture units if theres only one -- sampler because the default unit is zero.------ == Example------ This example loads a 256x256 PNG file with JuicyPixels and displays the--- image on a square. Of course without a correction for aspect ratio the--- square will only be square if you adjust your window to be square.------ @--- module Main where--- --- import Control.Monad.Loops (whileM_)--- import Data.Functor ((\<$\>))--- import qualified Data.Vector.Storable as V--- import Codec.Picture--- import Data.Word--- --- import qualified Graphics.UI.GLFW as GLFW--- import Linear--- import Graphics.GL.Low--- --- main = do---   GLFW.init---   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)---   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)---   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)---   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)---   mwin <- GLFW.createWindow 640 480 \"Texture\" Nothing Nothing---   case mwin of---     Nothing  -> putStrLn "createWindow failed"---     Just win -> do---       GLFW.makeContextCurrent (Just win)---       GLFW.swapInterval 1---       (vao, prog, texture) <- setup---       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do---         GLFW.pollEvents---         draw vao prog texture---         GLFW.swapBuffers win--- --- setup = do---   -- establish a VAO---   vao <- newVAO---   bindVAO vao---   -- load the shader---   vsource <- readFile "texture.vert"---   fsource <- readFile "texture.frag"---   prog <- newProgram vsource fsource---   useProgram prog---   -- load the vertices---   let blob = V.fromList -- a quad has four vertices---         [ -0.5, -0.5, 0, 1---         , -0.5,  0.5, 0, 0---         ,  0.5, -0.5, 1, 1---         ,  0.5,  0.5, 1, 0 ] :: V.Vector Float---   vbo <- newVBO blob StaticDraw---   bindVBO vbo---   setVertexLayout [ Attrib "position" 2 GLFloat---                   , Attrib "texcoord" 2 GLFloat ]---   -- load the element array to draw a quad with two triangles---   indices <- newElementArray (V.fromList [0,1,2,3,2,1] :: V.Vector Word8) StaticDraw---   bindElementArray indices---   -- load the texture with JuicyPixels---   let fromRight (Right x) = x---   ImageRGBA8 (Image w h image) <- fromRight \<$\> readImage "logo.png"---   texture <- newTexture2D image (Dimensions w h) :: IO (Tex2D RGBA)---   setTex2DFiltering Linear---   return (vao, prog, texture)--- --- draw vao prog texture = do---   clearColorBuffer (0.5, 0.5, 0.5)---   bindVAO vao---   useProgram prog---   bindTexture2D texture---   drawIndexedTriangles 6 UByteIndices--- @------ The vertex shader for this example looks like------ @--- #version 150--- in vec2 position;--- in vec2 texcoord;--- out vec2 Texcoord;--- void main()--- {---     gl_Position = vec4(position, 0.0, 1.0);---     Texcoord = texcoord;--- }--- @------ And the fragment shader looks like------ @--- #version 150--- in vec2 Texcoord;--- out vec4 outColor;--- uniform sampler2D tex;--- void main()--- {---   outColor = texture(tex, Texcoord);--- }--- @------ Should produce output like------ <<texture.png Screenshot of Texture Example>> -module Graphics.GL.Low.Texture (   newTexture2D,   newCubeMap,   newEmptyTexture2D,@@ -134,7 +30,11 @@   CubeMap,   Filtering(..),   Wrapping(..),-  Dimensions(..),+  Dimensions(..)++  -- * Example+  -- $example+ ) where  import Foreign.Ptr@@ -330,3 +230,106 @@  instance GLObject (CubeMap a) where   glObjectName (CubeMap n) = fromIntegral n++-- $example+--+-- <<texture.png Screenshot of Texture Example>>+--+-- This example loads a 256x256 PNG file with JuicyPixels and displays the+-- image on a square. Of course without a correction for aspect ratio the+-- square will only be square if you adjust your window to be square.+--+-- @+-- module Main where+-- +-- import Control.Monad.Loops (whileM_)+-- import Data.Functor ((\<$\>))+-- import qualified Data.Vector.Storable as V+-- import Codec.Picture+-- import Data.Word+-- +-- import qualified Graphics.UI.GLFW as GLFW+-- import Linear+-- import Graphics.GL.Low+-- +-- main = do+--   GLFW.init+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)+--   GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 2)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLForwardCompat True)+--   GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)+--   mwin <- GLFW.createWindow 640 480 \"Texture\" Nothing Nothing+--   case mwin of+--     Nothing  -> putStrLn "createWindow failed"+--     Just win -> do+--       GLFW.makeContextCurrent (Just win)+--       GLFW.swapInterval 1+--       (vao, prog, texture) <- setup+--       whileM_ (not \<$\> GLFW.windowShouldClose win) $ do+--         GLFW.pollEvents+--         draw vao prog texture+--         GLFW.swapBuffers win+-- +-- setup = do+--   -- establish a VAO+--   vao <- newVAO+--   bindVAO vao+--   -- load the shader+--   vsource <- readFile "texture.vert"+--   fsource <- readFile "texture.frag"+--   prog <- newProgram vsource fsource+--   useProgram prog+--   -- load the vertices+--   let blob = V.fromList -- a quad has four vertices+--         [ -0.5, -0.5, 0, 1+--         , -0.5,  0.5, 0, 0+--         ,  0.5, -0.5, 1, 1+--         ,  0.5,  0.5, 1, 0 ] :: V.Vector Float+--   vbo <- newVBO blob StaticDraw+--   bindVBO vbo+--   setVertexLayout [ Attrib "position" 2 GLFloat+--                   , Attrib "texcoord" 2 GLFloat ]+--   -- load the element array to draw a quad with two triangles+--   indices <- newElementArray (V.fromList [0,1,2,3,2,1] :: V.Vector Word8) StaticDraw+--   bindElementArray indices+--   -- load the texture with JuicyPixels+--   let fromRight (Right x) = x+--   ImageRGBA8 (Image w h image) <- fromRight \<$\> readImage "logo.png"+--   texture <- newTexture2D image (Dimensions w h) :: IO (Tex2D RGBA)+--   setTex2DFiltering Linear+--   return (vao, prog, texture)+-- +-- draw vao prog texture = do+--   clearColorBuffer (0.5, 0.5, 0.5)+--   bindVAO vao+--   useProgram prog+--   bindTexture2D texture+--   drawIndexedTriangles 6 UByteIndices+-- @+--+-- The vertex shader for this example looks like+--+-- @+-- #version 150+-- in vec2 position;+-- in vec2 texcoord;+-- out vec2 Texcoord;+-- void main()+-- {+--     gl_Position = vec4(position, 0.0, 1.0);+--     Texcoord = texcoord;+-- }+-- @+--+-- And the fragment shader looks like+--+-- @+-- #version 150+-- in vec2 Texcoord;+-- out vec4 outColor;+-- uniform sampler2D tex;+-- void main()+-- {+--   outColor = texture(tex, Texcoord);+-- }+-- @
Graphics/GL/Low/VAO.hs view
@@ -1,3 +1,6 @@++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@@ -52,12 +55,10 @@ -- } -- @ -module Graphics.GL.Low.VAO -(-  VAO,   newVAO,   deleteVAO,-  bindVAO+  bindVAO,+  VAO ) where  import Foreign.Storable
Graphics/GL/Low/VertexAttrib.hs view
@@ -1,9 +1,8 @@+module Graphics.GL.Low.VertexAttrib ( -- | To feed vertices into the vertex shader, the layout of a vertex must be -- specified in the current VAO for the current shader program. Make a list of -- LayoutElements and use 'setVertexLayout' on it as seen below. ----- == Example--- -- @ -- setVertexLayout --   [ Attrib "position"  3 GLFloat   -- first 12 bytes maps to: in vec3 position;@@ -17,8 +16,6 @@ -- In this example four mappings from the current VBO to the variables -- in the current Program will be established in the current VAO. --module Graphics.GL.Low.VertexAttrib (   setVertexLayout,   VertexLayout(..),   DataType(..)
lowgl.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.3.1.0+version:             0.3.1.1  -- A short (one-line) description of the package. synopsis:            Basic gl wrapper and reference@@ -56,6 +56,7 @@                        Graphics.GL.Low.Cube                        Graphics.GL.Low.Depth                        Graphics.GL.Low.Error+                       Graphics.GL.Low.EntirePictureUpFront                        Graphics.GL.Low.Framebuffer                        Graphics.GL.Low.ImageFormat                        Graphics.GL.Low.Render@@ -89,4 +90,4 @@ source-repository this   type: git   location: https://github.com/evanrinehart/lowgl-  tag: 0.3.1.0+  tag: 0.3.1.1