161 lines
6.0 KiB
Haskell
161 lines
6.0 KiB
Haskell
{- |
|
|
Contains the central drawing functions for the dodge loop. -}
|
|
module Dodge.Render
|
|
( module Dodge.Render.Picture
|
|
, doDrawing
|
|
)
|
|
where
|
|
import Dodge.Data
|
|
import Dodge.Config.Data
|
|
import Dodge.Base
|
|
--import Dodge.Render.HUD
|
|
--import Dodge.Render.MenuScreen
|
|
import Dodge.Render.Picture
|
|
--import Dodge.Render.PerspectiveMatrix
|
|
import Geometry
|
|
--import Picture
|
|
import Picture.Render
|
|
import Picture.Preload
|
|
import Shader
|
|
import MatrixHelper
|
|
|
|
import Foreign (Word32)
|
|
--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
|
|
|
|
{- |
|
|
Central drawing function.
|
|
Returns a 'Word32' that should give the number of ticks it took to evaluate.
|
|
-}
|
|
doDrawing :: RenderData -> World -> IO Word32
|
|
doDrawing pdata w = do
|
|
sTicks <- SDL.ticks
|
|
clear [ColorBuffer,DepthBuffer]
|
|
let rot = _cameraRot w
|
|
camzoom = _cameraZoom w
|
|
trans = _cameraCenter w
|
|
wins = (getWindowX w,getWindowY w)
|
|
wallPointsCol = wallsPointsAndCols w
|
|
windowPoints = wallsWindows w
|
|
lightPoints = lightsForGloom' w
|
|
viewFroms@(viewFromx,viewFromy) = _cameraViewFrom w
|
|
pic = worldPictures w
|
|
wallPoints = map fst wallPointsCol
|
|
-- set the coordinate uniforms ready for drawing elements using world coordinates
|
|
setCommonUniforms pdata rot camzoom trans wins
|
|
depthFunc $= Just Less
|
|
pmat <- (newMatrix RowMajor $ perspectiveMatrix rot camzoom trans wins viewFroms)
|
|
:: IO (GLmatrix GLfloat)
|
|
-- draw the lightmap. Probably changes the bound framebufferObject
|
|
createLightMap pdata (w ^. config . shadow_resolution) wallPoints lightPoints viewFroms pmat
|
|
(foregroundPics w)
|
|
|
|
-- -- set the coordinate uniforms ready for drawing elements using world coordinates
|
|
-- setCommonUniforms pdata rot camzoom trans wins
|
|
|
|
-- draw the background. Assumes that depth testing is not enabled or that
|
|
-- the depth buffer is ready to be drawn on
|
|
blendFuncSeparate $= ((SrcAlphaSaturate, OneMinusSrcAlpha), (Zero,One))
|
|
renderBackground pdata rot camzoom trans wins
|
|
-- draw the walls
|
|
depthFunc $= Just Less
|
|
if w ^. config . wall_textured
|
|
then renderTextureWalls pdata wallPointsCol pmat
|
|
else renderBlankWalls pdata wallPointsCol pmat
|
|
-- I believe a more apt name would be setCeilingDepth: stops drawing of objects
|
|
-- at points that are behind the extension of walls to the screen edge
|
|
_ <- setWallDepth pdata wallPoints (viewFromx,viewFromy) pmat
|
|
-- draw the first layer of pictures
|
|
-- these will probably all be opaque
|
|
_ <- renderFoldable pdata $ picToLTree (Just 0) pic
|
|
-- reset blend so that light map doesn't apply
|
|
-- useful for drawing vivid projectiles
|
|
blendFuncSeparate $= ((SrcAlpha,OneMinusSrcAlpha) , (Zero,One))
|
|
depthFunc $= Just Lequal
|
|
_ <- renderFoldable pdata $ picToLTree (Just 1) pic
|
|
-- reset blend so that light map applies again
|
|
-- allows us to be certain these elements are drawn on top of those before,
|
|
-- in case we want transparency effects
|
|
blendFuncSeparate $= ((SrcAlphaSaturate, OneMinusSrcAlpha), (Zero,One))
|
|
_ <- renderFoldable pdata $ picToLTree (Just 2) pic
|
|
depthMask $= Disabled
|
|
-- render transparent walls
|
|
-- the ordering between these and transparent clouds perhaps presents a challenge
|
|
renderBlankWalls pdata windowPoints pmat
|
|
|
|
depthMask $= Enabled
|
|
forM_ (_pictureShaders pdata) $ setPerpMatUniform rot camzoom trans wins viewFroms
|
|
depthFunc $= Just Lequal
|
|
_ <- renderFoldable pdata $ picToLTree (Just 0) (foregroundPics w)
|
|
|
|
-- draw the fbo to the screen
|
|
-- allows for post-processing
|
|
-- first, bind the screen fbo
|
|
bindFramebuffer Framebuffer $= defaultFramebufferObject
|
|
-- we probably do not want to blend during this step
|
|
blend $= Disabled
|
|
depthFunc $= Just Always
|
|
textureBinding Texture2D $= Just (snd3 $ _fbo2 pdata)
|
|
-- textureFilter Texture2D $= ((Linear',Just Linear') , Linear')
|
|
-- generateMipmap' Texture2D
|
|
if _crHP (you w) > 0
|
|
then do
|
|
bindShaderBuffers [_fullscreenShader pdata] [4]
|
|
drawShader (_fullscreenShader pdata) 4
|
|
else do
|
|
bindShaderBuffers [_grayscaleShader pdata] [4]
|
|
drawShader (_grayscaleShader pdata) 4
|
|
blend $= Enabled
|
|
|
|
-- reset the coordinate uniforms for pictures that are drawn wrt to window
|
|
-- coordinates
|
|
resetShaderUniforms (map extractProgAndUnis $ _pictureShaders pdata)
|
|
blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
|
|
_ <- renderFoldable pdata (picToLTree Nothing $ fixedCoordPictures w)
|
|
eTicks <- SDL.ticks
|
|
return (eTicks - sTicks)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
renderBlankWalls
|
|
:: RenderData
|
|
-> [((Point2,Point2),Point4)] -- ^ List: wall positions and color
|
|
-> GLmatrix GLfloat
|
|
-> IO ()
|
|
renderBlankWalls pdata wps pmat = do
|
|
n <- F.foldM (pokeShader $ _wallBlankShader pdata) wps
|
|
bindShaderBuffers [_wallBlankShader pdata] [n]
|
|
currentProgram $= Just (_shaderProgram $ _wallBlankShader pdata)
|
|
uniform (( _shaderMatrixUniform $ _wallBlankShader pdata) )
|
|
$= pmat
|
|
cullFace $= Just Back
|
|
drawShader (_wallBlankShader pdata) n
|
|
cullFace $= Nothing
|
|
|
|
renderTextureWalls
|
|
:: RenderData
|
|
-> [((Point2,Point2),Point4)] -- ^ List: wall positions and color
|
|
-> GLmatrix GLfloat
|
|
-> IO ()
|
|
renderTextureWalls pdata wps pmat = do
|
|
n <- F.foldM (pokeShader $ _wallTextureShader pdata) wps
|
|
bindShaderBuffers [_wallTextureShader pdata] [n]
|
|
currentProgram $= Just (_shaderProgram $ _wallTextureShader pdata)
|
|
uniform (( _shaderMatrixUniform $ _wallTextureShader pdata) )
|
|
$= pmat
|
|
cullFace $= Just Back
|
|
drawShader (_wallTextureShader pdata) n
|
|
cullFace $= Nothing
|