summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-05-17 03:55:38 -0400
committerJoe Crayne <joe@jerkface.net>2019-05-17 03:55:38 -0400
commitb5d68cc4aba82fec53e156a6c0c2d2726ee6ff46 (patch)
tree4fe1a29265412abc09dc20887a17d378322c08a2
parentf5d4a74e9a4b23917b97f48bde529cb21e3ec152 (diff)
Point primitive stream based ring buffer.
-rw-r--r--MeshSketch.hs29
-rw-r--r--PointPrimitiveRing.hs239
-rw-r--r--hello_obj2.lc21
3 files changed, 263 insertions, 26 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs
index 16c8284..0b3cd05 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -48,7 +48,7 @@ import LoadMesh
48import InfinitePlane 48import InfinitePlane
49import MtlParser (ObjMaterial(..)) 49import MtlParser (ObjMaterial(..))
50import Matrix 50import Matrix
51import TextureBufferRing 51import PointPrimitiveRing
52 52
53 53
54prettyDebug :: GL.DebugMessage -> String 54prettyDebug :: GL.DebugMessage -> String
@@ -96,6 +96,8 @@ data Camera = Camera
96 , camScreenToWorld :: Maybe (Matrix Float) 96 , camScreenToWorld :: Maybe (Matrix Float)
97 } 97 }
98 98
99camPos c = camTarget c - scale (camDistance c) (camDirection c)
100
99initCamera :: Camera 101initCamera :: Camera
100initCamera = Camera 102initCamera = Camera
101 { camHeightAngle = pi/6 103 { camHeightAngle = pi/6
@@ -251,7 +253,7 @@ new = do
251 defObjectArray "plane" Triangles $ do 253 defObjectArray "plane" Triangles $ do
252 "position" @: Attribute_V4F 254 "position" @: Attribute_V4F
253 defObjectArray "Points" Points $ do 255 defObjectArray "Points" Points $ do
254 "position" @: Attribute_Float 256 "position" @: Attribute_V3F
255 defUniforms $ do 257 defUniforms $ do
256 "PointBuffer" @: FTextureBuffer 258 "PointBuffer" @: FTextureBuffer
257 "CubeMap" @: FTextureCube 259 "CubeMap" @: FTextureCube
@@ -309,7 +311,8 @@ onRealize mesh pipeline schema mm = do
309 , EventMaskScrollMask 311 , EventMaskScrollMask
310 , EventMaskKeyPressMask -- , EventMaskKeyReleaseMask 312 , EventMaskKeyPressMask -- , EventMaskKeyReleaseMask
311 ] 313 ]
312 _ <- on w #event $ onEvent w r 314 _ <- on w #event $ \ev -> do gLAreaMakeCurrent w
315 onEvent w r ev
313 _ <- on w #render $ onRender w r 316 _ <- on w #render $ onRender w r
314 _ <- on w #resize $ onResize w r 317 _ <- on w #resize $ onResize w r
315 writeIORef (mmRealized mm) $ Just r 318 writeIORef (mmRealized mm) $ Just r
@@ -444,8 +447,11 @@ onEvent w realized ev = do
444 h <- get mev #x 447 h <- get mev #x
445 k <- get mev #y 448 k <- get mev #y
446 cam <- readIORef (stCamera st) 449 cam <- readIORef (stCamera st)
447 let d = computeDirection cam h k 450 let d = camPos cam + computeDirection cam h k
448 pushBack (stRingBuffer st) (d!0) (d!1) (d!2) 451 -- pushBack (stRingBuffer st) (d!0) (d!1) (d!2)
452 pushBack (stRingBuffer st) (2 * realToFrac h/camWidth cam - 1) (1 - 2 * realToFrac k/camHeight cam) 1 -- (d!0) (d!1) (d!2)
453 Just win <- getWidgetWindow w
454 windowInvalidateRect win Nothing False
449 put (etype,(h,k),d) 455 put (etype,(h,k),d)
450 _ -> do 456 _ -> do
451 mev <- get ev #motion 457 mev <- get ev #motion
@@ -463,8 +469,11 @@ onEvent w realized ev = do
463 h <- get bev #x 469 h <- get bev #x
464 k <- get bev #y 470 k <- get bev #y
465 cam <- readIORef (stCamera st) 471 cam <- readIORef (stCamera st)
466 let d = computeDirection cam h k 472 let d = camPos cam + computeDirection cam h k
467 pushBack (stRingBuffer st) (d!0) (d!1) (d!2) 473 -- pushBack (stRingBuffer st) (d!0) (d!1) (d!2)
474 pushBack (stRingBuffer st) (2 * realToFrac h/camWidth cam - 1) (1 - 2 * realToFrac k/camHeight cam) 1 -- (d!0) (d!1) (d!2)
475 Just win <- getWidgetWindow w
476 windowInvalidateRect win Nothing False
468 put (etype,(h,k),d) 477 put (etype,(h,k),d)
469 _ -> do 478 _ -> do
470 bev <- get ev #button 479 bev <- get ev #button
@@ -484,8 +493,10 @@ onEvent w realized ev = do
484 h <- get bev #x 493 h <- get bev #x
485 k <- get bev #y 494 k <- get bev #y
486 cam <- readIORef (stCamera st) 495 cam <- readIORef (stCamera st)
487 let d = computeDirection cam h k 496 let d = camPos cam + computeDirection cam h k
488 pushBack (stRingBuffer st) (d!0) (d!1) (d!2) 497 pushBack (stRingBuffer st) (2 * realToFrac h/camWidth cam - 1) (1 - 2 * realToFrac k/camHeight cam) 1 -- (d!0) (d!1) (d!2)
498 Just win <- getWidgetWindow w
499 windowInvalidateRect win Nothing False
489 _ -> do 500 _ -> do
490 bev <- get ev #button 501 bev <- get ev #button
491 h <- get bev #x 502 h <- get bev #x
diff --git a/PointPrimitiveRing.hs b/PointPrimitiveRing.hs
new file mode 100644
index 0000000..bd9a15b
--- /dev/null
+++ b/PointPrimitiveRing.hs
@@ -0,0 +1,239 @@
1{-# LANGUAGE LambdaCase, RecordWildCards #-}
2module PointPrimitiveRing where
3
4import Control.Monad
5import Data.Foldable
6import Data.Int
7import Data.IORef
8import Data.Maybe
9import Data.Word
10import qualified Data.Map.Strict as Map
11import qualified Data.Vector as V
12 ;import Data.Vector as V ((!),(//))
13import Foreign.C.Types (CPtrdiff)
14import Foreign.Marshal
15import Foreign.Ptr
16import Foreign.Storable
17
18import LambdaCube.GL as LC
19import LambdaCube.GL.Data -- (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer)
20import LambdaCube.GL.Mesh as LC
21import LambdaCube.GL.Type
22import LambdaCube.IR as LC
23import LambdaCube.GL.Util
24import LambdaCube.GL.Input.Type
25import LambdaCube.GL.Input hiding (createObjectCommands)
26
27import Graphics.GL.Core33
28
29data Ring = Ring
30 { rBufferObject :: Word32
31 , rStorage :: GLStorage
32 , rObject :: Object
33 , rSize :: IORef CPtrdiff
34 , rStart :: IORef CPtrdiff
35 , ringCapacity :: CPtrdiff
36 }
37
38addToObjectArray :: GLStorage
39 -> String -- ^ Slot name for a PrimitiveStream.
40 -> [String] -- ^ Uniform names. IORefs will be put in 'objUniSetup'.
41 -> GPUData
42 -> IO Object
43addToObjectArray input slotName objUniNames (GPUData prim streams indices _) = do
44 let ObjectArraySchema _ slotStreams = fromMaybe (error $ "addMeshToObjectArray - missing object array: " ++ slotName)
45 $ Map.lookup slotName $! objectArrays $! schema input
46 addObject input slotName prim indices (Map.intersection streams slotStreams) objUniNames
47
48setUniformCommand :: (String -> GLUniform)
49 -> (String,GLint)
50 -> GLObjectCommand
51setUniformCommand ulookup (n,i) = GLSetUniform i (ulookup n)
52
53bindTextureCommand :: (String -> IORef GLint)
54 -> (String -> GLUniform)
55 -> String
56 -> GLObjectCommand
57bindTextureCommand tlookup ulookup n = GLBindTexture (inputTypeToTextureTarget $ uniInputType u) (tlookup n) u
58 where
59 u = ulookup n
60 uniInputType (GLTypedUniform ty _) = unwitnessType ty
61 uniInputType (GLUniform r) = objectType r
62
63
64lookupOrLookup :: (Ord k, Show k) => String -> Map.Map k a -> Map.Map k a -> k -> a
65lookupOrLookup callsite objUnis topUnis n = Map.findWithDefault (topUni n) n objUnis
66 where
67 topUni n = Map.findWithDefault (error $ "internal error ("++callsite++"): " ++ show n) n topUnis
68
69
70classifyStreamType :: StreamType -> ( GLint
71 , GLuint -> GLuint -> GLint -> GLenum -> Ptr () -> GLObjectCommand)
72classifyStreamType = \case
73 Attribute_Word -> ( 1 , GLSetVertexAttribIArray )
74 Attribute_V2U -> ( 2 , GLSetVertexAttribIArray )
75 Attribute_V3U -> ( 3 , GLSetVertexAttribIArray )
76 Attribute_V4U -> ( 4 , GLSetVertexAttribIArray )
77 Attribute_Int -> ( 1 , GLSetVertexAttribIArray )
78 Attribute_V2I -> ( 2 , GLSetVertexAttribIArray )
79 Attribute_V3I -> ( 3 , GLSetVertexAttribIArray )
80 Attribute_V4I -> ( 4 , GLSetVertexAttribIArray )
81 Attribute_Float -> ( 1 , GLSetVertexAttribArray )
82 Attribute_V2F -> ( 2 , GLSetVertexAttribArray )
83 Attribute_V3F -> ( 3 , GLSetVertexAttribArray )
84 Attribute_V4F -> ( 4 , GLSetVertexAttribArray )
85 Attribute_M22F -> ( 4 , GLSetVertexAttribArray )
86 Attribute_M23F -> ( 6 , GLSetVertexAttribArray )
87 Attribute_M24F -> ( 8 , GLSetVertexAttribArray )
88 Attribute_M32F -> ( 6 , GLSetVertexAttribArray )
89 Attribute_M33F -> ( 9 , GLSetVertexAttribArray )
90 Attribute_M34F -> ( 12 , GLSetVertexAttribArray )
91 Attribute_M42F -> ( 8 , GLSetVertexAttribArray )
92 Attribute_M43F -> ( 12 , GLSetVertexAttribArray )
93 Attribute_M44F -> ( 16 , GLSetVertexAttribArray )
94
95drawElementsCommand :: GLenum -> IndexStream Buffer -> GLObjectCommand
96drawElementsCommand prim (IndexStream (Buffer arrs bo) arrIdx start idxCount)
97 = GLDrawElements prim (fromIntegral idxCount) idxType bo ptr
98 where
99 ArrayDesc arrType arrLen arrOffs arrSize = arrs ! arrIdx
100 idxType = arrayTypeToGLType arrType
101 ptr = intPtrToPtr $! fromIntegral (arrOffs + start * sizeOfArrayType arrType)
102
103objectDrawStyle :: (GLsizei -> [(GLint,GLsizei)]) -- ^ mask, normally \x -> [(0,x)]
104 -> Object
105 -> Either [(GLint,GLsizei)] (IndexStream Buffer)
106objectDrawStyle streamMask obj = case objIndices obj of
107 Nothing -> Left $ let cnt = head [c | Stream _ _ _ _ c <- Map.elems (objAttributes obj)]
108 in streamMask $ fromIntegral cnt
109 Just idxStream -> Right idxStream
110
111
112createObjectCommands :: Map.Map String (IORef GLint) -> Map.Map String GLUniform -> Object -> GLProgram -> [GLObjectCommand]
113createObjectCommands texUnitMap topUnis obj prg =
114 createObjectCommands_ (objectEnvironment texUnitMap topUnis obj (pure . ((,) 0))) prg
115
116createObjectCommands_ :: ObjectEnvironment -> GLProgram -> [GLObjectCommand]
117createObjectCommands_ ObjectEnvironment{..} prg = concat
118 [ map (setUniformCommand ulookup) $ Map.toList (inputUniforms prg)
119 , map (bindTextureCommand tlookup ulookup) $ toList (inputTextureUniforms prg)
120 , map (setVertexAttribCommmand alookup) $ Map.elems (inputStreams prg)
121 , case envDrawStyle of
122 Left ranges -> map (uncurry $ GLDrawArrays envPrim) ranges
123 Right indexed -> pure $ drawElementsCommand envPrim indexed
124 ]
125
126data ObjectEnvironment = ObjectEnvironment
127 { envPrim :: GLenum
128 , envDrawStyle :: Either [(GLint,GLsizei)] (IndexStream Buffer)
129 , tlookup :: String -> IORef GLint
130 , ulookup :: String -> GLUniform
131 , alookup :: String -> Stream Buffer
132 }
133
134objectEnvironment :: Map.Map String (IORef GLint)
135 -> Map.Map String GLUniform
136 -> Object
137 -> (GLsizei -> [(GLint, GLsizei)])
138 -> ObjectEnvironment
139objectEnvironment texUnitMap topUnis obj streamMask = ObjectEnvironment
140 { envPrim = primitiveToGLType $ objPrimitive obj
141 , envDrawStyle = objectDrawStyle streamMask obj
142 , tlookup = \n -> Map.findWithDefault (error $ "missing texture unit: " ++ show n) n texUnitMap
143 , ulookup = lookupOrLookup "missing uniform: " (objUniSetup obj) topUnis
144 , alookup = \n -> Map.findWithDefault (error $ "missing attribute: " ++ n) n $ objAttributes obj
145 }
146
147
148setVertexAttribCommmand :: (t -> Stream Buffer) -> (GLuint, t) -> GLObjectCommand
149setVertexAttribCommmand alookup (i,name) = case alookup name of
150 Stream ty (Buffer arrs bo) arrIdx start len -> mkAttrCmd i bo n (arrayTypeToGLType arrType) (intPtrToPtr $! offset)
151 where
152 (n, mkAttrCmd) = classifyStreamType ty
153 ArrayDesc arrType arrLen arrOffs arrSize = arrs ! arrIdx
154 offset = fromIntegral (arrOffs + start * fromIntegral n * sizeOfArrayType arrType)
155
156 -- constant generic attribute
157 constAttr -> GLSetVertexAttrib i constAttr
158
159updateCommands :: GLStorage
160 -> Object
161 -> (GLsizei -> [(GLint,GLsizei)])
162 -> IO Object
163updateCommands input obj mask = do
164 let cmdsRef = objCommands obj :: IORef (V.Vector (V.Vector [GLObjectCommand]))
165 slotIdx = objSlot obj :: Int
166 ppls <- readIORef $ pipelines input
167 cmds <- V.forM (ppls :: V.Vector (Maybe GLRenderer)) $ \mp -> case mp of
168 Nothing -> return V.empty
169 Just p -> do
170 let env = objectEnvironment (glTexUnitMapping p) (uniformSetup input) obj mask
171 Just ic <- readIORef $ glInput p
172 case icSlotMapInputToPipeline ic ! slotIdx of
173 Nothing -> return V.empty -- this slot is not used in that pipeline
174 Just pSlotIdx -> do
175 let emptyV = V.replicate (V.length $ glPrograms p) []
176 return $ emptyV // [(prgIdx,createObjectCommands_ env (glPrograms p ! prgIdx))
177 | prgIdx <- glSlotPrograms p ! pSlotIdx]
178 writeIORef cmdsRef cmds
179 return obj
180
181newRing :: GLStorage -> Int -> IO Ring
182newRing storage sz = do
183 bo <- alloca $! \pbo -> glGenBuffers 1 pbo >> peek pbo
184 glBindBuffer GL_ARRAY_BUFFER bo
185 let bufsize = 3 * fromIntegral sz
186 byteCount = 4 * bufsize
187 glBufferData GL_ARRAY_BUFFER byteCount nullPtr GL_DYNAMIC_DRAW
188 glBindBuffer GL_ARRAY_BUFFER 0
189 startRef <- newIORef 0
190 sizeRef <- newIORef 0
191 let buffer = Buffer (V.singleton $ ArrayDesc ArrFloat (fromIntegral bufsize) 0 (fromIntegral byteCount))
192 bo
193 gd = GPUData PointList (Map.singleton "position" $ Stream Attribute_V3F buffer 0 0 sz) Nothing [buffer]
194 obj <- addToObjectArray storage "Points" [] gd
195 readIORef (objCommands obj) >>= mapM_ print
196 -- [[GLSetUniform 0 GLUniform M44F,GLSetVertexAttribArray 0 5 3 5126 0x0000000000000000,GLDrawArrays 0 0 1],[],[],[]]
197 let r = Ring
198 { rBufferObject = bo
199 , rStorage = storage
200 , rObject = obj
201 , rSize = sizeRef
202 , rStart = startRef
203 , ringCapacity = bufsize
204 }
205 updateRingCommands r
206 return r
207
208updateRingCommands :: Ring -> IO ()
209updateRingCommands r = do
210 start <- fmap (fromIntegral . (`div` 3)) $ readIORef $ rStart r
211 size <- fmap (fromIntegral . (`div` 3)) $ readIORef $ rSize r
212 let mask 0 = []
213 mask cnt = if start + size < cnt
214 then [(start,size)]
215 else [(0,start + size - cnt), (start,cnt-start)]
216 updateCommands (rStorage r) (rObject r) mask
217 readIORef (objCommands $ rObject r) >>= mapM_ print
218 return ()
219
220pushBack :: Ring -> Float -> Float -> Float -> IO ()
221pushBack r x y z = allocaArray 3 $ \ptr -> do
222 pokeElemOff ptr 0 x
223 pokeElemOff ptr 1 y
224 pokeElemOff ptr 2 z
225 start <- readIORef $ rStart r
226 writeIORef (rStart r) (mod (start + 3) (ringCapacity r))
227 glBindBuffer GL_ARRAY_BUFFER (rBufferObject r)
228 glBufferSubData GL_ARRAY_BUFFER (4*start) (4*3) ptr
229 glBindBuffer GL_ARRAY_BUFFER 0
230 glFlush
231 glFinish
232 sz <- readIORef (rSize r)
233 putStrLn $ "pushBack "++show (sz,start,(x,y,z))
234 when (sz < ringCapacity r) $ do
235 writeIORef (rSize r) (sz + 3)
236 updateRingCommands r
237
238updateRingUniforms :: GLStorage -> Ring -> IO ()
239updateRingUniforms _ _ = return ()
diff --git a/hello_obj2.lc b/hello_obj2.lc
index 8e9bbe0..1181943 100644
--- a/hello_obj2.lc
+++ b/hello_obj2.lc
@@ -19,8 +19,7 @@ makeFrame (cubemap :: TextureCube)
19 (texture :: Texture) 19 (texture :: Texture)
20 (prims :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float)) 20 (prims :: PrimitiveStream Triangle (Vec 4 Float, Vec 3 Float, Vec 3 Float))
21 (plane :: PrimitiveStream Triangle ((Vec 4 Float))) 21 (plane :: PrimitiveStream Triangle ((Vec 4 Float)))
22 (pointsMax :: Int) 22 (points :: PrimitiveStream Point ((Vec 3 Float)))
23 (pointsStart :: Int)
24 23
25 = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1)) 24 = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1))
26 `overlay` 25 `overlay`
@@ -46,23 +45,12 @@ makeFrame (cubemap :: TextureCube)
46 in ((r + V4 0 0 0 (0.8)))) 45 in ((r + V4 0 0 0 (0.8))))
47 & accumulateWith (DepthOp Less True, ColorOp blendplane (V4 True True True True)) 46 & accumulateWith (DepthOp Less True, ColorOp blendplane (V4 True True True True))
48 `overlay` 47 `overlay`
49 zipCount (fetch "Points" ((Attribute "position")) :: PrimitiveStream Point ((Float))) 48 points
50 & mapPrimitives (\(n,_) -> {- let nn = 0.2 * fromInt n :: Float 49 & mapPrimitives (\((p)) -> let p' = point p -- coordmap cam $ point p
51 p = V4 nn nn nn 1
52 p' = coordmap cam p
53 in (p', V4 1 1 0 1 :: Vec 4 Float)) -}
54 let i = mod (n + pointsStart) pointsMax
55 t = TextureBufferSlot "PointBuffer"
56 p = V4 (textureBuffer t i)
57 (textureBuffer t (i+1))
58 (textureBuffer t (i+2))
59 1
60 p' = coordmap cam p
61 in (p', V4 1 1 0 1 :: Vec 4 Float)) 50 in (p', V4 1 1 0 1 :: Vec 4 Float))
62 51
63 & renderPoints cam 52 & renderPoints cam
64 53
65
66renderPoints :: 54renderPoints ::
67 Mat 4 4 Float 55 Mat 4 4 Float
68 -> PrimitiveStream Point (Vec 4 Float, Vec 4 Float) 56 -> PrimitiveStream Point (Vec 4 Float, Vec 4 Float)
@@ -86,6 +74,5 @@ main = renderFrame $
86 (Texture2DSlot "diffuseTexture") 74 (Texture2DSlot "diffuseTexture")
87 (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw")) 75 (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw"))
88 (fetch "plane" ((Attribute "position"))) 76 (fetch "plane" ((Attribute "position")))
89 (Uniform "PointsMax") 77 (fetch "Points" ((Attribute "position")))
90 (Uniform "PointsStart")
91 78