packages feed

lowgl 0.2.1.0 → 0.2.1.1

raw patch · 9 files changed

+430/−43 lines, 9 files

Files

Graphics/GL/Low.hs view
@@ -1,3 +1,4 @@+-- | Basic low-level GL wrapper and reference. module Graphics.GL.Low (    -- * Overview@@ -40,7 +41,7 @@   --   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 \"Demo\" Nothing Nothing+  --   mwin <- GLFW.createWindow 640 480 \"Hello World\" Nothing Nothing   --   case mwin of   --     Nothing  -> putStrLn "createWindow failed"   --     Just win -> do@@ -107,7 +108,7 @@   --   -- And the output should look like   ---  -- <<demo.png Demo>>+  -- <<hello_world.png Hello World>>    -- * OpenGL API Basically   --@@ -145,16 +146,7 @@   -- - Image attachment points of an FBO    -- ** Shader Programs-  -- | The role of the second half of a shader 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 completely separate from configuring the VAO).-  -- At most one Program can be "in use" at a time.+  -- | See "Graphics.GL.Low.Shader"    -- ** VAO   -- | The VAO is essential. At least one VAO must be created and bound to the
Graphics/GL/Low/Blending.hs view
@@ -1,4 +1,5 @@--- | When blending is enabled, colors written to the color buffer will be+-- | = 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,19 +12,136 @@ -- component of the source pixel, the destination pixel, or a specified -- constant color. See 'basicBlending' for a common choice. ----- The order of rendering matters when using blending. The farther-away--- primitives should be rendered first to get transparent materials to look--- right. This means a depth test is unhelpful when using blending. 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.+-- = Example -- -- @--- blending example program here+-- 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+--   setVertexAttributeLayout [Attrib "position" 2 VFloat]+--   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 where+module Graphics.GL.Low.Blending (+  enableBlending,+  disableBlending,+  basicBlending,+  Blending(..),+  BlendFactor(..),+  BlendEquation(..)+) where  import Data.Default import Graphics.GL
Graphics/GL/Low/BufferObject.hs view
@@ -1,6 +1,42 @@ {-# LANGUAGE ScopedTypeVariables #-}--- | VBO and ElementArrays. Both are buffer objects but are used for two--- different things.++-- | 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+-- 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/.+--+-- Example VBO contents:+--+-- <<vbo.png VBO diagram>>+--+-- 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+-- 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+-- accepts element array objects whose indices are encoded as unsigned bytes,+-- unsigned 16-bit ints, and unsigned 32-bit ints.+--+-- Example ElementArray contents appropriate for render triangles and lines+-- respectively:+--+-- <<element_array.png Element array diagram>>+--+-- See 'Graphics.GL.Low.Render.drawIndexedTriangles' and friends to see which+-- primitives are possible to construct with element arrays. It is not+-- necessary to use element arrays to render. The non-indexed versions of+-- the primitive render commands will simply traverse the vertices in order+-- specified in the VBOs.+ module Graphics.GL.Low.BufferObject (   VBO,   ElementArray,@@ -26,13 +62,10 @@  import Graphics.GL.Low.Classes --- | 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.+-- | Handle to a VBO. 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.+-- | Handle to an element array buffer object. data ElementArray = ElementArray GLuint deriving Show  -- | Usage hint for allocation of buffer object storage.
Graphics/GL/Low/Error.hs view
@@ -1,7 +1,18 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE PatternSynonyms #-}-module Graphics.GL.Low.Error where +-- | If you issue an invalid GL command or run out of memory, the GL+-- implementation may set an internal flag indicating that an error has+-- occurred. You can query this flag ('getGLError') to see if something went+-- wrong with a previous command. If you ignore errors, chances are nothing+-- will happen except perhaps some rendering weirdness. However checking this+-- periodically is a good idea, perhaps once per frame, because it might+-- indicate a bug in your code.+module Graphics.GL.Low.Error (+  GLError(..),+  getGLError,+) where+ import Control.Exception import Data.Typeable @@ -25,7 +36,16 @@   show InvalidFramebufferOperation = "INVALID_FRAMEBUFFER_OPERATION Framebuffer object is not complete"   show OutOfMemory = "Not enough memory left to execute command" --- | Check for a GL Error.+-- | Check for a GL Error. This call has the semantics of a dequeue. If an+-- error is returned, then calling getGLError again may return more errors that+-- have "stacked up." When it returns Nothing then there are no more errors to+-- report. An error indicates that a bug in your code caused incorrect ussage+-- of the API or that the implementation has run out of memory.+--+-- It has been suggested that using this after every single GL command may+-- adversely affect performance (not to mention be very tedious). Since there+-- is no reasonable way to recover from a GL error, a good idea might be to+-- check this once per frame or even less often, and respond with a core dump. getGLError :: IO (Maybe GLError) getGLError = do   n <- glGetError
Graphics/GL/Low/Shader.hs view
@@ -1,3 +1,178 @@+-- | 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+-- a rasterized primitive (actually this is more complicated but close enough).+--+-- The inputs to the vertex program are:+--+-- - a vertex (see "Graphics.GL.Low.VAO")+-- - uniforms+--+-- The outputs of the vertex program are:+--+-- - clip space position of the vertex, gl_Position+-- - any number of variables matching inputs to the fragment program+-- - (if rendering a point, then you can set gl_PointSize)+--+-- The inputs to the fragment program are:+--+-- - the previously mentioned outputs of the vertex program (interpolated)+-- - the window position of the pixel, gl_FragCoord+-- - samplers (see "Graphics.GL.Low.Texture")+-- - uniforms+-- - gl_FrontFacing, true if pixel is part of a front facing triangle+-- - (if rendering a point, then you can use gl_PointCoord)+--+-- The outputs of the fragment program are:+--+-- - 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+--   setVertexAttributeLayout+--     [ Attrib "position" 2 VFloat+--     , Attrib "location" 2 VFloat ]+--   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,@@ -33,11 +208,7 @@ import Graphics.GL.Low.Classes import Graphics.GL.Low.VertexAttrib --- | 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.+-- | Handle to a shader program. newtype Program = Program GLuint deriving Show  -- | Either a vertex shader or a fragment shader.
Graphics/GL/Low/Texture.hs view
@@ -24,7 +24,7 @@ import Data.Vector.Storable import Data.Word import Control.Applicative-import Data.Traversable+import Data.Traversable (sequenceA)  import Graphics.GL 
Graphics/GL/Low/VAO.hs view
@@ -1,3 +1,57 @@+-- | Vertex Array Objects (VAO). Despite having almost no operations of its+-- own, the VAO mechanism is one of the most complex pieces of OpenGL. A VAO+-- has mutable state which associates vertex shader input variables (actually+-- the integer location of the variable) with three things:+--+-- - The VBO to read from.+-- - The position in the each vertex array (in the VBO) to read from.+-- - The interpretation of the bytes found there (32-bit float, 16-bit int, etc).+--+-- You set these VAO parameters with the following dance:+--+-- - Bind a VAO+-- - Bind a VBO+-- - Use a Program+-- - call 'Graphics.GL.Low.VertexAttrib.setVertexAttributeLayout' which will+-- lookup the position of the input variables and issue the appropriate+-- glVertexAttribPointer calls.+--+-- After a VAO is configured against a Program, either can be swapped in or+-- out freely and they will still work when both are swapped in again together.+--+-- An "in-use" program will use whatever VAO is bound for getting its vertex+-- inputs. It is up to the programmer to ensure that the VAO has been+-- configured with the right variable positions for the current program. Two+-- ways to do this are to use a consistent set of variables for all shaders or+-- restrict a set of VAOs to only be allowed with specific Program objects.+--+-- The currently bound VBO is not remembered or restored by binding a VAO, but+-- the currently bound ElementArray is. This detail won't affect you if you+-- always explicitly bind an ElementArray after binding a VAO. Alternatively+-- you can exploit this to bundle particular models and their element arrays+-- as a VAO.+--+-- Diagram of possible VAO contents:+--+-- <<vao.png VAO Diagram>>+--+-- The above VAO would be compatible with the following vertex program:+--+-- @+-- #version 150+-- +-- in vec2 position;+-- in vec3 color;+--+-- out vec3 Color;+-- +-- void main()+-- {+--     gl_Position = vec4(position, 0.0, 1.0);+--     Color = color;+-- }+-- @+ module Graphics.GL.Low.VAO  (   VAO,@@ -13,9 +67,7 @@  import Graphics.GL.Low.Classes --- | 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.+-- | Handle to a VAO. newtype VAO = VAO GLuint deriving Show  instance GLObject VAO where
Graphics/GL/Low/VertexAttrib.hs view
@@ -116,7 +116,8 @@       let total = totalLayout layout       forM_ layout' $ \(name, size, offset, fmt) -> do         attrib <- withCString name $ \ptr -> glGetAttribLocation (fromIntegral p) (castPtr ptr)-        let stride = total - size * sizeOfVertexComponent fmt+        --let stride = total - size * sizeOfVertexComponent fmt+        let stride = total         let norm = isNormalized fmt         glVertexAttribPointer           (fromIntegral attrib)
lowgl.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.2.1.0+version:             0.2.1.1  -- A short (one-line) description of the package. synopsis:            Basic gl wrapper and reference@@ -89,4 +89,4 @@ source-repository this   type: git   location: https://github.com/evanrinehart/lowgl-  tag: 0.2.1.0+  tag: 0.2.1.1