summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-05-14 13:32:37 -0400
committerJoe Crayne <joe@jerkface.net>2019-05-14 13:32:37 -0400
commit07ea0fe2a37cab1e549c084f31d231632857b99f (patch)
tree4e884c2cdf509fa10d35842d5853063b7a56d995
parent9f99af1750924a0be6e003842830aec93380dfdc (diff)
TextureBuffer-based ring buffer.
-rw-r--r--MeshSketch.hs182
-rw-r--r--hello_obj2.lc32
2 files changed, 173 insertions, 41 deletions
diff --git a/MeshSketch.hs b/MeshSketch.hs
index b84cd7e..9425890 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -16,6 +16,8 @@ import Data.Text (Text)
16import Data.Map.Strict (Map) 16import Data.Map.Strict (Map)
17import qualified Data.Map.Strict as Map 17import qualified Data.Map.Strict as Map
18import qualified Data.Vector as V 18import qualified Data.Vector as V
19import Foreign.Marshal.Array
20import Foreign.Storable
19import GI.Gdk 21import GI.Gdk
20import GI.Gdk.Objects 22import GI.Gdk.Objects
21import GI.GLib.Constants 23import GI.GLib.Constants
@@ -30,9 +32,12 @@ import Control.Exception
30import LambdaCube.GL as LC 32import LambdaCube.GL as LC
31import LambdaCube.IR as LC 33import LambdaCube.IR as LC
32import LambdaCube.Gtk 34import LambdaCube.Gtk
33import LambdaCube.GL.Data (uploadCubeMapToGPU) 35import LambdaCube.GL.Data (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer)
34import LambdaCube.GL.Type (TextureCubeData(..)) 36import LambdaCube.GL.Type (TextureCubeData(..),Object(..))
35-- import Text.Show.Pretty (ppShow) 37-- import Text.Show.Pretty (ppShow)
38import qualified Graphics.Rendering.OpenGL as GL
39import Data.Char
40import Text.Printf
36 41
37import CubeMap 42import CubeMap
38import GLWidget (nullableContext, withCurrentGL) 43import GLWidget (nullableContext, withCurrentGL)
@@ -44,6 +49,27 @@ import InfinitePlane
44import MtlParser (ObjMaterial(..)) 49import MtlParser (ObjMaterial(..))
45import Matrix 50import Matrix
46 51
52
53prettyDebug :: GL.DebugMessage -> String
54prettyDebug (GL.DebugMessage src typ (GL.DebugMessageID mid) severity msg) = unwords ws
55 where
56 ws = [wsrc,wtyp,wmid,wseverity,msg]
57 -- DebugSourceShaderCompiler DebugTypeOther 1 DebugSeverityNotification
58 wsrc = filter isUpper $ drop 11 $ show src
59 wtyp = take 2 $ drop 9 $ show typ
60 wmid = printf "%03i" mid
61 wseverity = drop 13 $ show severity
62
63setupGLDebugging :: IO ()
64setupGLDebugging = do
65 let pdebug m@(GL.DebugMessage src typ mid severity msg) = do
66 putStrLn (">> " ++ prettyDebug m)
67 GL.debugOutput GL.$= GL.Enabled
68 GL.debugOutputSynchronous GL.$= GL.Enabled
69 GL.debugMessageControl (GL.MessageGroup Nothing Nothing Nothing) GL.$= GL.Enabled
70 GL.debugMessageCallback GL.$= Just pdebug
71
72
47-- State created by uploadState. 73-- State created by uploadState.
48data State = State 74data State = State
49 { stAnimator :: Animator 75 { stAnimator :: Animator
@@ -53,6 +79,8 @@ data State = State
53 , stSkybox :: IORef Int 79 , stSkybox :: IORef Int
54 , stSkyTexture :: IORef TextureCubeData 80 , stSkyTexture :: IORef TextureCubeData
55 , stDragFrom :: IORef (Maybe (Vector Float,Camera)) 81 , stDragFrom :: IORef (Maybe (Vector Float,Camera))
82 , stRingBuffer :: Ring
83 , stPenDown :: IORef Bool
56 } 84 }
57 85
58data Camera = Camera 86data Camera = Camera
@@ -111,6 +139,49 @@ mkFullscreenToggle w = do
111 if b then windowFullscreen w 139 if b then windowFullscreen w
112 else windowUnfullscreen w 140 else windowUnfullscreen w
113 141
142data Ring = Ring
143 { ringMax :: Int
144 , ringTexture :: TextureBufferData
145 , ringStart :: IO Int
146 , ringSize :: IO Int
147 , pushBack :: Float -> Float -> Float -> IO ()
148 , popFront :: IO ()
149 }
150
151newRing :: GLStorage -> Int -> IO Ring
152newRing storage cnt = do
153 let ringCapacity = cnt * 3
154 tbo <- uploadTextureBufferToGPU ringCapacity
155 p <- uploadMeshToGPU Mesh
156 { mAttributes = Map.singleton "position" $ A_Float $ V.fromList
157 $ replicate ringCapacity 0.0
158 , mPrimitive = P_Points
159 }
160 obj <- addMeshToObjectArray storage "Points" [] p
161 LC.updateUniforms storage $ do
162 "PointBuffer" @= return tbo
163 rstart <- newIORef 0
164 rsize <- newIORef 0
165 return Ring
166 { ringMax = cnt * 3
167 , ringTexture = tbo
168 , ringStart = readIORef rstart
169 , ringSize = readIORef rsize
170 , pushBack = \x y z -> do
171 start <- readIORef rstart
172 allocaArray 3 $ \ptr -> do
173 pokeElemOff ptr 0 x
174 pokeElemOff ptr 1 y
175 pokeElemOff ptr 2 z
176 updateTextureBuffer tbo start 3 ptr
177 writeIORef rstart (mod (start + 3) ringCapacity)
178 sz <- readIORef rsize
179 putStrLn $ "pushBack "++show (sz,start,(x,y,z))
180 when (sz < ringCapacity) $ do
181 writeIORef rsize (sz + 3)
182 , popFront = modifyIORef' rsize $ \s -> if s > 3 then s - 3 else 0
183 }
184
114uploadState :: IsWidget glarea => MeshData -> glarea -> GLStorage -> IO State 185uploadState :: IsWidget glarea => MeshData -> glarea -> GLStorage -> IO State
115uploadState obj glarea storage = do 186uploadState obj glarea storage = do
116 -- load OBJ geometry and material descriptions 187 -- load OBJ geometry and material descriptions
@@ -122,6 +193,8 @@ uploadState obj glarea storage = do
122 -- grid plane 193 -- grid plane
123 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" [] 194 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" []
124 195
196 ring <- newRing storage 100
197
125 -- setup FrameClock 198 -- setup FrameClock
126 w <- toWidget glarea 199 w <- toWidget glarea
127 tm <- newAnimator w 200 tm <- newAnimator w
@@ -146,6 +219,7 @@ uploadState obj glarea storage = do
146 LC.addMeshToObjectArray storage "SkyCube" [] mi 219 LC.addMeshToObjectArray storage "SkyCube" [] mi
147 220
148 drag <- newIORef Nothing 221 drag <- newIORef Nothing
222 pendown <- newIORef False
149 223
150 let st = State 224 let st = State
151 { stAnimator = tm 225 { stAnimator = tm
@@ -155,6 +229,8 @@ uploadState obj glarea storage = do
155 , stSkybox = skybox 229 , stSkybox = skybox
156 , stSkyTexture = skytex 230 , stSkyTexture = skytex
157 , stDragFrom = drag 231 , stDragFrom = drag
232 , stRingBuffer = ring
233 , stPenDown = pendown
158 } 234 }
159 -- _ <- addAnimation tm (whirlingCamera st) 235 -- _ <- addAnimation tm (whirlingCamera st)
160 236
@@ -187,6 +263,8 @@ setUniforms gl storage st = do
187 LC.updateUniforms storage $ do 263 LC.updateUniforms storage $ do
188 "CameraPosition" @= return (pos :: Vector Float) 264 "CameraPosition" @= return (pos :: Vector Float)
189 "ViewProjection" @= return (mvp :: Matrix Float) 265 "ViewProjection" @= return (mvp :: Matrix Float)
266 "PointsStart" @= fmap (fromIntegral :: Int -> Int32) (ringStart $ stRingBuffer st)
267 "PointsMax" @= return (fromIntegral (ringMax $ stRingBuffer st) :: Int32)
190 268
191data MeshSketch = MeshSketch 269data MeshSketch = MeshSketch
192 { mmWidget :: GLArea 270 { mmWidget :: GLArea
@@ -214,10 +292,15 @@ new = do
214 "uvw" @: Attribute_V3F 292 "uvw" @: Attribute_V3F
215 defObjectArray "plane" Triangles $ do 293 defObjectArray "plane" Triangles $ do
216 "position" @: Attribute_V4F 294 "position" @: Attribute_V4F
295 defObjectArray "Points" Points $ do
296 "position" @: Attribute_Float
217 defUniforms $ do 297 defUniforms $ do
298 "PointBuffer" @: FTextureBuffer
218 "CubeMap" @: FTextureCube 299 "CubeMap" @: FTextureCube
219 "CameraPosition" @: V3F 300 "CameraPosition" @: V3F
220 "ViewProjection" @: M44F 301 "ViewProjection" @: M44F
302 "PointsMax" @: Int
303 "PointsStart" @: Int
221 "diffuseTexture" @: FTexture2D 304 "diffuseTexture" @: FTexture2D
222 "diffuseColor" @: V4F 305 "diffuseColor" @: V4F
223 return $ (,) <$> mobj <*> mpipeline 306 return $ (,) <$> mobj <*> mpipeline
@@ -248,6 +331,7 @@ onUnrealize mm = do
248onRealize :: MeshData -> Pipeline -> PipelineSchema -> MeshSketch -> IO () 331onRealize :: MeshData -> Pipeline -> PipelineSchema -> MeshSketch -> IO ()
249onRealize mesh pipeline schema mm = do 332onRealize mesh pipeline schema mm = do
250 onUnrealize mm 333 onUnrealize mm
334 setupGLDebugging
251 storage <- LC.allocStorage schema 335 storage <- LC.allocStorage schema
252 renderer <- LC.allocRenderer pipeline 336 renderer <- LC.allocRenderer pipeline
253 compat <- LC.setStorage renderer storage -- check schema compatibility 337 compat <- LC.setStorage renderer storage -- check schema compatibility
@@ -298,6 +382,8 @@ onResize glarea realized w h = do
298 } 382 }
299 LC.setScreenSize (stStorage realized) wd ht) 383 LC.setScreenSize (stStorage realized) wd ht)
300 384
385-- This computes a point in world coordinates on the view screen if
386-- we assume the camera is located at the origin.
301computeDirection :: Camera -> Double -> Double -> Vector Float 387computeDirection :: Camera -> Double -> Double -> Vector Float
302computeDirection cam h k = 388computeDirection cam h k =
303 let d̂ = camDirection cam -- forward 389 let d̂ = camDirection cam -- forward
@@ -392,49 +478,63 @@ onEvent w realized ev = do
392 case etype of 478 case etype of
393 479
394 EventTypeMotionNotify -> do 480 EventTypeMotionNotify -> do
395 mev <- get ev #motion 481 case inputSource of
396 h <- get mev #x 482 Just InputSourcePen -> do
397 k <- get mev #y 483 isDown <- readIORef (stPenDown st)
398 {- 484 when isDown $ do
399 cam <- readIORef (stCamera st) 485 mev <- get ev #motion
400 {- 486 h <- get mev #x
401 let o = fromList [ camWidth cam / 2, camHeight cam / 2 ] 487 k <- get mev #y
402 r = camHeight cam / (2 * sin (camHeight cam / 2)) 488 cam <- readIORef (stCamera st)
403 489 let d = computeDirection cam h k
404 c = fromList [realToFrac h, realToFrac k] - o :: Vector Float 490 pushBack (stRingBuffer st) (d!0) (d!1) (d!2)
405 d = realToFrac $ norm_2 c 491 put (etype,(h,k),d)
406 τ = asin (d / r) -- angle from center 492 _ -> do
407 axis = fromList [c!1, - (c!0)] :: Vector Float 493 mev <- get ev #motion
408 -} 494 h <- get mev #x
409 let d̂ = camDirection cam -- forward 495 k <- get mev #y
410 û = camUp cam -- upward 496 put (h,k)
411 r̂ = d̂ `cross` û -- rightward 497 updateCameraRotation w st h k
412 x_r = realToFrac h - (camWidth cam / 2) 498 return ()
413 x_u = (camHeight cam / 2) - realToFrac k
414 x_d = (camHeight cam / 2) / tan (camHeightAngle cam / 2)
415 x = fromList [x_r,x_u,x_d]
416 -}
417
418 updateCameraRotation w st h k
419 return ()
420 499
421 EventTypeButtonPress -> do 500 EventTypeButtonPress -> do
422 bev <- get ev #button 501 case inputSource of
423 h <- get bev #x 502 Just InputSourcePen -> do
424 k <- get bev #y 503 writeIORef (stPenDown st) True
425 cam <- readIORef (stCamera st) 504 bev <- get ev #button
426 let d = computeDirection cam h k 505 h <- get bev #x
427 writeIORef (stDragFrom st) $ Just (d,cam) 506 k <- get bev #y
428 put (etype,(h,k),d) 507 cam <- readIORef (stCamera st)
429 return () 508 let d = computeDirection cam h k
509 pushBack (stRingBuffer st) (d!0) (d!1) (d!2)
510 put (etype,(h,k),d)
511 _ -> do
512 bev <- get ev #button
513 h <- get bev #x
514 k <- get bev #y
515 cam <- readIORef (stCamera st)
516 let d = computeDirection cam h k
517 writeIORef (stDragFrom st) $ Just (d,cam)
518 put (etype,(h,k),d)
519 return ()
430 520
431 EventTypeButtonRelease -> do 521 EventTypeButtonRelease -> do
432 bev <- get ev #button 522 case inputSource of
433 h <- get bev #x 523 Just InputSourcePen -> do
434 k <- get bev #y 524 writeIORef (stPenDown st) False
435 updateCameraRotation w st h k 525 bev <- get ev #button
436 sanitizeCamera st 526 h <- get bev #x
437 writeIORef (stDragFrom st) Nothing 527 k <- get bev #y
528 cam <- readIORef (stCamera st)
529 let d = computeDirection cam h k
530 pushBack (stRingBuffer st) (d!0) (d!1) (d!2)
531 _ -> do
532 bev <- get ev #button
533 h <- get bev #x
534 k <- get bev #y
535 updateCameraRotation w st h k
536 sanitizeCamera st
537 writeIORef (stDragFrom st) Nothing
438 538
439 EventTypeScroll -> do 539 EventTypeScroll -> do
440 sev <- get ev #scroll 540 sev <- get ev #scroll
diff --git a/hello_obj2.lc b/hello_obj2.lc
index 991c3c2..8e9bbe0 100644
--- a/hello_obj2.lc
+++ b/hello_obj2.lc
@@ -19,6 +19,8 @@ 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)
23 (pointsStart :: Int)
22 24
23 = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1)) 25 = imageFrame (emptyDepthImage 1, emptyColorImage (V4 0 0 0.4 1))
24 `overlay` 26 `overlay`
@@ -43,6 +45,34 @@ makeFrame (cubemap :: TextureCube)
43 r = V4 1 1 1 0 *! (max c%x c%y) 45 r = V4 1 1 1 0 *! (max c%x c%y)
44 in ((r + V4 0 0 0 (0.8)))) 46 in ((r + V4 0 0 0 (0.8))))
45 & accumulateWith (DepthOp Less True, ColorOp blendplane (V4 True True True True)) 47 & accumulateWith (DepthOp Less True, ColorOp blendplane (V4 True True True True))
48 `overlay`
49 zipCount (fetch "Points" ((Attribute "position")) :: PrimitiveStream Point ((Float)))
50 & mapPrimitives (\(n,_) -> {- let nn = 0.2 * fromInt n :: Float
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))
62
63 & renderPoints cam
64
65
66renderPoints ::
67 Mat 4 4 Float
68 -> PrimitiveStream Point (Vec 4 Float, Vec 4 Float)
69 -> ( (FragmentOperation Depth, FragmentOperation (Color (VecScalar 4 Float)))
70 , FragmentStream 1 ((Vec 4 Float)) )
71renderPoints cam points =
72 points
73 & rasterizePrimitives (PointCtx (PointSize 10.0) 1.0 LowerLeft) ((Flat))
74 & mapFragments (\((c)) -> ((c)))
75 & accumulateWith (DepthOp Always False, ColorOp NoBlending (V4 True True True True))
46 76
47textureCubeSlot s = TextureCubeSlot s 77textureCubeSlot s = TextureCubeSlot s
48 78
@@ -56,4 +86,6 @@ main = renderFrame $
56 (Texture2DSlot "diffuseTexture") 86 (Texture2DSlot "diffuseTexture")
57 (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw")) 87 (fetch "objects" (Attribute "position", Attribute "normal", Attribute "uvw"))
58 (fetch "plane" ((Attribute "position"))) 88 (fetch "plane" ((Attribute "position")))
89 (Uniform "PointsMax")
90 (Uniform "PointsStart")
59 91