Refactor vao preload

This commit is contained in:
2021-02-19 12:41:46 +01:00
parent f4db9bf9a1
commit f6efe98181
16 changed files with 441 additions and 485 deletions
+140 -116
View File
@@ -6,6 +6,8 @@ import Control.Lens
import Control.Monad
import Control.Monad.Trans.State
import qualified Control.Foldl as F
import Data.Bifunctor
import Picture
@@ -18,7 +20,7 @@ import Foreign
import Codec.Picture
import Graphics.Rendering.OpenGL hiding (get,translate,scale,imageHeight,imageWidth,Polygon,Color,T)
import Graphics.Rendering.OpenGL hiding (Line,get,translate,scale,imageHeight,imageWidth,Polygon,Color,T)
import qualified Graphics.Rendering.OpenGL as GL
import Data.Foldable
@@ -36,27 +38,11 @@ toVec2 (x,y) = Vector2 x y
toVec3 (x,y,z) = Vector3 x y z
toVec4 (x,y,z,w) = Vector4 x y z w
mapFlat :: (NFData b) => (a -> VerticesContainer b) -> VerticesContainer a -> [b]
mapFlat f = fromVC . foldMap f
polyToTris :: [s] -> [s]
{-# INLINE polyToTris #-}
polyToTris (a:b:c:as) = a : intercalate [a] (zipWith (\x y->[x,y]) (init (b:c:as)) (c:as))
polyToTris _ = []
data Tx a = Tx [Tx a] | Lx a
deriving instance Foldable Tx
stateBump :: [Int] -> () -> State Int [Int]
stateBump xs _ = do
s <- get
modify (+1)
return (s:xs)
redT :: Foldable t => t () -> [Int]
redT x = evalState (foldM stateBump [] x) 0
tripFirst :: (a -> a') -> (a,b,c) -> (a',b,c)
{-# INLINE tripFirst #-}
tripFirst f (x,y,z) = (f x,y,z)
@@ -66,42 +52,57 @@ tripSecond :: (b -> b') -> (a,b,c) -> (a,b',c)
tripSecond f (x,y,z) = (x,f y,z)
scaleT :: Float -> (Point3,Point4,Point2) -> (Point3,Point4,Point2)
{-# INLINE scaleT #-}
scaleT x (a,b,(o,s)) = (a,b,(o,s*x))
overPos :: (Point3 -> Point3) -> RenderType -> RenderType
overPos f (RenderPoly vs) = RenderPoly $ map (first $ f) vs
overPos f (RenderLine vs) = RenderLine $ map (first $ f) vs
overPos f (RenderText vs) = RenderText $ map (\(a,b,c) -> (f a,b,c)) vs
overPos f (RenderCirc (a,b,c)) = RenderCirc (f a,b,c)
overPos _ RenderBlank = RenderBlank
overCol :: (Point4 -> Point4) -> RenderType -> RenderType
overCol f (RenderPoly vs) = RenderPoly $ map (second $ f) vs
overCol f (RenderLine vs) = RenderLine $ map (second $ f) vs
overCol f (RenderText vs) = RenderText $ map (\(a,b,c) -> (a,f b,c)) vs
overCol f (RenderCirc (a,b,c)) = RenderCirc (a,f b,c)
overCol _ RenderBlank = RenderBlank
scaleRen,translateRen :: Float -> Float -> RenderType -> RenderType
scaleRen x y (RenderPoly xs) = RenderPoly $ map (first $ scale3 x y) xs
scaleRen x y (RenderText xs) = RenderText $ map (tripFirst (scale3 x y ) . scaleT x) xs
--scaleRen x y (RenderText xs) = RenderText $ map (\(a,b,c) -> (a,b, (0,0.2))) xs
scaleRen x y rt = rt
translateRen x y (RenderPoly xs) = RenderPoly $ map (first $ translate3 x y) xs
translateRen x y (RenderText xs) = RenderText $ map (tripFirst $ translate3 x y) xs
--translateRen x y (RenderText xs) = RenderText $ map (tripFirst $ const (0.2,0.2,0)) xs
translateRen x y rt = rt
{-# INLINE scaleRen #-}
scaleRen x y (RenderText vs) = overPos (scale3 x y) $ RenderText $ map (scaleT x) vs
scaleRen x y (RenderCirc (a,b,c)) = overPos (scale3 x y) $ RenderCirc (a,b,c)
scaleRen x y rt = overPos (scale3 x y) rt
{-# INLINE translateRen #-}
translateRen x y = overPos $ translate3 x y
rotateRen,setDepthRen :: Float -> RenderType -> RenderType
rotateRen a (RenderPoly xs) = RenderPoly $ map (first $ rotate3 a) xs
rotateRen a (RenderText xs) = RenderText $ map (tripFirst $ rotate3 a) xs
rotateRen a rt = rt
setDepthRen a (RenderPoly xs) = RenderPoly $ map (first $ (\(x,y,_) -> (x,y,a))) xs
setDepthRen a (RenderText xs) = RenderText $ map (tripFirst $ (\(x,y,_) -> (x,y,a))) xs
setDepthRen a rt = rt
{-# INLINE rotateRen #-}
rotateRen a = overPos $ rotate3 a
{-# INLINE setDepthRen #-}
setDepthRen d = overPos $ \(x,y,_) -> (x,y,-d)
{-# INLINE colorRen #-}
colorRen :: RGBA -> RenderType -> RenderType
colorRen c (RenderPoly xs) = RenderPoly $ map (second $ const c) xs
colorRen c (RenderText xs) = RenderText $ map (tripSecond $ const c) xs
colorRen c rt = rt
colorRen c = overCol $ const c
stringToList :: String -> [(Point3,Point4,Point2)]
stringToList s = zipWith (\x (a,b,c) -> (translate3 x (0-dimText) a,b,c))
{-# INLINE stringToList #-}
stringToList s = zipWith (\x (a,b,c) -> (translate3 x 0 a,b,c))
[0,0.9*dimText..]
$ map charToTuple s
where dimText = 100
charToTuple :: Char -> (Point3,Point4,Point2)
{-# INLINE charToTuple #-}
charToTuple c = ((0,0,0),white,(offset,100))
where offset = fromIntegral (fromEnum c) - 32
picToFTree :: Picture -> FTree RenderType
{-# INLINE picToFTree #-}
picToFTree (Polygon ps) = FLeaf $ RenderPoly $ zip (map zeroZ $ polyToTris ps) $ repeat black
picToFTree (PolygonCol vs) = let (ps,cs) = unzip vs
in FLeaf $ RenderPoly $ zip (map zeroZ $ polyToTris ps) $ polyToTris cs
picToFTree (Circle r) = FLeaf $ RenderCirc $ ((0.5,0,0),red,r)
picToFTree Blank = FLeaf $ RenderBlank
picToFTree (Text s) = FLeaf $ RenderText $ stringToList s
picToFTree (Scale x y pic) = FBranch (scaleRen x y) $ picToFTree pic
@@ -110,10 +111,75 @@ picToFTree (Rotate a pic) = FBranch (rotateRen a) $ picToFTree pic
picToFTree (SetDepth a pic) = FBranch (setDepthRen a) $ picToFTree pic
picToFTree (Color c pic) = FBranch (colorRen c) $ picToFTree pic
picToFTree (Pictures pics) = FBranches $ map picToFTree pics
picToFTree (Line ps) = FLeaf $ RenderLine $ zip (map zeroZ $ doubleLine ps) $ repeat black
pokeTexts :: Ptr Float -> Ptr Float -> Ptr Float -> FTree RenderType -> IO Int
pokeTexts = go 0
where go n pa pb pc t = foldM (pokeText pa pb pc) n t
doubleLine :: [Point2] -> [Point2]
doubleLine (x:y:xs) = concat $ zipWith (:) (init (x:y:xs)) $ map (\a -> [a]) (y:xs)
doubleLine _ = []
pokeFold :: (Ptr Float, Ptr Float) -> F.FoldM IO RenderType Int
pokeFold (pa,pb) = F.FoldM
(pokePoly pa pb)
(return 0)
return
pokeTextFold :: (Ptr Float, Ptr Float,Ptr Float) -> F.FoldM IO RenderType Int
pokeTextFold (pa,pb,pc) = F.FoldM
(pokeText pa pb pc)
(return 0)
return
pokeCircFold :: (Ptr Float, Ptr Float,Ptr Float) -> F.FoldM IO RenderType Int
pokeCircFold (pa,pb,pc) = F.FoldM
(pokeCirc pa pb pc)
(return 0)
return
theFold :: (Ptr Float,Ptr Float)
-> (Ptr Float,Ptr Float,Ptr Float)
-> (Ptr Float,Ptr Float,Ptr Float)
-> (Ptr Float,Ptr Float)
-> F.FoldM IO RenderType (Int,Int,Int,Int)
theFold pas pbs pcs pds = (,,,) <$> pokeFold pas <*> pokeTextFold pbs <*> pokeCircFold pcs
<*> pokeLineFold pds
pokeLineFold :: (Ptr Float, Ptr Float) -> F.FoldM IO RenderType Int
pokeLineFold (pa,pb) = F.FoldM
(pokeLine pa pb)
(return 0)
return
pokeLine :: Ptr Float -> Ptr Float -> Int -> RenderType -> IO Int
pokeLine pa pb n (RenderLine vs) = foldM (pokeLineVert pa pb) n vs
pokeLine _ _ n _ = return n
pokeLineVert :: Ptr Float -> Ptr Float -> Int -> (Point3, Point4) -> IO Int
pokeLineVert pa pb n ((x,y,z),(r,g,b,a))
| n > 20000 * 2 = return n
| otherwise = do
pokeElemOff pa (3*n+0) x
pokeElemOff pa (3*n+1) y
pokeElemOff pa (3*n+2) z
pokeElemOff pb (4*n+0) r
pokeElemOff pb (4*n+1) g
pokeElemOff pb (4*n+2) b
pokeElemOff pb (4*n+3) a
return (n+1)
pokeCirc :: Ptr Float -> Ptr Float -> Ptr Float -> Int -> RenderType -> IO Int
pokeCirc pa pb pc n (RenderCirc vs) = pokeCircVert pa pb pc n vs
pokeCirc _ _ _ n _ = return n
pokeCircVert :: Ptr Float -> Ptr Float -> Ptr Float -> Int -> (Point3, Point4, Float) -> IO Int
pokeCircVert pa pb pc n ((x,y,z),(r,g,b,a),s)
| n > 20000 * 2 = return n
| otherwise = do
pokeElemOff pa (3*n+0) x
pokeElemOff pa (3*n+1) y
pokeElemOff pa (3*n+2) z
pokeElemOff pb (4*n+0) r
pokeElemOff pb (4*n+1) g
pokeElemOff pb (4*n+2) b
pokeElemOff pb (4*n+3) a
pokeElemOff pc n s
return (n+1)
pokeText :: Ptr Float -> Ptr Float -> Ptr Float -> Int -> RenderType -> IO Int
pokeText pa pb pc n (RenderText vs) = foldM (pokeTextVert pa pb pc) n vs
@@ -155,33 +221,6 @@ pokeVert pa pb n ((x,y,z),(r,g,b,a))
pokeElemOff pb (4*n+3) a
return (n+1)
reducePicture :: Picture -> (DL.DList Float,DL.DList Float)
{-# INLINE reducePicture #-}
reducePicture = reducePicture' black id
where
reducePicture' :: RGBA -> (Point3 -> Point3) -> Picture -> (DL.DList Float,DL.DList Float)
reducePicture' col tran Blank = (DL.empty,DL.empty)
reducePicture' col tran (Text _) = (DL.empty,DL.empty)
reducePicture' col tran (Polygon ps)
= ( DL.fromList $ concatMap (flat3 . tran . zeroZ) (polyToTris ps)
, DL.fromList $ concatMap (flat4 . const col) (polyToTris ps)
)
reducePicture' col tran (Scale x y pic)
= reducePicture' col (tran . scale3 x y) pic
reducePicture' col tran (Translate x y pic)
= reducePicture' col (tran . translate3 x y) pic
reducePicture' col tran (Rotate a pic)
= reducePicture' col (tran . rotate3 a) pic
reducePicture' col tran (SetDepth a pic)
= reducePicture' col (tran . \(x,y,z) -> (x,y,a)) pic
reducePicture' col tran (Color c pic)
= reducePicture' c tran pic
reducePicture' col tran (Pictures pics)
= foldr com (DL.empty,DL.empty) $ map (reducePicture' col tran) pics
where com (xs,ys) (xs',ys') = (xs <> xs', ys <> ys')
translate3 :: Float -> Float -> Point3 -> Point3
{-# INLINE translate3 #-}
translate3 a b (x,y,z) = (x+a,y+b,z)
@@ -193,72 +232,57 @@ rotate3 :: Float -> Point3 -> Point3
rotate3 a (x,y,z) = (x',y',z)
where (x',y') = rotateV a (x,y)
renderPicture' :: PreloadData -> Picture -> IO ()
renderPicture' pdata pic = do
renderPicture' :: PreloadData -> Float -> (Float,Float) -> Picture -> IO ()
renderPicture' pdata zoom (winx,winy) pic = do
let firstIndex = 0
fSize = sizeOf (0::Float)
(nTriVs,numVert',numCircVs,nLineVs)
<- F.foldM (theFold (_ptrPosVBO pdata, _ptrColVBO pdata)
(_ptrCharPos pdata, _ptrCharCol pdata, _ptrCharTex pdata)
(_ptrCircPos pdata, _ptrCircCol pdata, _ptrCircSca pdata)
(_ptrLinePos pdata, _ptrLineCol pdata)
) $ picToFTree pic
depthFunc $= Just Less
-- draw triangles
currentProgram $= Just (_basicShader pdata)
numVert <- pokePic (_ptrPosVBO pdata) (_ptrColVBO pdata) $ picToFTree pic
bindVertexArrayObject $= Just (_basicVAO pdata)
bindBuffer ArrayBuffer $= Just (_posVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert * 3, _ptrPosVBO pdata, StreamDraw)
bufferData ArrayBuffer $= (fromIntegral $ fSize * nTriVs * 3, _ptrPosVBO pdata, StreamDraw)
bindBuffer ArrayBuffer $= Just (_colVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert * 4, _ptrColVBO pdata, StreamDraw)
drawArrays Triangles (fromIntegral firstIndex) (fromIntegral $ numVert)
bufferData ArrayBuffer $= (fromIntegral $ fSize * nTriVs * 4, _ptrColVBO pdata, StreamDraw)
drawArrays Triangles (fromIntegral firstIndex) (fromIntegral $ nTriVs)
-- draw lines, don't need to change the program or vaos, just need to bind the
-- vbos and draw
bindBuffer ArrayBuffer $= Just (_posVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * nLineVs * 3, _ptrLinePos pdata, StreamDraw)
bindBuffer ArrayBuffer $= Just (_colVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * nLineVs * 4, _ptrLineCol pdata, StreamDraw)
drawArrays Lines (fromIntegral firstIndex) (fromIntegral $ nLineVs)
-- draw circles
currentProgram $= Just (_circShader pdata)
uniform (_uniWinSize pdata) $= Vector2 winx winy
uniform (_csZoomUni pdata) $= zoom
bindVertexArrayObject $= Just (_circVAO pdata)
bindBuffer ArrayBuffer $= Just (_posVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *3, _ptrCircPos pdata, StreamDraw)
bindBuffer ArrayBuffer $= Just (_colVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *4, _ptrCircCol pdata, StreamDraw)
bindBuffer ArrayBuffer $= Just (_texVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *1, _ptrCircSca pdata, StreamDraw)
drawArrays Points (fromIntegral firstIndex) (fromIntegral $ numCircVs)
currentProgram $= Just (_textShader pdata)
numVert' <- pokeTexts (_ptrPosVBO pdata) (_ptrColVBO pdata) (_ptrTexVBO pdata) $ picToFTree pic
bindVertexArrayObject $= Just (_textVAO pdata)
bindBuffer ArrayBuffer $= Just (_posVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *3, _ptrPosVBO pdata, StreamDraw)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *3, _ptrCharPos pdata, StreamDraw)
bindBuffer ArrayBuffer $= Just (_colVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *4, _ptrColVBO pdata, StreamDraw)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *4, _ptrCharCol pdata, StreamDraw)
bindBuffer ArrayBuffer $= Just (_texVBO pdata)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *2, _ptrTexVBO pdata, StreamDraw)
bufferData ArrayBuffer $= (fromIntegral $ fSize * numVert' *2, _ptrCharTex pdata, StreamDraw)
drawArrays Points (fromIntegral firstIndex) (fromIntegral $ numVert')
renderPicture :: PreloadData -> Picture -> IO ()
renderPicture pdata pic = do
currentProgram $= Just (_basicShader pdata)
bindVertexArrayObject $= Just (_basicVAO pdata)
bindBuffer ArrayBuffer $= Just (_posVBO pdata)
let firstIndex = 0
let (vs,cs) = reducePicture pic
vertices :: [Float]
vertices = DL.toList vs
numVertices = length vertices
vertexSize = sizeOf (head vertices)
pokeArray (_ptrPosVBO pdata) vertices
bufferData ArrayBuffer $= (fromIntegral (length vertices * vertexSize), _ptrPosVBO pdata, StreamDraw)
-- marshallVs vertices $ \ptr -> do
-- bufferData ArrayBuffer $= (fromIntegral (numVertices * vertexSize), ptr, StreamDraw)
bindBuffer ArrayBuffer $= Just (_colVBO pdata)
let colVs = DL.toList cs
pokeArray (_ptrColVBO pdata) colVs
bufferData ArrayBuffer $= (fromIntegral (length colVs * vertexSize), _ptrColVBO pdata, StreamDraw)
-- marshallVs colVs $ \ptr -> do
-- bufferData ArrayBuffer $= (fromIntegral (div (4 * numVertices * colVsize) 3), ptr, StreamDraw)
drawArrays Triangles (fromIntegral firstIndex) (fromIntegral $ numVertices)
---- currentProgram $= Just (_textShader pdata)
---- bindVertexArrayObject $= Just (_textVAO pdata)
---- bindBuffer ArrayBuffer $= Just (_posVBO pdata)
---- let vertices' = concatMap flat3 posChar
---- numVertices' = length posChar
---- vertexSize' = sizeOf $ head vertices'
---- pokeArray (_ptrPosVBO pdata) vertices'
---- bufferData ArrayBuffer $= (fromIntegral (3 * numVertices' * vertexSize'), _ptrPosVBO pdata, StreamDraw)
---- --withArray vertices' $ \ptr -> do
---- -- bufferData ArrayBuffer $= (fromIntegral (3 * numVertices' * vertexSize'), ptr, StreamDraw)
---- bindBuffer ArrayBuffer $= Just (_colVBO pdata)
---- pokeArray (_ptrColVBO pdata) $ concatMap flat4 colChar
---- bufferData ArrayBuffer $= (fromIntegral (4 * numVertices' * vertexSize'), _ptrColVBO pdata, StreamDraw)
---- bindBuffer ArrayBuffer $= Just (_texVBO pdata)
---- pokeArray (_ptrTexVBO pdata) $ concatMap flat2 texChar
---- bufferData ArrayBuffer $= (fromIntegral (2 * numVertices' * vertexSize'), _ptrTexVBO pdata, StreamDraw)
---- drawArrays Points (fromIntegral firstIndex) (fromIntegral $ numVertices')
bufferOffset :: Integral a => a -> Ptr b