224 lines
7.1 KiB
Haskell
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
|