--{-# LANGUAGE TemplateHaskell #-} --{-# OPTIONS_GHC -Wno-unused-top-binds #-} module Preload.Render ( preloadRender, cleanUpRenderPreload, ) where import Geometry.Data import MatrixHelper import GLHelp import Control.Lens import Control.Monad import Data.Preload.Render import qualified Data.Vector.Mutable as MV import Foreign import Framebuffer.Setup import Shader import Shader.AuxAddition import Shader.Bind import Shader.Compile import Shader.Data import Shader.Parameters import Graphics.GL.Core45 numDrawableWalls :: Int numDrawableWalls = 5000 preloadRender :: IO RenderData preloadRender = do -- set up uniform buffer object theUBO <- mglCreate glCreateBuffers glNamedBufferData theUBO 64 nullPtr GL_STREAM_DRAW glBindBufferBase GL_UNIFORM_BUFFER 0 theUBO isoUBO <- mglCreate glCreateBuffers withArray (isoMatrix 0 1 (V2 0 0) (V2 2 2)) $ \ptr -> glNamedBufferStorage isoUBO 64 ptr 0 lightsubo <- mglCreate glCreateBuffers glNamedBufferData lightsubo 640 nullPtr GL_STREAM_DRAW glBindBufferBase GL_UNIFORM_BUFFER 1 lightsubo -- setup wall points VBO, VAOs and shaders wpVBOname <- mglCreate glCreateBuffers wpVBOptr <- mallocArray (8 * numDrawableWalls) glNamedBufferData wpVBOname ( fromIntegral $ floatSize * numDrawableWalls * 8) nullPtr GL_STREAM_DRAW let wpVBO = VBO{_vboName = wpVBOname, _vboPtr = wpVBOptr, _vboAttribSizes = [4, 4], _vboStride = 8} -- wpVAOname <- genObjectName -- bindVertexArrayObject $= Just wpVAOname wpVAOname <- mglCreate glCreateVertexArrays glBindVertexArray wpVAOname setupVertexAttribPointer wpVAOname wpVBOname 0 4 8 0 --wpColVAOname <- genObjectName --bindVertexArrayObject $= Just wpColVAOname wpColVAOname <- mglCreate glCreateVertexArrays glBindVertexArray wpColVAOname setupVertexAttribPointer wpColVAOname wpVBOname 0 4 8 0 setupVertexAttribPointer wpColVAOname wpVBOname 1 4 8 4 let wpVAO = VAO{_vaoName = wpVAOname, _vaoVBO = wpVBO, _vaoAttribSizes = [4], _vaoStride = 8} wpColVAO = VAO{_vaoName = wpColVAOname, _vaoVBO = wpVBO, _vaoAttribSizes = [4,4], _vaoStride = 8} -- setup window points VBO, VAOs and shaders winVBOname <- mglCreate glCreateBuffers winVBOptr <- mallocArray (8 * numDrawableWalls) glNamedBufferData wpVBOname ( fromIntegral $ floatSize * numDrawableWalls * 8) nullPtr GL_STREAM_DRAW let winVBO = VBO{_vboName = winVBOname, _vboPtr = winVBOptr, _vboAttribSizes = [4, 4], _vboStride = 8} --winColVAOname <- genObjectName --bindVertexArrayObject $= Just winColVAOname winColVAOname <- mglCreate glCreateVertexArrays glBindVertexArray winColVAOname setupVertexAttribPointer winColVAOname winVBOname 0 4 8 0 setupVertexAttribPointer winColVAOname winVBOname 1 4 8 4 let winColVAO = VAO {_vaoName = winColVAOname, _vaoVBO = winVBO, _vaoAttribSizes = [4,4], _vaoStride = 8} -- setup shape geometry/cap VBO and two VAOs shEBOptr <- mallocArray numDrawableElements shEBOname <- mglCreate glCreateBuffers glNamedBufferData shEBOname ( fromIntegral $ glushortSize * numDrawableElements) nullPtr GL_STREAM_DRAW let shEBO = EBO{_eboName = shEBOname, _eboPtr = shEBOptr} shVBOname <- mglCreate glCreateBuffers shVBOptr <- mallocArray (7 * numDrawableElements) glNamedBufferData shVBOname ( fromIntegral $ floatSize * numDrawableElements * 7) nullPtr GL_STREAM_DRAW let shVBO = VBO{_vboName = shVBOname, _vboPtr = shVBOptr, _vboAttribSizes = [4, 4], _vboStride = 8} --shPosColVAOname <- genObjectName --bindVertexArrayObject $= Just shPosColVAOname shPosColVAOname <- mglCreate glCreateVertexArrays glBindVertexArray shPosColVAOname setupVertexAttribPointer shPosColVAOname shVBOname 0 3 7 0 setupVertexAttribPointer shPosColVAOname shVBOname 1 4 7 3 --bindBuffer ElementArrayBuffer $= Just shEBOname glVertexArrayElementBuffer shPosColVAOname shEBOname --shPosVAOname <- genObjectName --bindVertexArrayObject $= Just shPosVAOname shPosVAOname <- mglCreate glCreateVertexArrays glBindVertexArray shPosVAOname setupVertexAttribPointer shPosVAOname shVBOname 0 3 7 0 --bindBuffer ElementArrayBuffer $= Just shEBOname glVertexArrayElementBuffer shPosVAOname shEBOname let shPosColVAO = VAO {_vaoName = shPosColVAOname, _vaoVBO = shVBO, _vaoAttribSizes = [3,4], _vaoStride = 7} shPosVAO = VAO{_vaoName = shPosVAOname, _vaoVBO = shVBO, _vaoAttribSizes = [3], _vaoStride = 7} --setup silhouette edge VAO --shEdgeVAOname <- genObjectName --bindVertexArrayObject $= Just shEdgeVAOname shEdgeVAOname <- mglCreate glCreateVertexArrays glBindVertexArray shEdgeVAOname setupVertexAttribPointer shEdgeVAOname shVBOname 0 3 7 0 --setup ebo for silhouette edges silEBOname <- mglCreate glCreateBuffers silEBOptr <- mallocArray numDrawableElements -- it may be important to bind this while the correct VAO is bound glVertexArrayElementBuffer shEdgeVAOname silEBOname --bindBuffer ElementArrayBuffer $= Just silEBOname glNamedBufferData silEBOname ( fromIntegral $ glushortSize * numDrawableElements) nullPtr GL_STREAM_DRAW let silEBO = EBO{_eboName = silEBOname, _eboPtr = silEBOptr} shEdgeVAO = VAO{_vaoName = shEdgeVAOname, _vaoVBO = shVBO, _vaoAttribSizes = [3], _vaoStride = 7} -- shEdgeVAO is unecessary? -- lighting shaders lightingWallShadShad <- makeShaderUsingVAO "lighting/wallShadow" [vert, geom, frag] EPoints wpVAO >>= addUniforms ["lightPos","rad"] lightingCapShad <- makeShaderUsingVAO "lighting/cap" [vert, geom] ETriangles shPosVAO >>= addUniforms ["lightPos"] lightingLineShadowShad <- makeShaderUsingVAO "lighting/lineShadow" [vert, geom] ELinesAdjacency shEdgeVAO >>= addUniforms ["lightPos", "radiusUniform"] shadowedgeshader <- makeShaderUsingVAO "shadow/edge" [vert, geom] ELinesAdjacency shEdgeVAO shadowcapshader <- makeShaderUsingVAO "shadow/cap" [vert, geom] ETriangles shPosVAO shadowwallshader <- makeShaderUsingVAO "shadow/wallShadow" [vert, geom] EPoints wpVAO shadowlightshader <- makeShaderSized "shadow/light" [vert, geom, frag] [1] 1 EPoints shadowcombineshader <- makeShaderSized "shadow/combine" [vert,geom,frag] [1] 1 EPoints poke (shadVBOptr' shadowlightshader) 1 -- positional shader positionalBlankShad <- makeShader "positional/blank" [vert, frag] [3] ETriangles -- 2D draw shaders bslist <- makeShader "dualTwoD/basic" [vert, frag] [3, 4] ETriangles bslista <- makeShader "dualTwoD/basic" [vert, frag] [3, 4] ETriangles aslist <- makeShader "dualTwoD/arc" [vert, frag] [3, 4, 3] ETriangles eslist <- makeShader "dualTwoD/ellipse" [vert, geom, frag] [3, 4] ETriangles bezierQuadShader <- makeShader "dualTwoD/bezierQuad" [vert, frag] [3, 4, 4] ETriangleStrip cslist <- makeShader "dualTwoD/character" [vert, frag] [3, 4, 2] ETriangles >>= vaddTextureNoFilter "data/texture/charMap.png" -- this should really be a 2d texture array basicTweakZShad <- makeShader "dualTwoD/basicTweakZ" [vert, frag] [4, 4] ETriangles -- fullscreen shaders --fullscreenAlphaHalveShad <- makeShaderSized "fullscreen/alphaHalve" [vert,frag] [2] 4 ETriangleStrip --pokeArray (shadVBOptr fullscreenAlphaHalveShad) $ concat cornerListNoCoord -- texture shaders, no textures attached fsShad <- makeShaderSized "texture/simple" [vert, frag] [2, 2] 4 ETriangleStrip -- note we directly poke the shader vertex data here -- could possibly use an indirect draw call pokeArray (shadVBOptr' fsShad) $ concat cornerList let fsshadvao = fsShad ^. shadVAO' bloomBlurShad <- makeShaderUsingVAO "texture/bloomBlur" [vert, frag] ETriangleStrip fsshadvao colorBlurShad <- makeShaderUsingVAO "texture/colorBlur" [vert, frag] ETriangleStrip fsshadvao grayscaleShad <- makeShaderUsingVAO "texture/grayscale" [vert, frag] ETriangleStrip fsshadvao lightingTextureShad <- makeShaderUsingVAO "lighting/texture" [vert, frag] ETriangleStrip fsshadvao >>= addUniforms ["lightPos", "lumRad"] -- >>= addUniforms ["lightPos", "lumRad"] -- >>= addUniforms ["lightID"] barrelShad <- makeShader "texture/barrel" [vert, geom, frag] [2, 2, 2, 1] EPoints -- blank wallShader wallBlankShad <- makeShaderUsingVAO "wall/blank" [vert, geom, frag] EPoints wpColVAO -- textured wallShader wallTextureShad <- makeShaderUsingVAO "wall/texture" [vert, geom, frag] EPoints wpColVAO >>= addSamplerTexture2D "data/texture/grayscaleDirt.png" ---- texture array shader textArrayShad <- makeShader "texture/arrayPos" [vert, frag] [3, 3] ETriangles >>= addTextureArray "data/texture/ayene_wooden_floor_transformed.png" -- >>= addTextureArray "data/texture/ayene_wooden_floor.png" -- bind fixed vertex data bindShaderBuffers [fsShad] [4, 4] framebuf2 <- setupTextureFramebuffer 800 600 framebuf3 <- setupTextureFramebuffer 800 600 rboBaseBloomName <- mglCreate glCreateRenderbuffers glNamedRenderbufferStorage rboBaseBloomName GL_DEPTH24_STENCIL8 800 600 fboBaseName <- setupFramebuffer2GivenStencil rboBaseBloomName fboCloudName <- setupFramebuffer2GivenStencil rboBaseBloomName fboBloomName <- setupFramebufferGivenStencil rboBaseBloomName fboColorName <- setupFramebufferGivenStencil rboBaseBloomName fboPosName <- setupFramebufferGivenStencil rboBaseBloomName fboLightingName <- setupFramebufferGivenStencil rboBaseBloomName --fboLightingHighName <- setupFramebufferGivenStencil rboBaseBloomName fboShadowName <- setupShadowFramebuffer fboHalf1Name <- setupTextureFramebuffer 300 300 fboHalf2Name <- setupTextureFramebuffer 300 300 fboHalf3Name <- setupTextureFramebuffer 300 300 -- reset to default framebuffer, ready for drawing direct to screen glBindFramebuffer GL_FRAMEBUFFER 0 -- set the clearColor to have 1 alpha glClearColor 0 0 0 1 shadV <- MV.new 6 zipWithM_ (MV.write shadV) [0 .. 5] [ bslist -- note the ordering is very important , basicTweakZShad -- ShadNum , bezierQuadShader , cslist , aslist , eslist ] initializeGLState return $ RenderData { _pictureShaders = shadV , _shapeShader = bslista{_shadVAO' = shPosColVAO} , _shapeEBO = shEBO , _silhouetteEBO = silEBO , _lightingCapShader = lightingCapShad , _lightingLineShadowShader = lightingLineShadowShad , _lightingWallShadShader = lightingWallShadShad , _shadowEdgeShader = shadowedgeshader , _shadowCapShader = shadowcapshader , _shadowWallShader = shadowwallshader , _shadowLightShader = shadowlightshader , _shadowCombineShader = shadowcombineshader , _positionalBlankShader = positionalBlankShad , _wallBlankShader = wallBlankShad , _wallTextureShader = wallTextureShad , _windowShader = wallBlankShad{_shadVAO' = winColVAO} , _textureArrayShader = textArrayShad , _fullscreenShader = fsShad , _lightingTextureShader = lightingTextureShad , _bloomBlurShader = bloomBlurShad , _colorBlurShader = colorBlurShad , _barrelShader = barrelShad , _grayscaleShader = grayscaleShad , _fbo2 = framebuf2 , _fbo3 = framebuf3 , _fboHalf1 = fboHalf1Name , _fboHalf2 = fboHalf2Name , _fboHalf3 = fboHalf3Name , _fboLighting = fboLightingName --, _fboLightingHigh = fboLightingHighName , _fboShadow = fboShadowName , _fboBase = fboBaseName , _fboCloud = fboCloudName , _fboBloom = fboBloomName , _fboColor = fboColorName , _fboPos = fboPosName , _rboBaseBloom = rboBaseBloomName , _matUBO = theUBO , _isoMatUBO = isoUBO , _lightsUBO = lightsubo } --------------------end preloadRender cornerList :: [[Float]] cornerList = [ [-1, 1, 0, 1] , [-1, -1, 0, 0] , [1, 1, 1, 1] , [1, -1, 1, 0] ] --cornerListForTriangles :: [[Float]] --cornerListForTriangles = -- [ [-1, 1, 0, 1] -- , [-1, -1, 0, 0] -- , [1, 1, 1, 1] -- , [-1, -1, 0, 0] -- , [1, 1, 1, 1] -- , [1, -1, 1, 0] -- ] initializeGLState :: IO () initializeGLState = do glEnable GL_DEPTH_TEST cleanUpRenderPreload :: RenderData -> IO () cleanUpRenderPreload pd = do -- TODO fix this --mapM_ freeShaderPointers $ _pictureShaders pd freeShaderPointers' $ _lightingWallShadShader pd freeShaderPointers' $ _fullscreenShader pd