Files
loop/src/Render.hs
T
2021-08-02 02:14:09 +02:00

224 lines
7.1 KiB
Haskell

{-# LANGUAGE TupleSections #-}
module Render
where
import Shader
import Shader.Data
import Shader.Poke
--import MatrixHelper
import Data.Preload.Render
import Picture.Data
--import Picture.Tree
--import Geometry
import Geometry.Data
--import Polyhedra.Data
--import Polyhedra
import Layers
--import Control.Lens
import Control.Monad
--import qualified Control.Foldl as F
import Foreign hiding (rotate)
import Graphics.Rendering.OpenGL hiding (Line,translate,scale,imageHeight,Polygon,Color,T)
--import Data.Foldable
--import Data.Tuple.Extra
--import qualified Data.IntMap.Strict as IM
import qualified SDL
divideSize :: Int -> Size -> Size
divideSize i (Size x y) = Size (div x $ fromIntegral i) (div y $ fromIntegral i)
sizeToTexSize :: Size -> TextureSize2D
sizeToTexSize (Size x y) = TextureSize2D x y
{- | Determine where light is shining in the world. -}
createLightMap
:: RenderData
-> [(Point3,Float,Float)] -- Lights
-> Int -- ^ number of walls
-> Int -- ^ number of silhoutte lines to draw
-> Int -- ^ number of surface triangles to draw
-> IO ()
createLightMap pdata lightPoints nWalls nSils nsurfVs = do
depthFunc $= Just Less
-- clear buffer to full alpha and furthest depth
-- clearColor is specified in preloadRender
clearColor $= Color4 0 0 0 1
clear [ColorBuffer,DepthBuffer]
--colorMask $= Color4 Disabled Disabled Disabled Disabled
cullFace $= Just Back
-- draw walls from your point of view in order to set z buffer
drawShader (_lightingWallShader pdata) nWalls
---- draw foreground elements to set z buffer
drawShader (_lightingSurfaceShader pdata) nsurfVs
-- for each of the lights:
-- stencil out the walls from this light's point of view
-- draw fading lightmap circles on the floor
-- draw fading lightmaps on the walls
depthMask $= Disabled
blendFunc $= (Zero, OneMinusSrcAlpha)
stencilTest $= Enabled
depthFunc $= Just Lequal
forM_ lightPoints $ \((V3 x y z),r,lum) -> do
-- stencil out shadows
colorMask $= Color4 Disabled Disabled Disabled Disabled
clear [StencilBuffer]
cullFace $= Just Back
stencilOp $= (OpKeep,OpKeep,OpIncr)
stencilFunc $= (Always, 0, 255)
currentProgram $= Just (_shaderProgram $ _lightingOccludeShader pdata)
uniform (head $ _shaderCustomUnis $ _lightingOccludeShader pdata)
$= Vector3 x y z
drawShader (_lightingOccludeShader pdata) nWalls
currentProgram $= Just (_shaderProgram $ _lightingLineShadowShader pdata)
uniform (head $ _shaderCustomUnis $ _lightingLineShadowShader pdata)
$= Vector3 x y z
drawShader (_lightingLineShadowShader pdata) nSils
cullFace $= Just Front
stencilOp $= (OpKeep,OpKeep,OpDecr)
currentProgram $= Just (_shaderProgram $ _lightingOccludeShader pdata)
drawShader (_lightingOccludeShader pdata) nWalls
currentProgram $= Just (_shaderProgram $ _lightingLineShadowShader pdata)
drawShader (_lightingLineShadowShader pdata) nSils
--depthFunc $= Just Lequal
-- draw geometry surfaces
cullFace $= Just Back
colorMask $= Color4 Disabled Disabled Disabled Enabled
stencilFunc $= (Equal, 0, 255)
currentProgram $= Just (_shaderProgram $ _lightingSurfaceShader pdata)
uniform (head $ _shaderCustomUnis $ _lightingSurfaceShader pdata)
$= Vector3 x y z
uniform (_shaderCustomUnis (_lightingSurfaceShader pdata) !! 1)
$= Vector2 r lum
drawShader (_lightingSurfaceShader pdata) nsurfVs
-- draw wall light "circles"
currentProgram $= Just (_shaderProgram $ _lightingWallShader pdata)
uniform (head $ _shaderCustomUnis $ _lightingWallShader pdata)
$= Vector3 x y z
uniform (_shaderCustomUnis (_lightingWallShader pdata) !! 1)
$= Vector2 r lum
drawShader (_lightingWallShader pdata) nWalls
cullFace $= Nothing
stencilTest $= Disabled
--blend $= Disabled
{- |
Blur between two framebuffers.
Assumes no depth testing is done
-}
pingPongBlur :: RenderData -> IO ()
pingPongBlur pdata = do
bindFramebuffer Framebuffer $= fst (_fbo3 pdata)
textureBinding Texture2D $= Just (snd $ _fbo2 pdata)
drawShader (_bloomBlurShader pdata) 4
bindFramebuffer Framebuffer $= fst (_fbo2 pdata)
textureBinding Texture2D $= Just (snd $ _fbo3 pdata)
drawShader (_bloomBlurShader pdata) 4
-- assumes that vertices have already been sent to the shader
pingPongBetween
:: (FramebufferObject,TextureObject)
-> (FramebufferObject,TextureObject)
-> FullShader
-> IO ()
pingPongBetween (fb1,to1) (fb2,to2) fs = do
bindFramebuffer Framebuffer $= fb2
textureBinding Texture2D $= Just to1
drawShader fs 4
bindFramebuffer Framebuffer $= fb1
textureBinding Texture2D $= Just to2
drawShader fs 4
drawTextureOnFramebuffer
:: FullShader
-> FramebufferObject
-> TextureObject
-> IO ()
drawTextureOnFramebuffer fs fbo to = do
bindFramebuffer Framebuffer $= fbo
textureBinding Texture2D $= Just to
drawShader fs 4
pokeBindFoldable
-- :: Foldable f
:: RenderData
-> [Verx]
-> IO (PicShads Int)
pokeBindFoldable pdata m = do
let shads = _pictureShaders pdata
--counts = zeroCounts
--elist <- foldM (pokeVX' shads) counts m
elist <- pokeVerxs (fmap (_vaoVBO . _vshaderVAO) shads) m
bindShader shads elist
return elist
zeroCounts :: PicShads Int
zeroCounts = PicShads 0 0 0 0 0 0
pokeVerxLayers
:: PicShads VBO
-> [Verx]
-> Layers (PicShads Int)
-> IO (Layers (PicShads Int))
pokeVerxLayers = undefined
pokeBindFoldableLayer
:: RenderData
-> Picture
-> IO (Layers (PicShads Int))
pokeBindFoldableLayer pdata m = do
let shads = _pictureShaders pdata
slist'' <- pokeLayVerxsFold (fmap (_vaoVBO . _vshaderVAO) shads) m
bindShaderLay shads slist''
return slist''
renderFoldable
:: RenderData
-> [Verx]
-> IO Word32
renderFoldable pdata struct = do
pokeStartTicks <- SDL.ticks
count <- pokeBindFoldable pdata struct
let shads = _pictureShaders pdata
mapM_ (uncurry (drawShaderLay 0)) ((,) <$> shads <*> count)
pokeEndTicks <- SDL.ticks
return $ pokeEndTicks - pokeStartTicks
------------------------------end renderFoldable
renderLayer :: Int -> PicShads VShader -> Layers (PicShads Int) -> IO ()
renderLayer i shads counts = sequence_ $ drawShaderLay i <$> shads <*> getLay i counts
pokeTwoOff
:: Ptr Float
-> Int
-> (Float,Float)
-> IO ()
{-# INLINE pokeTwoOff #-}
pokeTwoOff ptr n (x,y) = do
pokeElemOff ptr (2*n+0) x
pokeElemOff ptr (2*n+1) y
pokeThreeOff
:: Ptr Float
-> Int
-> (Float,Float,Float)
-> IO ()
{-# INLINE pokeThreeOff #-}
pokeThreeOff ptr n (x,y,z) = do
pokeElemOff ptr (3*n+0) x
pokeElemOff ptr (3*n+1) y
pokeElemOff ptr (3*n+2) z
pokeFourOff :: Ptr Float -> Int -> (Float,Float,Float,Float) -> IO ()
{-# INLINE pokeFourOff #-}
pokeFourOff ptr n (x,y,z,w) = do
pokeElemOff ptr (4*n+0) x
pokeElemOff ptr (4*n+1) y
pokeElemOff ptr (4*n+2) z
pokeElemOff ptr (4*n+3) w