summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKosyrev Serge <_deepfire@feelingofgreen.ru>2018-09-20 03:38:49 +0300
committerKosyrev Serge <_deepfire@feelingofgreen.ru>2018-09-20 03:43:38 +0300
commit5c74819ac632f9a746497621064c9bcfab86eb49 (patch)
tree53f8f96f4f4dfaca16c538660d68175050d93044
parent23937046e4771c32fda6c46e80c593009ce9b769 (diff)
lambdacube-gl-pickint: new executable to test integer picking
-rw-r--r--examples/pickInt.hs184
-rw-r--r--examples/pickInt.json1
-rw-r--r--examples/pickInt.lc21
-rw-r--r--examples/pickIntDraw.json1
-rw-r--r--examples/pickIntDraw.lc21
-rw-r--r--lambdacube-gl.cabal23
6 files changed, 251 insertions, 0 deletions
diff --git a/examples/pickInt.hs b/examples/pickInt.hs
new file mode 100644
index 0000000..2443c8b
--- /dev/null
+++ b/examples/pickInt.hs
@@ -0,0 +1,184 @@
1{-# LANGUAGE PackageImports, LambdaCase, OverloadedStrings, StandaloneDeriving, ViewPatterns #-}
2import Control.Monad
3import Data.Aeson
4import Data.Vect (Mat4(..), Vec3(..), Vec4(..))
5import Graphics.GL.Core33 as GL
6import LambdaCube.GL as LambdaCubeGL
7import LambdaCube.GL.Mesh as LambdaCubeGL
8import Text.Printf
9import "GLFW-b" Graphics.UI.GLFW as GLFW
10import qualified Data.ByteString as SB
11import qualified Data.Map as Map
12import qualified Data.Vect as Vc
13import qualified Data.Vector as V
14import qualified Foreign as F
15import qualified Foreign.C.Types as F
16import qualified LambdaCube.GL.Type as LC
17import qualified LambdaCube.Linear as LCLin
18
19----------------------------------------------------
20-- See: http://lambdacube3d.com/getting-started
21----------------------------------------------------
22
23screenDim :: (,) Int Int
24screenDim = (,) 800 600
25(,) screenW screenH = screenDim
26
27main :: IO ()
28main = do
29 Just pipePickDesc <- decodeStrict <$> SB.readFile "pickInt.json"
30 Just pipeDrawDesc <- decodeStrict <$> SB.readFile "pickIntDraw.json"
31
32 win <- initWindow "LambdaCube 3D integer picking" 800 600
33
34 -- setup render data
35 let inputSchema = makeSchema $ do
36 defObjectArray "objects" Triangles $ do
37 "position" @: Attribute_V2F
38 "id" @: Attribute_Int
39 "color" @: Attribute_V4F
40 defUniforms $ do
41 "viewProj" @: M44F
42
43 storage <- LambdaCubeGL.allocStorage inputSchema
44
45 -- upload geometry to GPU and add to pipeline input
46 LambdaCubeGL.uploadMeshToGPU triangleA >>= LambdaCubeGL.addMeshToObjectArray storage "objects" []
47 LambdaCubeGL.uploadMeshToGPU triangleB >>= LambdaCubeGL.addMeshToObjectArray storage "objects" []
48
49 -- allocate GL pipeline
50 pipePick <- LambdaCubeGL.allocRenderer pipePickDesc
51 pipeDraw <- LambdaCubeGL.allocRenderer pipeDrawDesc
52 errPick <- LambdaCubeGL.setStorage pipePick storage
53 errDraw <- LambdaCubeGL.setStorage pipeDraw storage
54 case (errPick, errDraw) of -- check schema compatibility
55 (Just err, _) -> putStrLn err
56 (_, Just err) -> putStrLn err
57 (Nothing, Nothing) -> loop
58 where loop = do
59 -- update graphics input
60 GLFW.getWindowSize win >>= \(w,h) -> LambdaCubeGL.setScreenSize storage (fromIntegral w) (fromIntegral h)
61 LambdaCubeGL.updateUniforms storage $ do
62 let (,) x y = (,) 0 0
63 cvpos = Vec3 x (-y) 0
64 toScreen = screenM screenW screenH
65 "viewProj" @= pure (mat4ToM44F $! (Vc.fromProjective $! Vc.translation cvpos) Vc..*. toScreen)
66
67 let pickPoints =
68 [ (0, 0) -- should be black
69 , (200, 200) -- ..blue, ffff0000
70 , (600, 400) -- ..red, ff0000ff
71 ] :: [(,) Int Int]
72
73 -- render to render texture
74 LambdaCubeGL.renderFrame pipePick
75 case LC.glOutputs pipePick of
76 [LC.GLOutputRenderTexture (fromIntegral -> fbo) _rendTex] -> do
77 rtexPicks <- collectPicks fbo pickPoints
78 printPicks pickPoints rtexPicks
79 x -> error $ "Unexpected outputs: " <> show x
80
81 -- render to framebuffer & pick
82 LambdaCubeGL.renderFrame pipeDraw
83 colorPicks <- collectPicks 0 pickPoints
84 printPicks pickPoints colorPicks
85
86 GLFW.swapBuffers win
87 GLFW.pollEvents
88
89 let keyIsPressed k = fmap (==KeyState'Pressed) $ GLFW.getKey win k
90 escape <- keyIsPressed Key'Escape
91 if escape then return () else loop
92 collectPicks :: Int -> [(,) Int Int] -> IO [Int]
93 collectPicks fb picks =
94 forM picks $ (fromIntegral <$>) . pickFrameBuffer fb screenDim
95 printPicks pickPoints colorPicks = do
96 forM_ (zip pickPoints colorPicks) $ \((x,y), col)-> do
97 printf "%d:%d: %x " x y col
98 putStrLn ""
99
100 LambdaCubeGL.disposeRenderer pipePick
101 LambdaCubeGL.disposeRenderer pipeDraw
102 LambdaCubeGL.disposeStorage storage
103 GLFW.destroyWindow win
104 GLFW.terminate
105
106deriving instance Show (LC.GLOutput)
107deriving instance Show (LC.GLTexture)
108
109-- geometry data: triangles
110scale = 250.0
111s = scale
112
113triangleA :: LambdaCubeGL.Mesh
114triangleA = Mesh
115 { mAttributes = Map.fromList
116 [ ("position", A_V2F $ V.fromList [V2 s s, V2 s (-s), V2 (-s) (-s)])
117 , ("color", A_V4F $ V.fromList $ take 4 $ repeat $ V4 1 0 0 1)
118 , ("id", A_Int $ V.fromList [1, 1, 1])
119 ]
120 , mPrimitive = P_Triangles
121 }
122
123triangleB :: LambdaCubeGL.Mesh
124triangleB = Mesh
125 { mAttributes = Map.fromList
126 [ ("position", A_V2F $ V.fromList [V2 s s, V2 (-s) (-s), V2 (-s) s])
127 , ("color", A_V4F $ V.fromList $ take 4 $ repeat $ V4 0 0 1 1)
128 , ("id", A_Int $ V.fromList [2, 2, 2])
129 ]
130 , mPrimitive = P_Triangles
131 }
132
133vec4ToV4F :: Vec4 -> LCLin.V4F
134vec4ToV4F (Vc.Vec4 x y z w) = LCLin.V4 x y z w
135
136mat4ToM44F :: Mat4 -> LCLin.M44F
137mat4ToM44F (Mat4 a b c d) = LCLin.V4 (vec4ToV4F a) (vec4ToV4F b) (vec4ToV4F c) (vec4ToV4F d)
138
139screenM :: Int -> Int -> Mat4
140screenM w h = scaleM
141 where (fw, fh) = (fromIntegral w, fromIntegral h)
142 scaleM = Vc.Mat4 (Vc.Vec4 (1/fw) 0 0 0)
143 (Vc.Vec4 0 (1/fh) 0 0)
144 (Vc.Vec4 0 0 1 0)
145 (Vc.Vec4 0 0 0 0.5)
146
147pickFrameBuffer
148 :: Int -- ^ framebuffer
149 -> (,) Int Int -- ^ FB dimensions
150 -> (,) Int Int -- ^ pick coordinates
151 -> IO F.Word32 -- ^ resultant pixel value
152pickFrameBuffer fb (w, h) (x, y) = do
153 glFinish
154 glBindFramebuffer GL_READ_FRAMEBUFFER $ fromIntegral fb
155 glReadBuffer GL_BACK_LEFT
156 withFrameBuffer x (h - y - 1) 1 1 $ \p -> fromIntegral <$> F.peek (F.castPtr p :: F.Ptr F.Word32)
157
158withFrameBuffer :: Int -> Int -> Int -> Int -> (F.Ptr F.Word8 -> IO a) -> IO a
159withFrameBuffer x y w h fn = F.allocaBytes (w*h*4) $ \p -> do
160 glPixelStorei GL_UNPACK_LSB_FIRST 0
161 glPixelStorei GL_UNPACK_SWAP_BYTES 0
162 glPixelStorei GL_UNPACK_ROW_LENGTH $ fromIntegral w
163 glPixelStorei GL_UNPACK_IMAGE_HEIGHT 0
164 glPixelStorei GL_UNPACK_SKIP_ROWS 0
165 glPixelStorei GL_UNPACK_SKIP_PIXELS 0
166 glPixelStorei GL_UNPACK_SKIP_IMAGES 0
167 glPixelStorei GL_UNPACK_ALIGNMENT 1
168 glReadPixels (fromIntegral x) (fromIntegral y) (fromIntegral w) (fromIntegral h) GL_RGBA GL_UNSIGNED_BYTE $ F.castPtr p
169 glPixelStorei GL_UNPACK_ROW_LENGTH 0
170 fn p
171
172initWindow :: String -> Int -> Int -> IO Window
173initWindow title width height = do
174 GLFW.init
175 GLFW.defaultWindowHints
176 mapM_ GLFW.windowHint
177 [ WindowHint'ContextVersionMajor 3
178 , WindowHint'ContextVersionMinor 3
179 , WindowHint'OpenGLProfile OpenGLProfile'Core
180 , WindowHint'OpenGLForwardCompat True
181 ]
182 Just win <- GLFW.createWindow width height title Nothing Nothing
183 GLFW.makeContextCurrent $ Just win
184 return win
diff --git a/examples/pickInt.json b/examples/pickInt.json
new file mode 100644
index 0000000..233cd61
--- /dev/null
+++ b/examples/pickInt.json
@@ -0,0 +1 @@
{"textures":[{"textureBaseLevel":0,"textureSize":{"tag":"VV2U","arg0":{"x":800,"y":600}},"tag":"TextureDescriptor","textureMaxLevel":0,"textureSampler":{"samplerMaxLod":null,"samplerLodBias":0,"tag":"SamplerDescriptor","samplerBorderColor":{"tag":"VV4F","arg0":{"w":1,"z":0,"x":0,"y":0}},"samplerMinFilter":{"tag":"Nearest"},"samplerWrapT":{"tag":"Repeat"},"samplerMagFilter":{"tag":"Nearest"},"samplerWrapR":null,"samplerCompareFunc":null,"samplerWrapS":{"tag":"Repeat"},"samplerMinLod":null},"textureType":{"tag":"Texture2D","arg0":{"tag":"IntT","arg0":{"tag":"RGBA"}},"arg1":1},"textureSemantic":{"tag":"Color"}}],"commands":[{"tag":"SetRenderTarget","arg0":0},{"tag":"ClearRenderTarget","arg0":[{"tag":"ClearImage","clearValue":{"tag":"VV4I","arg0":{"w":0,"z":0,"x":0,"y":0}},"imageSemantic":{"tag":"Color"}}]},{"tag":"SetProgram","arg0":0},{"tag":"SetRasterContext","arg0":{"arg3":{"tag":"LastVertex"},"tag":"TriangleCtx","arg0":{"tag":"CullFront","arg0":{"tag":"CCW"}},"arg1":{"tag":"PolygonFill"},"arg2":{"tag":"NoOffset"}}},{"tag":"SetAccumulationContext","arg0":{"accViewportName":null,"tag":"AccumulationContext","accOperations":[{"tag":"ColorOp","arg0":{"tag":"NoBlending"},"arg1":{"tag":"VV4B","arg0":{"w":true,"z":true,"x":true,"y":true}}}]}},{"tag":"RenderSlot","arg0":0}],"slots":[{"tag":"Slot","slotPrimitive":{"tag":"Triangles"},"slotStreams":{"color":{"tag":"V4F"},"id":{"tag":"Int"},"position":{"tag":"V3F"}},"slotName":"objects","slotUniforms":{"viewProj":{"tag":"M44F"}},"slotPrograms":[0]}],"programs":[{"programInTextures":{},"tag":"Program","programOutput":[{"tag":"Parameter","ty":{"tag":"V4I"},"name":"f0"}],"programStreams":{"vi3":{"tag":"Parameter","ty":{"tag":"Int"},"name":"id"},"vi2":{"tag":"Parameter","ty":{"tag":"V4F"},"name":"color"},"vi1":{"tag":"Parameter","ty":{"tag":"V3F"},"name":"position"}},"fragmentShader":"#version 330 core\nvec4 texture2D(sampler2D s,vec2 uv) {\n return texture(s,uv);\n}\nflat in vec2 vo1;\nflat in ivec4 vo2;\nout ivec4 f0;\nvoid main() {\n f0 = vo2;\n}","vertexShader":"#version 330 core\nvec4 texture2D(sampler2D s,vec2 uv) {\n return texture(s,uv);\n}\nuniform mat4 viewProj;\nin vec3 vi1;\nin vec4 vi2;\nin int vi3;\nflat out vec2 vo1;\nflat out ivec4 vo2;\nvoid main() {\n gl_Position = (viewProj) * (vec4 ((vi1).x,(vi1).y,0.0,1.0));\n vo1 = vec2 (0.0,0.0);\n vo2 = ivec4 (0,0,0,vi3);\n}","geometryShader":null,"programUniforms":{"viewProj":{"tag":"M44F"}}}],"samplers":[],"tag":"Pipeline","backend":{"tag":"OpenGL33"},"streams":[],"targets":[{"tag":"RenderTarget","renderTargets":[{"tag":"TargetItem","targetSemantic":{"tag":"Color"},"targetRef":{"tag":"TextureImage","arg0":0,"arg1":0,"arg2":null}}]}],"info":"generated by lambdacube-compiler 0.6.1.0"} \ No newline at end of file
diff --git a/examples/pickInt.lc b/examples/pickInt.lc
new file mode 100644
index 0000000..a75bc19
--- /dev/null
+++ b/examples/pickInt.lc
@@ -0,0 +1,21 @@
1type FB = FrameBuffer 1 '[ 'Color (Vec 4 Int)]
2
3scene :: String -> FB -> FB
4scene name prevFB =
5 Accumulate ((ColorOp NoBlending (one :: Vec 4 Bool)))
6 (mapFragments (\(uv, rgba) -> ((rgba)))
7 $ rasterizePrimitives (TriangleCtx CullFront PolygonFill NoOffset LastVertex) (Flat, Flat)
8 $ mapPrimitives
9 (\(pos, color, id)->
10 ( (Uniform "viewProj" :: Mat 4 4 Float) *. (V4 pos%x pos%y 0 1)
11 , V2 0.0 0.0
12 , V4 0 0 0 id))
13 $ fetch name ( Attribute "position" :: Vec 3 Float
14 , Attribute "color" :: Vec 4 Float
15 , Attribute "id" :: Int))
16 prevFB
17
18main :: Output
19main = TextureOut (V2 800 600) $
20 scene "objects" $
21 FrameBuffer ((colorImage1 (V4 0 0 0 0)))
diff --git a/examples/pickIntDraw.json b/examples/pickIntDraw.json
new file mode 100644
index 0000000..610caf3
--- /dev/null
+++ b/examples/pickIntDraw.json
@@ -0,0 +1 @@
{"textures":[],"commands":[{"tag":"SetRenderTarget","arg0":0},{"tag":"ClearRenderTarget","arg0":[{"tag":"ClearImage","clearValue":{"tag":"VV4F","arg0":{"w":0,"z":0,"x":0,"y":0}},"imageSemantic":{"tag":"Color"}}]},{"tag":"SetProgram","arg0":0},{"tag":"SetRasterContext","arg0":{"arg3":{"tag":"LastVertex"},"tag":"TriangleCtx","arg0":{"tag":"CullFront","arg0":{"tag":"CCW"}},"arg1":{"tag":"PolygonFill"},"arg2":{"tag":"NoOffset"}}},{"tag":"SetAccumulationContext","arg0":{"accViewportName":null,"tag":"AccumulationContext","accOperations":[{"tag":"ColorOp","arg0":{"tag":"NoBlending"},"arg1":{"tag":"VV4B","arg0":{"w":true,"z":true,"x":true,"y":true}}}]}},{"tag":"RenderSlot","arg0":0}],"slots":[{"tag":"Slot","slotPrimitive":{"tag":"Triangles"},"slotStreams":{"color":{"tag":"V4F"},"id":{"tag":"Int"},"position":{"tag":"V3F"}},"slotName":"objects","slotUniforms":{"viewProj":{"tag":"M44F"}},"slotPrograms":[0]}],"programs":[{"programInTextures":{},"tag":"Program","programOutput":[{"tag":"Parameter","ty":{"tag":"V4F"},"name":"f0"}],"programStreams":{"vi3":{"tag":"Parameter","ty":{"tag":"Int"},"name":"id"},"vi2":{"tag":"Parameter","ty":{"tag":"V4F"},"name":"color"},"vi1":{"tag":"Parameter","ty":{"tag":"V3F"},"name":"position"}},"fragmentShader":"#version 330 core\nvec4 texture2D(sampler2D s,vec2 uv) {\n return texture(s,uv);\n}\nflat in vec2 vo1;\nflat in vec4 vo2;\nout vec4 f0;\nvoid main() {\n f0 = vo2;\n}","vertexShader":"#version 330 core\nvec4 texture2D(sampler2D s,vec2 uv) {\n return texture(s,uv);\n}\nuniform mat4 viewProj;\nin vec3 vi1;\nin vec4 vi2;\nin int vi3;\nflat out vec2 vo1;\nflat out vec4 vo2;\nvoid main() {\n gl_Position = (viewProj) * (vec4 ((vi1).x,(vi1).y,0.0,1.0));\n vo1 = vec2 (0.0,0.0);\n vo2 = vi2;\n}","geometryShader":null,"programUniforms":{"viewProj":{"tag":"M44F"}}}],"samplers":[],"tag":"Pipeline","backend":{"tag":"OpenGL33"},"streams":[],"targets":[{"tag":"RenderTarget","renderTargets":[{"tag":"TargetItem","targetSemantic":{"tag":"Color"},"targetRef":{"tag":"Framebuffer","arg0":{"tag":"Color"}}}]}],"info":"generated by lambdacube-compiler 0.6.1.0"} \ No newline at end of file
diff --git a/examples/pickIntDraw.lc b/examples/pickIntDraw.lc
new file mode 100644
index 0000000..fd1a587
--- /dev/null
+++ b/examples/pickIntDraw.lc
@@ -0,0 +1,21 @@
1type FB = FrameBuffer 1 '[ 'Color (Vec 4 Float)]
2
3scene :: String -> FB -> FB
4scene name prevFB =
5 Accumulate ((ColorOp NoBlending (one :: Vec 4 Bool)))
6 (mapFragments (\(uv, rgba) -> ((rgba)))
7 $ rasterizePrimitives (TriangleCtx CullFront PolygonFill NoOffset LastVertex) (Flat, Flat)
8 $ mapPrimitives
9 (\(pos, color, id)->
10 ( (Uniform "viewProj" :: Mat 4 4 Float) *. (V4 pos%x pos%y 0 1)
11 , V2 0.0 0.0
12 , color))
13 $ fetch name ( Attribute "position" :: Vec 3 Float
14 , Attribute "color" :: Vec 4 Float
15 , Attribute "id" :: Int))
16 prevFB
17
18main :: Output
19main = ScreenOut $
20 scene "objects" $
21 FrameBuffer ((colorImage1 (V4 0 0 0 0)))
diff --git a/lambdacube-gl.cabal b/lambdacube-gl.cabal
index d473889..2c82ae5 100644
--- a/lambdacube-gl.cabal
+++ b/lambdacube-gl.cabal
@@ -84,6 +84,29 @@ executable lambdacube-gl-hello
84 lambdacube-gl, 84 lambdacube-gl,
85 lambdacube-ir == 0.3.* 85 lambdacube-ir == 0.3.*
86 86
87executable lambdacube-gl-pickint
88 -- if flag(example)
89 -- Buildable: True
90 -- else
91 -- Buildable: False
92
93 hs-source-dirs: examples
94 main-is: pickInt.hs
95 default-language: Haskell2010
96
97 build-depends:
98 GLFW-b >= 1.4,
99 JuicyPixels >=3.2,
100 OpenGLRaw,
101 aeson >= 1.1.2,
102 base,
103 bytestring >=0.10,
104 containers >=0.5,
105 lambdacube-gl,
106 lambdacube-ir,
107 vect,
108 vector >=0.12
109
87executable lambdacube-gl-hello-obj 110executable lambdacube-gl-hello-obj
88 if flag(example) 111 if flag(example)
89 Buildable: True 112 Buildable: True