Skip to content

Commit 2a727e8

Browse files
committed
First working version
1 parent 1bf6095 commit 2a727e8

File tree

20 files changed

+1086
-2
lines changed

20 files changed

+1086
-2
lines changed

LambdaGL.cabal

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
cabal-version: 1.12
2+
3+
-- This file has been generated from package.yaml by hpack version 0.31.2.
4+
--
5+
-- see: https://github.com/sol/hpack
6+
--
7+
-- hash: f73f63d782e90ba60475dcbed3119c57dae075854d91e89730b10b494e3c20da
8+
9+
name: LambdaGL
10+
version: 0.1.0.0
11+
category: Web
12+
homepage: https://github.com/Simre1/LambdaGL#readme
13+
author: Author name here
14+
maintainer: example@example.com
15+
copyright: 2020 Author name here
16+
license: BSD3
17+
license-file: LICENSE
18+
build-type: Simple
19+
extra-source-files:
20+
README.md
21+
22+
library
23+
exposed-modules:
24+
Data.HList
25+
Data.SizedVector
26+
Data.StateAction
27+
Graphics.LambdaGL.Buffer
28+
Graphics.LambdaGL.Draw
29+
Graphics.LambdaGL.Program
30+
Graphics.LambdaGL.Shader
31+
Graphics.LambdaGL.Texture
32+
Graphics.LambdaGL.Types.List
33+
Graphics.LambdaGL.Types.Shared
34+
Graphics.LambdaGL.Uniform
35+
Graphics.LambdaGL.Utility
36+
other-modules:
37+
Paths_LambdaGL
38+
hs-source-dirs:
39+
src
40+
default-extensions: OverloadedStrings GADTs TypeFamilies DataKinds TypeOperators PatternSynonyms FlexibleInstances FlexibleContexts MultiParamTypeClasses RankNTypes ScopedTypeVariables FunctionalDependencies TypeApplications OverloadedLists PolyKinds UndecidableInstances GeneralisedNewtypeDeriving StandaloneDeriving FunctionalDependencies ConstraintKinds
41+
build-depends:
42+
OpenGL
43+
, StateVar
44+
, base >=4.7 && <5
45+
, bytestring
46+
, text
47+
, vector
48+
default-language: Haskell2010
49+
50+
executable example
51+
main-is: Main.hs
52+
other-modules:
53+
Example01
54+
Paths_LambdaGL
55+
hs-source-dirs:
56+
example
57+
default-extensions: OverloadedStrings GADTs TypeFamilies DataKinds TypeOperators PatternSynonyms FlexibleInstances FlexibleContexts MultiParamTypeClasses RankNTypes ScopedTypeVariables FunctionalDependencies TypeApplications OverloadedLists PolyKinds UndecidableInstances GeneralisedNewtypeDeriving StandaloneDeriving FunctionalDependencies ConstraintKinds
58+
build-depends:
59+
LambdaGL
60+
, OpenGL
61+
, StateVar
62+
, base >=4.7 && <5
63+
, bytestring
64+
, sdl2
65+
, text
66+
, vector
67+
default-language: Haskell2010

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,19 @@
1-
# typed-gl
2-
Experimental wrapper for opengl in haskell.
1+
# LambdaGL
2+
3+
LambdaGL tries to simplify the task of interfacing with OpenGL less difficult by utilising advanced types.
4+
5+
Right now, this project is in its infancy and not usable for any serious application.
6+
7+
Feel free to check out the code as well as the example.
8+
9+
## Build & Execute Example
10+
11+
I am using stack as my build tool.
12+
13+
``
14+
git clone https://github.com/Simre1/LambdaGL.git
15+
16+
stack build
17+
18+
stack exec example
19+
``

Setup.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

example/Example01.hs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
module Example01 where
2+
3+
import qualified Data.ByteString as B
4+
import qualified Data.Vector.Storable as VS
5+
import Data.IORef
6+
7+
import Data.SizedVector
8+
import Data.HList
9+
10+
import Graphics.LambdaGL.Buffer
11+
import Graphics.LambdaGL.Program
12+
import Graphics.LambdaGL.Draw
13+
import Graphics.LambdaGL.Shader
14+
import Graphics.LambdaGL.Texture
15+
import Graphics.LambdaGL.Uniform
16+
import Graphics.LambdaGL.Types.Shared
17+
18+
example01 :: IO (IO ())
19+
example01 = do
20+
-- Timer to use as a uniform.
21+
timer <- newIORef 0
22+
draw <- createDrawAction
23+
pure $ readIORef timer >>= draw >> modifyIORef timer (+1)
24+
25+
createDrawAction :: IO (Int -> IO ())
26+
createDrawAction = do
27+
vertexBuffer :: Buffer '[(D2, Float)] <- createBuffer
28+
writeBuffer vertexBuffer $ VS.fromList $ [HostData (V2 (-1) (-1)) <:> Nil, HostData (V2 (1) (-1)) <:> Nil, HostData (V2 1 1) <:> Nil, HostData (V2 (-1) 1) <:> Nil, HostData (V2 (-1) (-1)) <:> Nil]
29+
30+
vertexShader :: CompiledShader 'Vertex '[] '[] '[(D2, Float)] '[(D2, Float)] <- compileShader $ Shader $ ShaderSource vertexShader
31+
32+
fragmentShader :: CompiledShader 'Fragment '[Named "time" Float] '[Texture NoMipMap TextureNormal D2 RGBA8] '[(D2, Float)] '[] <- compileShader $ Shader $ ShaderSource fragmentShader
33+
34+
texture <- newTexture @NoMipMap @TextureNormal @D2 @RGBA8
35+
36+
bindTexture texture $ do
37+
writeTexture (V2 2 2) $ VS.fromList [V4 0 0 0 255, V4 255 255 255 255, V4 255 255 255 255, V4 0 0 0 255]
38+
39+
program <- createProgram $ TwoShader vertexShader fragmentShader
40+
41+
let uniforms x =
42+
(makeDrawUniform $ (Named x :: Named "time" Float))
43+
44+
let initial = toDrawInput vertexBuffer 0
45+
drawObj <- createDraw program (uniforms 0) initial
46+
pure $ \i -> do
47+
let pI = skipDrawInput @'[(D2, Float)]
48+
runDrawEnv $ do
49+
clearColor $ V4 1 1 1 1
50+
bindLastTexture texture $
51+
draw drawObj (uniforms $ fromIntegral i) pI (DrawOptions TriangleStrip 0 5)
52+
pure ()
53+
54+
fragmentShader :: B.ByteString
55+
fragmentShader =
56+
mconcat . fmap (<> "\n") $
57+
[ "#version 450 core",
58+
"in vec2 fragCoord;",
59+
"out vec4 fragColor;",
60+
"uniform float time;",
61+
"uniform sampler2D tex;",
62+
"void main()",
63+
"{",
64+
"vec4 c = texture(tex, fragCoord);",
65+
"fragColor = vec4(abs(fragCoord) * (sin(time/21) * sin(time/13) + abs(vec2(sin(time/47)))), c.z, 1.0);",
66+
"}"
67+
]
68+
69+
vertexShader :: B.ByteString
70+
vertexShader =
71+
mconcat . fmap (<> "\n") $
72+
[ "#version 430 core",
73+
"layout(location = 0) in vec2 vPosition;",
74+
"out vec2 fragCoord;",
75+
"void main()",
76+
"{",
77+
"gl_Position = vec4(vPosition, 1, 1);",
78+
"fragCoord = vPosition;",
79+
"}"
80+
]

example/Main.hs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
module Main where
2+
3+
import qualified SDL
4+
import qualified Data.StateVar as SV
5+
import qualified Data.Text as T
6+
import qualified Graphics.Rendering.OpenGL as GL
7+
import GHC.Clock
8+
import Control.Concurrent (threadDelay)
9+
import Control.Monad
10+
11+
import Example01
12+
13+
main :: IO ()
14+
main = do
15+
-- Set up SDL window and GL context.
16+
SDL.initializeAll
17+
window <- SDL.createWindow (T.pack "My SDL Application") SDL.defaultWindow {SDL.windowGraphicsContext = SDL.OpenGLContext SDL.defaultOpenGL {SDL.glProfile = SDL.Core SDL.Debug 4 6}}
18+
context <- SDL.glCreateContext window
19+
GL.debugOutput SV.$= GL.Enabled
20+
SDL.HintRenderScaleQuality SV.$= SDL.ScaleLinear
21+
renderQuality <- SV.get SDL.HintRenderScaleQuality
22+
when (renderQuality /= SDL.ScaleLinear) $
23+
putStrLn "Warning: Linear texture filtering not enabled!"
24+
25+
-- Set up example01
26+
drawExample <- example01
27+
28+
-- Start app loop
29+
time <- getMonotonicTime
30+
appLoop time drawExample window
31+
32+
appLoop :: Double -> IO () -> SDL.Window -> IO ()
33+
appLoop time drawExample window = do
34+
35+
-- Poll events to determine if the app should exit.
36+
events <- SDL.pollEvents
37+
let checkForExitEvent event =
38+
case SDL.eventPayload event of
39+
SDL.KeyboardEvent keyboardEvent ->
40+
SDL.keyboardEventKeyMotion keyboardEvent == SDL.Pressed &&
41+
SDL.keysymKeycode (SDL.keyboardEventKeysym keyboardEvent) == SDL.KeycodeEscape
42+
SDL.WindowClosedEvent _ -> True
43+
_ -> False
44+
shouldExit = any checkForExitEvent events
45+
46+
-- Draw the given example.
47+
drawExample
48+
49+
-- Calculate used time to loop at 60FPS
50+
SDL.glSwapWindow window
51+
time2 <- getMonotonicTime
52+
threadDelay ((+) 16600 $ round $ (time - time2) * 1000000)
53+
time3 <- getMonotonicTime
54+
55+
-- Continue unless quit button was pressed.
56+
unless shouldExit (appLoop time3 drawExample window)

package.yaml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: LambdaGL
2+
version: 0.1.0.0
3+
#synopsis:
4+
#description:
5+
homepage: https://github.com/Simre1/LambdaGL#readme
6+
license: BSD3
7+
author: Author name here
8+
maintainer: example@example.com
9+
copyright: 2020 Author name here
10+
category: Web
11+
extra-source-files:
12+
- README.md
13+
14+
dependencies:
15+
- base >= 4.7 && < 5
16+
- OpenGL
17+
- text
18+
- StateVar
19+
- bytestring
20+
- vector
21+
22+
library:
23+
source-dirs: src
24+
25+
executables:
26+
example:
27+
source-dirs: example
28+
main: Main.hs
29+
dependencies:
30+
- sdl2
31+
- LambdaGL
32+
33+
34+
default-extensions:
35+
- OverloadedStrings
36+
- GADTs
37+
- TypeFamilies
38+
- DataKinds
39+
- TypeOperators
40+
- PatternSynonyms
41+
- FlexibleInstances
42+
- FlexibleContexts
43+
- MultiParamTypeClasses
44+
- RankNTypes
45+
- ScopedTypeVariables
46+
- FunctionalDependencies
47+
- TypeApplications
48+
- OverloadedLists
49+
- PolyKinds
50+
- UndecidableInstances
51+
- GeneralisedNewtypeDeriving
52+
- StandaloneDeriving
53+
- FunctionalDependencies
54+
- ConstraintKinds

src/Data/HList.hs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module Data.HList where
2+
3+
import Data.Proxy
4+
import GHC.TypeLits
5+
6+
import Data.Functor.Identity
7+
8+
import Foreign.Storable
9+
import Foreign.Ptr
10+
11+
data HList f (things :: [*]) where
12+
Nil :: HList f '[]
13+
Cons :: f x -> HList f xs -> HList f (x ': xs)
14+
15+
instance Storable (HList f '[]) where
16+
sizeOf _ = 0
17+
alignment _ = 0
18+
peek _ = pure Nil
19+
poke _ _ = pure ()
20+
21+
instance (Storable (f x), Storable (HList f xs)) => Storable (HList f (x ': xs)) where
22+
sizeOf _ = sizeOf (undefined :: f x) + sizeOf (undefined :: HList f xs)
23+
alignment _ = alignment (undefined :: f x) + alignment (undefined :: HList f xs)
24+
peek ptr = do
25+
x <- peek (castPtr ptr)
26+
rest <- peek (castPtr (ptr `plusPtr` sizeOf (undefined :: f x)))
27+
pure $ Cons x rest
28+
poke ptr (Cons fx rest) = do
29+
poke (castPtr ptr) fx
30+
poke (ptr `plusPtr` sizeOf (undefined :: f x)) (rest :: HList f xs)
31+
32+
33+
(<:>) = Cons
34+
infixr 8 <:>

0 commit comments

Comments
 (0)