Files
loop/src/Dodge/Render.hs
T
2021-09-01 11:18:53 +01:00

260 lines
9.7 KiB
Haskell

{- |
Contains the central drawing functions for the dodge loop. -}
module Dodge.Render
( doDrawing
)
where
import Dodge.Data
import Dodge.Config.Data
import Dodge.Base.Window
import Dodge.Render.Picture
--import Dodge.Creature.ShadowBox
import Geometry
import Render
import Data.Preload.Render
import Shader
import Shader.Poke
import Shader.Bind
import Shader.Data
import MatrixHelper
--import Polyhedra.Data
import Polyhedra
--import Tuple
import Foreign
--import Control.Applicative
--import Control.Monad.State
import Control.Lens
import Control.Monad
--import qualified Control.Foldl as F
--import Data.Tuple.Extra
--import Data.List
--import Data.Bifunctor
--import Data.Function
--import qualified Data.IntMap.Strict as IM
--import qualified Data.Map as M
--import qualified Data.Set as S
import Graphics.Rendering.OpenGL hiding (color,scale,translate,rotate)
import qualified SDL
import qualified Data.Vector.Unboxed.Mutable as UMV
doDrawing :: RenderData -> World -> IO Word32
doDrawing pdata w = do
sTicks <- SDL.ticks
let rot = _cameraRot w
camzoom = _cameraZoom w
trans = _cameraCenter w
wins = V2 (getWindowX w) (getWindowY w)
(wallPointsCol,windowPoints) = wallsAndWindows w
lightPoints = lightsForGloom w
viewFroms@(V2 vfx vfy) = _cameraViewFrom w
viewFrom3d = Vector3 vfx vfy 20
shadV = _pictureShaders pdata
-- bind as much data into vbos as feasible at this point
-- poke wall points and colors
nWalls <- poke224s (shadVBOptr $ _wallTextureShader pdata) wallPointsCol
nSils <- pokePoint3s (shadVBOptr $ _lightingLineShadowShader pdata)
$
--youSil w ++
_foregroundEdgeVerx w
-- poke foreground geometry for caps
nCaps <- pokePoint3s (shadVBOptr $ _lightingCapShader pdata)
$ concatMap polyToGeoRender (foregroundPics w)
-- bind wall points, silhouette data, surface geometry
uncurry bindShaderBuffers $ unzip
[ ( _wallTextureShader pdata, nWalls)
, (_lightingLineShadowShader pdata, nSils)
, (_lightingCapShader pdata, nCaps)
]
-- set the coordinate uniform ready for drawing elements using world coordinates
bufferUBO $ perspectiveMatrixb rot camzoom trans wins viewFroms
viewport $= (Position 0 0
, divideSize (w ^. config . shadow_resolution) $ Size (round $ fstV2 wins) (round $ sndV2 wins))
bindFramebuffer Framebuffer $= fst (_fboBase pdata)
clearColor $= Color4 0 0 0 0
clear [ColorBuffer,DepthBuffer]
depthFunc $= Just Less
-- draw wall occlusions from the camera's point of view
currentProgram $= Just (_shaderProgram $ _lightingOccludeShader pdata)
uniform (head $ _shaderCustomUnis $ _lightingOccludeShader pdata)
$= viewFrom3d
drawShader (_lightingOccludeShader pdata) nWalls
--draw walls onto base buffer
if w ^. config . wall_textured
then renderTextureWalls pdata nWalls
else renderBlankWalls pdata nWalls
---draw foreground geometry onto base buffer
renderFoldable shadV $ polysToPic $ foregroundPics w
--draw objects onto base buffer
layerCounts <- UMV.replicate (6*6) 0
pokeBindFoldableLayer shadV layerCounts $ worldPictures w
renderLayer 0 shadV layerCounts
--draw floor onto base buffer
nTextArrayVs <- pokePoint33s (shadVBOptr $ _textureArrayShader pdata) (_floorTiles w)
bindShaderBuffers [_textureArrayShader pdata] [nTextArrayVs]
drawShader (_textureArrayShader pdata) nTextArrayVs
--draw bloom onto bloom buffer
bindFramebuffer Framebuffer $= fst (_fboBloom pdata)
clear [ColorBuffer]
blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
depthMask $= Disabled
renderLayer 3 shadV layerCounts
depthMask $= Enabled
renderLayer 1 shadV layerCounts
--setup downscale viewport for blurring bloom
viewport $= (Position 0 0
, divideSize (2 * (w ^. config . shadow_resolution)) $ Size (round $ fstV2 wins) (round $ sndV2 wins))
bindFramebuffer Framebuffer $= fst (_fboFourth1 pdata)
depthFunc $= Just Always
textureBinding Texture2D $= Just (snd $ _fboBloom pdata)
blend $= Disabled
drawShader (_bloomBlurShader pdata) 4
replicateM_ 5 $ pingPongBetween (_fboFourth1 pdata) (_fboFourth2 pdata) (_bloomBlurShader pdata)
blend $= Enabled
viewport $= (Position 0 0
, divideSize (w ^. config . shadow_resolution) $ Size (round $ fstV2 wins) (round $ sndV2 wins))
--draw lightmap for base buffer
bindFramebuffer Framebuffer $= fst (_fboLighting pdata)
createLightMap pdata lightPoints nWalls nSils nCaps (snd $ snd $ _fboBase pdata)
colorMask $= Color4 Enabled Enabled Enabled Enabled
clearColor $= Color4 0 0 0 0
--apply lightmap to base buffer
bindFramebuffer Framebuffer $= fst (_fboBase pdata)
textureBinding Texture2D $= Just (snd $ _fboLighting pdata)
blend $= Enabled
blendFunc $= (Zero, OneMinusSrcColor)
drawShader (_fullscreenShader pdata) 4
blendFunc $= (SrcAlpha, OneMinusSrcAlpha)
--draw clouds
bindFramebuffer Framebuffer $= fst (_fboCloud pdata)
depthFunc $= Just Lequal
depthMask $= Disabled
clearColor $= Color4 0.5 0.5 0.5 0
--blendFunc $= (SrcAlphaSaturate,One)
blendFuncSeparate $= ((SrcAlpha,OneMinusSrcAlpha),(One,OneMinusSrcAlpha))
drawBuffers $= [FBOColorAttachment 0,NoBuffers]
clear [ColorBuffer]
renderLayer 2 shadV layerCounts
renderWindows pdata windowPoints
----render transparency depths
depthMask $= Enabled
blend $= Disabled
drawBuffers $= [NoBuffers,FBOColorAttachment 1]
renderLayer 2 shadV layerCounts
renderWindows pdata windowPoints
depthMask $= Disabled
blend $= Enabled
----draw lightmap for cloud buffer
bindFramebuffer Framebuffer $= fst (_fboLighting pdata)
createLightMap pdata lightPoints nWalls nSils nCaps (snd $ snd $ _fboCloud pdata)
colorMask $= Color4 Enabled Enabled Enabled Enabled
clearColor $= Color4 0 0 0 0
--apply lightmap to cloud buffer
clearColor $= Color4 0 0 0 0
bindFramebuffer Framebuffer $= fst (_fboCloud pdata)
depthMask $= Disabled
drawBuffers $= [FBOColorAttachment 0,NoBuffers]
depthFunc $= Just Always
textureBinding Texture2D $= Just (snd $ _fboLighting pdata)
blend $= Enabled
--blendFunc $= (Zero, OneMinusSrcAlpha)
blendFuncSeparate $= ((Zero, OneMinusSrcColor),(Zero, One))
drawShader (_fullscreenShader pdata) 4
blendFunc $= (SrcAlpha, OneMinusSrcAlpha)
depthMask $= Disabled
depthFunc $= Just Always
--Draw blurred bloom onto base buffer
bindFramebuffer Framebuffer $= fst (_fboBase pdata)
blend $= Enabled
blendFunc $= (SrcAlpha, One)
textureBinding Texture2D $= Just (snd $ _fboFourth1 pdata)
drawShader (_fullscreenShader pdata) 4
blendFunc $= (SrcAlpha, OneMinusSrcAlpha)
textureBinding Texture2D $= Just (fst $ snd $ _fboCloud pdata)
drawShader (_fullscreenShader pdata) 4
depthFunc $= Just Lequal
viewport $= (Position 0 0, Size (round $ fstV2 wins) (round $ sndV2 wins))
depthFunc $= Just Always
blendFunc $= (One,Zero)
-- perform any radial distortion
case _radDistortion w of
[] -> do
bindTO $ fst $ snd $ _fboBase pdata
bindFramebuffer Framebuffer $= defaultFramebufferObject
--bufferUBO $ perspectiveMatrixb rot camzoom trans wins viewFroms
drawShader (_fullscreenShader pdata) 4
rds -> do
let bindDrawDist :: (Point2,Point2,Point2,Float) -> IO ()
bindDrawDist ( V2 a b , V2 c d , V2 e f , g) = do
pokeArray (shadVBOptr $ _barrelShader pdata)
[a,b,c,d,e,f,g]
bindShaderBuffers [_barrelShader pdata] [1]
drawShader (_barrelShader pdata) 1
fboList = take (length rds - 1) (concat (repeat [fst $ _fbo2 pdata,fst $ _fbo3 pdata]))
++ [defaultFramebufferObject]
toList = fst (snd (_fboBase pdata)) : concat (repeat [snd $ _fbo2 pdata,snd $ _fbo3 pdata])
bindings = zipWith (>>) (map bindFBO fboList) (map bindTO toList)
activeTexture $= TextureUnit 1
zipWithM_ (>>) bindings $ map bindDrawDist rds
activeTexture $= TextureUnit 0
-- draw overlay
bufferUBO $ isoMatrix 0 1 (V2 0 0) (V2 2 2)
depthFunc $= Just Always
depthMask $= Disabled
blend $= Enabled
blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
renderFoldable shadV $ fixedCoordPictures w
depthMask $= Enabled
eTicks <- SDL.ticks
return (eTicks - sTicks)
--------------------------------------------------------------------------------
-- note: currently assume there is only one UBO, we only bind it once at setup
bufferUBO :: [Float] -> IO ()
bufferUBO mat = withArray mat $ \ptr ->
bufferSubData UniformBuffer WriteToBuffer 0 64 ptr
renderBlankWalls
:: RenderData
-> Int -- ^ number of walls
-> IO ()
renderBlankWalls pdata nWalls = do
cullFace $= Just Back
drawShader (_wallBlankShader pdata) nWalls
cullFace $= Nothing
renderWindows
:: RenderData
-> [((Point2,Point2),Point4)] -- ^ List: wall positions and color
-> IO ()
renderWindows pdata wps = do
n <- poke224s (shadVBOptr $ _wallBlankShader pdata) wps
bindShaderBuffers [_wallBlankShader pdata] [n]
currentProgram $= Just (_shaderProgram $ _wallBlankShader pdata)
cullFace $= Just Back
drawShader (_wallBlankShader pdata) n
cullFace $= Nothing
renderTextureWalls
:: RenderData
-> Int -- ^ number of walls
-> IO ()
renderTextureWalls pdata nWalls = do
cullFace $= Just Back
drawShader (_wallTextureShader pdata) nWalls
cullFace $= Nothing