Files
loop/src/Picture/Preload.hs
T
2021-02-27 02:09:04 +01:00

200 lines
6.8 KiB
Haskell

{-# LANGUAGE TemplateHaskell #-}
--{-# LANGUAGE Strict #-}
module Picture.Preload
where
import Codec.Picture
import Graphics.Rendering.OpenGL hiding (Point (..),translate,scale,imageHeight,imageWidth)
import qualified Graphics.Rendering.OpenGL as GL
import qualified Data.Vector.Storable as V
import Control.Lens
import Control.Monad
import Foreign
import Shaders
data RenderData = RenderData
{ --_charMap :: Image PixelRGBA8
_textures :: [TextureObject]
, _basicShader :: (Program, [UniformLocation])
, _textShader :: (Program, [UniformLocation])
, _circShader :: (Program, [UniformLocation])
, _arcShader :: (Program, [UniformLocation])
, _fadeCircleShader :: (Program, [UniformLocation])
, _backShader :: (Program, [UniformLocation])
, _wallShadowShader :: (Program, [UniformLocation])
, _triVAO :: VAO
, _lineVAO :: VAO
, _textVAO :: VAO
, _circVAO :: VAO
, _arcVAO :: VAO
, _backVAO :: VAO
, _wallVAO :: VAO
, _fadeCircVAO :: VAO
, _posVBO :: BufferObject
, _colVBO :: BufferObject
, _texVBO :: BufferObject
, _wssLightPos :: UniformLocation
, _dummyVBO :: BufferObject
, _dummyPtr :: Ptr Float
}
data VAO = VAO
{ _vao :: VertexArrayObject
, _vaoBufferTargets :: [(BufferObject,Ptr Float,Int)]
}
makeLenses ''RenderData
makeLenses ''VAO
floatSize = sizeOf (0.5 :: GLfloat)
setupVAO :: [(BufferObject,GLuint,Int)] -> IO VAO
setupVAO ps = do
theVAO <- genObjectName
bindVertexArrayObject $= Just theVAO
forM_ ps setupArrayBuffer
ptrs <- forM ps setupVBOPointers
return $ VAO theVAO ptrs
numDrawableElements :: Int
numDrawableElements = 50000
setupVBOPointers :: (BufferObject,GLuint,Int) -> IO (BufferObject,Ptr Float,Int)
setupVBOPointers (vbo,_,vsize) = do
thePtr <- mallocArray (vsize * numDrawableElements)
return (vbo,thePtr,vsize)
setupArrayBuffer :: (BufferObject,GLuint,Int) -> IO ()
setupArrayBuffer (vbo,aloc,i) = do
bindBuffer ArrayBuffer $= Just vbo
vertexAttribPointer (AttribLocation aloc) $=
( ToFloat
, VertexArrayDescriptor (fromIntegral i)
Float
(fromIntegral $ floatSize * i)
(bufferOffset 0)
)
vertexAttribArray (AttribLocation aloc) $= Enabled
loadTextures :: IO [Image PixelRGBA8]
loadTextures = do
-- echarMap <- readImage "data/texture/smudgedDirt.png"
echarMap <- readImage "data/texture/charMap.png"
case echarMap of
Left err -> do
putStrLn err
return []
Right charMap ->
return [convertRGBA8 charMap]
bufferOffset :: Integral a => a -> Ptr b
bufferOffset = plusPtr nullPtr . fromIntegral
preloadRender :: IO RenderData
preloadRender = do
-- compile shader programs
bs <- makeSourcedShader "basic" [VertexShader,FragmentShader]
ts <- makeSourcedShader "character" [VertexShader,GeometryShader,FragmentShader]
cs <- makeSourcedShader "circle" [VertexShader,GeometryShader,FragmentShader]
as <- makeSourcedShader "arc" [VertexShader,GeometryShader,FragmentShader]
fcs <- makeSourcedShader "fadeCircle" [VertexShader,GeometryShader,FragmentShader]
bgs <- makeSourcedShader "background" [VertexShader,GeometryShader,FragmentShader]
wss <- makeSourcedShader "wallShadow" [VertexShader,GeometryShader,FragmentShader]
wssLightPosUniLoc <- GL.uniformLocation (fst wss) "lightPos"
-- get uniform locations
--setup vbos
--need to be bound before assigning the vertex attribute pointers
posVBO <- genObjectName
colVBO <- genObjectName
texVBO <- genObjectName
--the following vbo is set up to contain one fixed vertex
dummyvbo <- genObjectName
dummyptr <- malloc
poke dummyptr 0
bindBuffer ArrayBuffer$= Just dummyvbo
bufferData ArrayBuffer$= (fromIntegral floatSize, dummyptr, StaticDraw)
-- load charmap as texture
-- Right cmap <- readImage "data/texture/smudgedDirt.png"
Right cmap <- readImage "data/texture/charMap.png"
let tex = convertRGBA8 cmap
chartex <- genObjectName
textureBinding Texture2D $= Just chartex
let texData = V.toList $ imageData tex
wtex = fromIntegral $ imageWidth tex
htex = fromIntegral $ imageHeight tex
withArray texData $ \ptr -> do
texImage2D Texture2D NoProxy 0 RGBA8 (TextureSize2D wtex htex) 0
(PixelData RGBA UnsignedByte ptr)
generateMipmap' Texture2D
textureFilter Texture2D $= ((Linear',Just Linear') , Nearest)
Right cmap' <- readImage "data/texture/smudgedDirt.png"
let dirt = convertRGBA8 cmap'
dirttex <- genObjectName
textureBinding Texture2D $= Just dirttex
let texData' = V.toList $ imageData dirt
wtex' = fromIntegral $ imageWidth dirt
htex' = fromIntegral $ imageHeight dirt
withArray texData' $ \ptr -> do
texImage2D Texture2D NoProxy 0 RGBA8 (TextureSize2D wtex' htex') 0
(PixelData RGBA UnsignedByte ptr)
generateMipmap' Texture2D
textureFilter Texture2D $= ((Linear',Just Linear') , Nearest)
--textureBinding Texture2D $= Just chartex
trivao <- setupVAO [(posVBO,0,3),(colVBO,1,4)]
linevao <- setupVAO [(posVBO,0,3),(colVBO,1,4)]
textvao <- setupVAO [(posVBO,0,3),(colVBO,1,4),(texVBO,2,2)]
circvao <- setupVAO [(posVBO,0,3),(colVBO,1,4),(texVBO,2,1)]
arcvao <- setupVAO [(posVBO,0,3),(colVBO,1,4),(texVBO,2,4)]
backgroundvao <- setupVAO [(posVBO,0,4),(colVBO,1,2)]
wallvao <- setupVAO [(posVBO,0,4)]--,(colVBO,1,4)]
fadecircvao <- setupVAO [(posVBO,0,4)]
return $ RenderData
{ -- _charMap = convertRGBA8 cmap
_textures = [chartex,dirttex]
,_basicShader = bs
, _textShader = ts
, _circShader = cs
, _arcShader = as
, _fadeCircleShader = fcs
, _backShader = bgs
, _wallShadowShader = wss
, _triVAO = trivao
, _textVAO = textvao
, _circVAO = circvao
, _arcVAO = arcvao
, _lineVAO = linevao
, _backVAO = backgroundvao
, _wallVAO = wallvao
, _fadeCircVAO = fadecircvao
, _posVBO = posVBO
, _colVBO = colVBO
, _texVBO = texVBO
, _dummyVBO = dummyvbo
, _dummyPtr = dummyptr
, _wssLightPos = wssLightPosUniLoc
}
vaoPointers :: VAO -> [Ptr Float]
vaoPointers = (\(_,ps,_) -> ps) . unzip3 . _vaoBufferTargets
cleanUpRenderPreload :: RenderData -> IO ()
cleanUpRenderPreload pd = do
mapM_ free $ vaoPointers $ _triVAO pd
mapM_ free $ vaoPointers $ _textVAO pd
mapM_ free $ vaoPointers $ _circVAO pd
mapM_ free $ vaoPointers $ _arcVAO pd
mapM_ free $ vaoPointers $ _lineVAO pd
free $ _dummyPtr pd