From 9947979b52d1289f3ac88bdb253b93f683a9b4ba Mon Sep 17 00:00:00 2001 From: justin Date: Sun, 12 Mar 2023 14:06:11 +0000 Subject: [PATCH] Try to improve instancing shadows --- shader/shadow/cap.geom | 2 +- shader/shadow/edge.geom | 141 +++++++------- shader/shadow/wallShadow.geom | 101 +++++----- src/Data/Preload/Render.hs | 2 +- src/Dodge/Data/Config.hs | 2 + src/Dodge/Render.hs | 67 +++---- src/Framebuffer/Update.hs | 3 +- src/Preload/Render.hs | 10 +- src/Render.hs | 336 ++++++++++++++++++++-------------- 9 files changed, 368 insertions(+), 296 deletions(-) diff --git a/shader/shadow/cap.geom b/shader/shadow/cap.geom index 103149ea1..971c706a8 100644 --- a/shader/shadow/cap.geom +++ b/shader/shadow/cap.geom @@ -10,7 +10,7 @@ layout (std140, binding = 1) uniform LightsBlock } ; vec3 lightPos = posBool[gl_InvocationID].xyz ; float theBool = posBool[gl_InvocationID].w; -// this code is duplicated in lineShadow.geom, should not be changed on its own +// this code is duplicated in shadow/edge.geom, should not be changed on its own vec4 projNear (vec4 pos) { // note we project to a specific height diff --git a/shader/shadow/edge.geom b/shader/shadow/edge.geom index 669392067..df22326e8 100644 --- a/shader/shadow/edge.geom +++ b/shader/shadow/edge.geom @@ -1,78 +1,85 @@ #version 450 core -layout (lines_adjacency) in; -layout (invocations = 20) in; -layout (triangle_strip, max_vertices = 4) out; -layout (std140, binding = 0) uniform TheMat { mat4 theMat; } ; -layout (std140, binding = 1) uniform LightsBlock -{ - vec4 posBool[20]; - vec4 colRad[20]; -} ; -vec3 lightPos1 = posBool[gl_InvocationID].xyz; +layout(lines_adjacency) in; +layout(invocations = 20) in; +layout(triangle_strip, max_vertices = 4) out; +layout(std140, binding = 0) uniform TheMat { mat4 theMat; }; +layout(std140, binding = 1) uniform LightsBlock { + vec4 posBool[20]; + vec4 colRad[20]; +}; +vec3 lightPos = posBool[gl_InvocationID].xyz; float theBool = posBool[gl_InvocationID].w; -vec4 shift (vec4 p) { return (vec4 (p.xyz + (100000*(p.xyz-lightPos1)), 1));} ; -vec4 shiftBy (float x,vec4 p) { return (vec4 (lightPos1 + (x*normalize(p.xyz-lightPos1)), 1));} ; -// copied from lighting/cap.geom, should not be changed on its own -vec4 projNear (vec4 pos) -{ - // note we project to a specific height - // this is quite brittle, not ideal - vec3 dir = pos.xyz - lightPos1 ; - float a = (140 - pos.z) / dir.z ; - vec2 xy = (pos.xyz + a * dir).xy ; - return vec4 ( xy, 140 , 1) ; -} ; -vec4 shiftNear (vec4 pos) -{ vec4 sp = shift(pos); - if (sp.z > 140) - { return projNear(pos) ; } - else - { return sp ; } -} ; -vec4 f (vec4 p) {return (theMat * p);} ; -void main() -{ - if (theBool == 1){ -// float ru2 = radiusUniform * radiusUniform ; - float ru = colRad[gl_InvocationID].w ; - float ru2 = ru * ru; +float rad = colRad[gl_InvocationID].w; +vec4 shift(vec4 p) { return (vec4(p.xyz + (100000 * (p.xyz - lightPos)), 1)); }; +vec4 shiftBy(float x, vec4 p) { + return (vec4(lightPos + (x * normalize(p.xyz - lightPos)), 1)); +}; +vec4 shift1(vec4 p) { + return (vec4(lightPos + (rad * normalize(p.xyz - lightPos)), 1)); +}; +// copied from shadow/cap.geom, should not be changed on its own +vec4 projNear(vec4 pos) { + // note we project to a specific height + // this is quite brittle, not ideal + vec3 dir = pos.xyz - lightPos; + float a = (140 - pos.z) / dir.z; + vec2 xy = (pos.xyz + a * dir).xy; + return vec4(xy, 140, 1); +}; +vec4 shiftNear(vec4 pos) { + vec4 sp = shift(pos); + if (sp.z > 140) { + return projNear(pos); + } else { + return sp; + } +}; +void main() { + if (theBool == 1) { vec4 p0 = gl_in[0].gl_Position; vec4 p1 = gl_in[1].gl_Position; - vec4 mid = 0.5*(p0 + p1); + vec4 mid = 0.5 * (p0 + p1); vec3 n0a = gl_in[2].gl_Position.xyz; vec3 n1a = gl_in[3].gl_Position.xyz; - vec3 n0 = cross(p1.xyz - p0.xyz, n0a - p0.xyz) ; - vec3 n1 = cross(p0.xyz - p1.xyz, n1a - p1.xyz) ; - - //vec3 n2 = n0 + n1; // assumes the summands are normalized - vec3 lightDir = p0.xyz - lightPos1.xyz; - vec3 lightDir2 = p1.xyz - lightPos1.xyz; - // first test if the edge is part of the silhouette + vec3 n0 = cross(p1.xyz - p0.xyz, n0a - p0.xyz); + vec3 n1 = cross(p0.xyz - p1.xyz, n1a - p1.xyz); + vec3 lightDir = p0.xyz - lightPos.xyz; + vec3 lightDir2 = p1.xyz - lightPos.xyz; + // test if the edge is part of the silhouette // that is, if the normals of the faces connected by the edge point are in // "different directions" wrt the light direction - if ( dot(n0 , lightDir) * dot(n1 , lightDir) <= 0 && - (dot(lightDir,lightDir) < ru2 || dot(lightDir2,lightDir2) < ru2) ) - // using <= rather than < seems to get rid of overlapping shadow - // artefacts + if (dot(n0, lightDir) * dot(n1, lightDir) <= 0 && + (dot(lightDir, lightDir) < rad * rad || + dot(lightDir2, lightDir2) < rad * rad)) + // using <= rather than < seems to get rid of overlapping shadow + // artefacts { - vec4 p2 = shiftNear(p0); - vec4 p3 = shiftNear(p1); - if ( dot(n0 , lightDir) > 0) - { - gl_Position = f(p0); gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = f(p1); gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = f(p2); gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = f(p3); gl_Layer = gl_InvocationID; EmitVertex(); - } - else - { - gl_Position = f(p1); gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = f(p0); gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = f(p3); gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = f(p2); gl_Layer = gl_InvocationID; EmitVertex(); - } - EndPrimitive(); + vec4 p2 = shiftNear(p0); + vec4 p3 = shiftNear(p1); + gl_Position = theMat * p0; + gl_Layer = gl_InvocationID; + EmitVertex(); + if (dot(n0, lightDir) > 0) { + gl_Position = theMat * p1; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = theMat * p2; + gl_Layer = gl_InvocationID; + EmitVertex(); + } else { + gl_Position = theMat * p2; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = theMat * p1; + gl_Layer = gl_InvocationID; + EmitVertex(); + } + gl_Position = theMat * p3; + gl_Layer = gl_InvocationID; + EmitVertex(); + EndPrimitive(); + } else { } - else { } - }else {} + } else { + } } diff --git a/shader/shadow/wallShadow.geom b/shader/shadow/wallShadow.geom index fb7d19fe9..bf688fb0f 100644 --- a/shader/shadow/wallShadow.geom +++ b/shader/shadow/wallShadow.geom @@ -1,54 +1,65 @@ #version 450 core -layout (points) in; -layout (invocations = 20) in; -layout (triangle_strip, max_vertices = 8) out; -layout (std140, binding = 0) uniform TheMat { mat4 theMat; } ; -layout (std140, binding = 1) uniform LightsBlock -{ - vec4 posBool[20]; - vec4 colRad[20]; -} ; +layout(points) in; +layout(invocations = 20) in; +layout(triangle_strip, max_vertices = 8) out; +layout(std140, binding = 0) uniform TheMat { mat4 theMat; }; +layout(std140, binding = 1) uniform LightsBlock { + vec4 posBool[20]; + vec4 colRad[20]; +}; vec3 lightPos = posBool[gl_InvocationID].xyz; float theBool = posBool[gl_InvocationID].w; -vec4 shift (vec4 p) -{ return vec4 (p.xy + (200 * (p.xy-lightPos.xy)), 0 , 1); -} -float isLHS (vec2 startV, vec2 testV) -{ - return sign( -startV.x * testV.y + startV.y * testV.x); +vec4 shift(vec4 p) { return vec4(p.xy + (200 * (p.xy - lightPos.xy)), 0, 1); } +float isLHS(vec2 startV, vec2 testV) { + return sign(-startV.x * testV.y + startV.y * testV.x); } // construct a box with openings on bottom face and face away from wall -void main() -{ -vec4 p1 = vec4 (gl_in[0].gl_Position.xy,0,1); -vec4 p2 = vec4 (gl_in[0].gl_Position.zw,0,1); -if (theBool==1 && isLHS (p1.xy - lightPos.xy, p2.xy - lightPos.xy) < 0) -{ -vec4 p3 = vec4 (p1.xy,100,1); -vec4 p4 = vec4 (p2.xy,100,1); -vec4 p5 = shift(p1); -vec4 p6 = shift(p2); -vec4 p7 = vec4 (p6.xy,100,1); -vec4 p8 = vec4 (p5.xy,100,1); +void main() { + vec4 p1 = vec4(gl_in[0].gl_Position.xy, 0, 1); + vec4 p2 = vec4(gl_in[0].gl_Position.zw, 0, 1); + if (theBool == 1 && isLHS(p1.xy - lightPos.xy, p2.xy - lightPos.xy) < 0) { + vec4 p3 = vec4(p1.xy, 100, 1); + vec4 p4 = vec4(p2.xy, 100, 1); + vec4 p5 = shift(p1); + vec4 p6 = shift(p2); + vec4 p7 = vec4(p6.xy, 100, 1); + vec4 p8 = vec4(p5.xy, 100, 1); -vec4 a1 = theMat * p1; -vec4 a2 = theMat * p2; -vec4 a3 = theMat * p3; -vec4 a4 = theMat * p4; -vec4 a5 = theMat * p5; -vec4 a6 = theMat * p6; -vec4 a7 = theMat * p7; -vec4 a8 = theMat * p8; + vec4 a1 = theMat * p1; + vec4 a2 = theMat * p2; + vec4 a3 = theMat * p3; + vec4 a4 = theMat * p4; + vec4 a5 = theMat * p5; + vec4 a6 = theMat * p6; + vec4 a7 = theMat * p7; + vec4 a8 = theMat * p8; - gl_Position = a1; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a5; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a3; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a8; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a4; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a7; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a2; gl_Layer = gl_InvocationID; EmitVertex(); - gl_Position = a6; gl_Layer = gl_InvocationID; EmitVertex(); + gl_Position = a1; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a5; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a3; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a8; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a4; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a7; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a2; + gl_Layer = gl_InvocationID; + EmitVertex(); + gl_Position = a6; + gl_Layer = gl_InvocationID; + EmitVertex(); - EndPrimitive(); -} else {} + EndPrimitive(); + } else { + } } diff --git a/src/Data/Preload/Render.hs b/src/Data/Preload/Render.hs index 8dcf1e6ba..c3d7fd549 100644 --- a/src/Data/Preload/Render.hs +++ b/src/Data/Preload/Render.hs @@ -50,7 +50,7 @@ data RenderData = RenderData , _fboColor :: (FBO, TO) , _fboPos :: (FBO, TO) , _fboLighting :: (FBO, TO) - , _fboLightingHigh :: (FBO, TO) + --, _fboLightingHigh :: (FBO, TO) , _fboShadow :: (FBO, (TO, TO)) , _rboBaseBloom :: GLuint -- RenderbufferObject id , _matUBO :: GLuint -- BufferObject id diff --git a/src/Dodge/Data/Config.hs b/src/Dodge/Data/Config.hs index 49f1893e7..c44c638ef 100644 --- a/src/Dodge/Data/Config.hs +++ b/src/Dodge/Data/Config.hs @@ -89,6 +89,8 @@ data ObjectShadows = GeoObjShads | InstancingShads | CPUObjShads | NoObjShads + | NoShadows + | NoLighting deriving (Show, Eq, Ord, Enum, Bounded) data RoomClipping = NoRoomClipBoundaries | AllRoomClipBoundaries | IntersectingRoomClipBoundaries diff --git a/src/Dodge/Render.hs b/src/Dodge/Render.hs index c9a7e7dd6..9829caa0e 100644 --- a/src/Dodge/Render.hs +++ b/src/Dodge/Render.hs @@ -3,26 +3,27 @@ module Dodge.Render ( doDrawing, ) where -import qualified Data.Map.Strict as M -import Picture.Base -import qualified SDL -import qualified Data.Vector as V -import Dodge.Render.Shadow +--import qualified Data.Vector as V + import Control.Lens import Control.Monad import qualified Control.Monad.Parallel as MP +import qualified Data.Map.Strict as M import Data.Preload.Render import qualified Data.Vector.Unboxed.Mutable as UMV import Dodge.Data.Universe import Dodge.Render.Lights import Dodge.Render.Picture +import Dodge.Render.Shadow import Dodge.Render.ShapePicture import Dodge.Render.Walls import Foreign import Geometry import Graphics.GL.Core45 import MatrixHelper +import Picture.Base import Render +import qualified SDL --import qualified SDL import Shader import Shader.Bind @@ -55,13 +56,11 @@ doDrawing' win pdata u = do lightPoints = lightsToRender cfig (w ^. cWorld . camPos) (w ^. cWorld . lWorld) viewFroms@(V2 vfx vfy) = w ^. cWorld . camPos . camViewFrom shadV = _pictureShaders pdata - lwShad = _lightingWallShadShader pdata -- bind as much data into vbos as feasible at this point -- count mutable vectors setup layerCounts <- UMV.replicate (numLayers * 6) 0 -- attempt to poke in parallel let (ws, wp) = wallSPics <> worldSPic cfig w - --( (nWalls, nWins , nFls),(nShapeVs, nIndices, nSilIndices) ) ((nWalls, nWins, nFls), (nShapeVs, nIndices, nSilIndices)) <- MP.bindM3 (\_ a b -> return (a, b)) @@ -109,21 +108,18 @@ doDrawing' win pdata u = do withArray (perspectiveMatrixb rot camzoom trans wins viewFroms) $ \ptr -> glNamedBufferSubData (pdata ^. matUBO) 0 64 ptr setViewportSize (round winx `div` resFact) (round winy `div` resFact) - --bindFramebuffer Framebuffer $= fst (_fboBase pdata) glBindFramebuffer GL_FRAMEBUFFER (_unFBO (fst (_fboBase pdata))) + glDepthMask GL_TRUE glClearColor 0 0 0 1 glClear $ sum [GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT] glDepthFunc GL_LESS -- draw wall occlusions from the camera's point of view --- currentProgram $= lwShad ^? shadProg -- Just (_shadProg lwShad) --- uniform (_shadUnis lwShad V.! 0) $= viewFrom3d - glUseProgram (lwShad ^. shadProg') - glUniform3f (_shadUnis' lwShad V.! 0) vfx vfy 20 - --bindVertexArrayObject $= lwShad ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO lwShad) - glBindVertexArray $ lwShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO lwShad) + glUseProgram (pdata ^. lightingWallShadShader . shadProg') + glUniform3f (pdata ^?! lightingWallShadShader . shadUnis' . ix 0) vfx vfy 20 + glBindVertexArray $ pdata ^. lightingWallShadShader . shadVAO' . vaoName unless (debugOn Remove_LOS cfig) $ glDrawArrays - (marshalEPrimitiveMode $ _shadPrim' lwShad) + (marshalEPrimitiveMode $ pdata ^. lightingWallShadShader . shadPrim') 0 (fromIntegral nWalls) --draw walls onto base buffer @@ -134,20 +130,16 @@ doDrawing' win pdata u = do renderLayer BottomLayer shadV layerCounts --draw object shapes onto base buffer let fs = _shapeShader pdata - --currentProgram $= Just (_shadProg fs) glUseProgram (_shadProg' fs) - --bindVertexArrayObject $= fs ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO fs) - glBindVertexArray $ fs ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO fs) + glBindVertexArray $ fs ^. shadVAO' . vaoName glDrawElements (marshalEPrimitiveMode $ _shadPrim' fs) (fromIntegral nIndices) GL_UNSIGNED_SHORT nullPtr --draw floor onto base buffer - -- nTextArrayVs <- pokePoint33s (shadVBOptr $ _textureArrayShader pdata) (_floorTiles w) drawShader (_textureArrayShader pdata) nFls --draw lightmap into its own buffer - --bindFramebuffer Framebuffer $= fst (_fboLighting pdata) glBindFramebuffer GL_FRAMEBUFFER (_unFBO (fst (_fboLighting pdata))) createLightMap cfig @@ -156,23 +148,18 @@ doDrawing' win pdata u = do nWalls nSilIndices nIndices - --(_graphics_object_shadows $ _uvConfig u) (u ^. uvConfig . graphics_object_shadows) (snd $ snd $ pdata ^. fboBase) (drawCPUShadows pdata ws) - glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE + glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE glClearColor 0 0 0 0 --apply lightmap to base buffer - --bindFramebuffer Framebuffer $= pdata ^. fboBase . _1 --fst (_fboBase pdata) glBindFramebuffer GL_FRAMEBUFFER (pdata ^. fboBase . _1 . unFBO) - --textureBinding Texture2D $= Just (snd $ _fboLighting pdata) - --textureBinding Texture2D $= pdata ^? fboLighting . _2 -- Just (snd $ _fboLighting pdata) - glBindTexture GL_TEXTURE_2D (pdata ^. fboLighting . _2 . unTO) -- Just (snd $ _fboLighting pdata) + glBindTexture GL_TEXTURE_2D (pdata ^. fboLighting . _2 . unTO) glEnable GL_BLEND glBlendFunc GL_ZERO GL_ONE_MINUS_SRC_COLOR drawShader (_fullscreenShader pdata) 4 --draw bloom onto bloom buffer - --bindFramebuffer Framebuffer $= pdata ^. fboBloom . _1 --fst (_fboBloom pdata) glBindFramebuffer GL_FRAMEBUFFER (pdata ^. fboBloom . _1 . unFBO) glClear GL_COLOR_BUFFER_BIT glDepthFunc GL_LESS @@ -233,7 +220,7 @@ doDrawing' win pdata u = do (_graphics_object_shadows $ _uvConfig u) (snd $ snd $ _fboCloud pdata) (drawCPUShadows pdata ws) - glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE + glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE glClearColor 0 0 0 0 --apply lightmap to cloud buffer glClearColor 0 0 0 0 @@ -307,14 +294,15 @@ doDrawing' win pdata u = do renderFoldable shadV $ fixedCoordPictures u glDepthMask GL_TRUE when (debugOn Show_ms_frame $ _uvConfig u) $ - renderFoldable - (_pictureShaders pdata) - ( setDepth (-1) - . translate (-0.5) (-0.8) - . scale 0.0005 0.0005 - $ fpsText (u ^. uvFrameTicks - u ^. uvLastFrameTicks) - ) + renderFoldable + (_pictureShaders pdata) + ( setDepth (-1) + . translate (-0.5) (-0.8) + . scale 0.0005 0.0005 + $ fpsText (u ^. uvFrameTicks - u ^. uvLastFrameTicks) + ) SDL.glSwapWindow win + -- eTicks <- SDL.ticks -- return (eTicks - sTicks) @@ -328,7 +316,6 @@ fpsText x = color col $ text $ "ms/frame " ++ show x | x < 50 = orange | otherwise = red - -------------------------------------------------------------------------------- -- note: currently assume there is only one UBO, we only bind it once at setup --bufferUBO :: GLuint -> [Float] -> IO () @@ -350,7 +337,8 @@ renderBlankWalls pdata nWalls = do --cullFace $= Just Back drawShader (_wallBlankShader pdata) nWalls glDisable GL_CULL_FACE - --cullFace $= Nothing + +--cullFace $= Nothing renderTextureWalls :: RenderData -> @@ -363,11 +351,12 @@ renderTextureWalls pdata nWalls = do glCullFace GL_BACK drawShader (_wallTextureShader pdata) nWalls glDisable GL_CULL_FACE - --cullFace $= Nothing + +--cullFace $= Nothing checkGLError :: IO () checkGLError = do - err <- glGetError + err <- glGetError case err of 0 -> return () i -> error $ "OpenGL error: " ++ show i diff --git a/src/Framebuffer/Update.hs b/src/Framebuffer/Update.hs index 6b34dc815..e460e2242 100644 --- a/src/Framebuffer/Update.hs +++ b/src/Framebuffer/Update.hs @@ -33,7 +33,8 @@ sizeFBOs xsize ysize xfull yfull rdata = do foldM (updateFBOTO2 xsize ysize GL_NEAREST GL_NEAREST GL_RGBA8 GL_RGBA16F) rdata [fboBase, fboCloud] >>= flip (foldM (updateFBOTO xsize ysize GL_NEAREST GL_NEAREST GL_RGBA8)) - [fboColor, fboLighting, fboLightingHigh] + [fboColor, fboLighting] + --[fboColor, fboLighting, fboLightingHigh] rdata'' <- foldM (updateFBOTO xsize ysize GL_LINEAR_MIPMAP_LINEAR GL_LINEAR GL_RGBA16F) diff --git a/src/Preload/Render.hs b/src/Preload/Render.hs index 9c2a59697..7d8a9afce 100644 --- a/src/Preload/Render.hs +++ b/src/Preload/Render.hs @@ -213,7 +213,7 @@ preloadRender = do fboColorName <- setupFramebufferGivenStencil rboBaseBloomName fboPosName <- setupFramebufferGivenStencil rboBaseBloomName fboLightingName <- setupFramebufferGivenStencil rboBaseBloomName - fboLightingHighName <- setupFramebufferGivenStencil rboBaseBloomName + --fboLightingHighName <- setupFramebufferGivenStencil rboBaseBloomName fboShadowName <- setupShadowFramebuffer @@ -238,7 +238,7 @@ preloadRender = do , aslist , eslist ] - + initializeGLState return $ RenderData { _pictureShaders = shadV @@ -270,7 +270,7 @@ preloadRender = do , _fboHalf2 = fboHalf2Name , _fboHalf3 = fboHalf3Name , _fboLighting = fboLightingName - , _fboLightingHigh = fboLightingHighName + --, _fboLightingHigh = fboLightingHighName , _fboShadow = fboShadowName , _fboBase = fboBaseName , _fboCloud = fboCloudName @@ -301,6 +301,10 @@ cornerList = -- , [1, -1, 1, 0] -- ] +initializeGLState :: IO () +initializeGLState = do + glEnable GL_DEPTH_TEST + cleanUpRenderPreload :: RenderData -> IO () cleanUpRenderPreload pd = do -- TODO fix this diff --git a/src/Render.hs b/src/Render.hs index 201c42d30..0f70ef9c1 100644 --- a/src/Render.hs +++ b/src/Render.hs @@ -7,9 +7,8 @@ module Render ( bindFBO, ) where -import Control.Monad -import Dodge.WindowSize import Control.Lens +import Control.Monad import Control.Monad.Primitive import Data.Preload.Render import qualified Data.Vector as V @@ -18,6 +17,7 @@ import qualified Data.Vector.Fusion.Stream.Monadic as VFSM import qualified Data.Vector.Mutable as MV import qualified Data.Vector.Unboxed.Mutable as UMV import Dodge.Data.Config +import Dodge.WindowSize import Foreign hiding (rotate) import Geometry.Data import Graphics.GL.Core45 @@ -26,13 +26,15 @@ import Shader import Shader.Data import Shader.ExtraPrimitive --- | Determine where light is shining in the world. --- think of the produced texture as showing what RGB values should be "taken --- away" from the shape colors. +{- | Determine where light is shining in the world. + think of the produced texture as showing what RGB values should be "taken + away" from the shape colors. +-} createLightMap :: Configuration -> RenderData -> [(Point3, Float, Point3)] -> -- Lights + -- | number of walls Int -> -- | number of silhoutte lines to draw @@ -46,107 +48,159 @@ createLightMap :: (Point3 -> Float -> IO ()) -> -- attempt at drawing shadow not using geo shader IO () createLightMap cfig pdata lightPoints nWalls nSils nCaps shadsdrawtype toPos drawCPUShadows = case shadsdrawtype of - InstancingShads -> instanceLightMap cfig pdata lightPoints nWalls nSils nCaps toPos - _ -> do - let llinesShad = _lightingLineShadowShader pdata - lcapShad = _lightingCapShader pdata - lwallShad = _lightingWallShadShader pdata - ltextShad = _lightingTextureShader pdata - -- we assume that the renderbuffer's depth has been correctly set elsewhere - -- we will not be changing that here - glDepthMask GL_FALSE - -- clearColor is specified differently in preloadRender - -- the colors are inverted - glClearColor 1 1 1 1 - glClear GL_COLOR_BUFFER_BIT - -- for each of the lights: - -- 1. stencil out the shadows from this light's point of view - -- 2. calculate lighting based on each fragment's position - -- to consider: adding normals/a "material" for each fragment - glBlendFunc GL_ZERO GL_ONE_MINUS_SRC_COLOR - glEnable GL_STENCIL_TEST - --stencilTest $= Enabled - glStencilOpSeparate GL_FRONT GL_KEEP GL_KEEP GL_INCR_WRAP - --stencilOpSeparate Front $= (OpKeep, OpKeep, OpIncrWrap) - --stencilOpSeparate Back $= (OpKeep, OpKeep, OpDecrWrap) - glStencilOpSeparate GL_BACK GL_KEEP GL_KEEP GL_DECR_WRAP - flip VFSM.mapM_ (VFSM.fromList lightPoints) $ \(V3 x y z, rad, V3 r g b) -> do - glDepthFunc GL_LESS - -- setup stencil - glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE - glClear GL_STENCIL_BUFFER_BIT + InstancingShads -> instanceLightMap cfig pdata lightPoints nWalls nSils nCaps toPos + NoShadows -> do + let ltextShad = _lightingTextureShader pdata + -- we assume that the renderbuffer's depth has been correctly set elsewhere + -- we will not be changing that here + glDepthMask GL_FALSE + -- clearColor is specified differently in preloadRender + -- the colors are inverted + glClearColor 1 1 1 1 + glClear GL_COLOR_BUFFER_BIT + -- for each of the lights: + -- 1. stencil out the shadows from this light's point of view + -- 2. calculate lighting based on each fragment's position + -- to consider: adding normals/a "material" for each fragment + glBlendFunc GL_ZERO GL_ONE_MINUS_SRC_COLOR + glEnable GL_STENCIL_TEST + --stencilTest $= Enabled + glStencilOpSeparate GL_FRONT GL_KEEP GL_KEEP GL_INCR_WRAP + --stencilOpSeparate Front $= (OpKeep, OpKeep, OpIncrWrap) + --stencilOpSeparate Back $= (OpKeep, OpKeep, OpDecrWrap) + glStencilOpSeparate GL_BACK GL_KEEP GL_KEEP GL_DECR_WRAP + flip VFSM.mapM_ (VFSM.fromList lightPoints) $ \(V3 x y z, rad, V3 r g b) -> do + glDepthFunc GL_LESS + -- setup stencil + glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE + glClear GL_STENCIL_BUFFER_BIT + glDisable GL_CULL_FACE + --cullFace $= Nothing + glStencilFunc GL_ALWAYS 0 255 + --draw lightmap itself + glDepthFunc GL_ALWAYS + -- bind world position texture + bindTO toPos + glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE + glStencilFunc GL_EQUAL 0 255 + glUseProgram (ltextShad ^. shadProg') --Just (_shadProg ltextShad) + glUniform3f (_shadUnis' ltextShad V.! 0) x y z + glUniform4f (_shadUnis' ltextShad V.! 1) r g b rad + --bindVertexArrayObject $= ltextShad ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO ltextShad) + glBindVertexArray $ ltextShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO ltextShad) + glDrawArrays + (marshalEPrimitiveMode (_shadPrim' ltextShad)) + 0 + (fromIntegral (4 :: Int)) + --cleanup: may not be necessary, depending on what comes after... + glDisable GL_CULL_FACE + glDisable GL_STENCIL_TEST + NoLighting -> do + glBindFramebuffer GL_FRAMEBUFFER (_unFBO (fst (_fboLighting pdata))) + glClearColor 0 0 0 1 + -- glClearDepth 0 + glBlendFunc GL_ZERO GL_ONE_MINUS_SRC_COLOR + glClear $ GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT + -- glClearDepth 1 glDisable GL_CULL_FACE - --cullFace $= Nothing - glStencilFunc GL_ALWAYS 0 255 - --draw wall shadows - --currentProgram $= Just (_shadProg lwallShad) - glUseProgram (_shadProg' lwallShad) - --uniform (_shadUnis lwallShad V.! 0) - -- $= Vector3 x y z - glUniform3f (_shadUnis' lwallShad V.! 0) x y z - --bindVertexArrayObject $= lwallShad ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO lwallShad) - glBindVertexArray $ lwallShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO lwallShad) - glDrawArrays - (marshalEPrimitiveMode $ _shadPrim' lwallShad) - 0 - (fromIntegral nWalls) - case shadsdrawtype of - GeoObjShads -> do - --draw silhouette shadows - glUseProgram (_shadProg' llinesShad) - glUniform3f (_shadUnis' llinesShad V.! 0) x y z - glUniform1f (_shadUnis' llinesShad V.! 1) rad - glBindVertexArray (_vaoName $ _shadVAO' llinesShad) - glDrawElements - (marshalEPrimitiveMode $ _shadPrim' llinesShad) - (fromIntegral nSils) - GL_UNSIGNED_SHORT - nullPtr - --draw caps on the near plane as required - glEnable GL_CULL_FACE - glCullFace GL_BACK - glUseProgram (_shadProg' lcapShad) - glUniform3f (_shadUnis' lcapShad V.! 0) x y z - glBindVertexArray $ lcapShad ^. shadVAO' . vaoName --Just (_vao $ _shadVAO lcapShad) - glDrawElements - (marshalEPrimitiveMode $ _shadPrim' lcapShad) - (fromIntegral nCaps) - GL_UNSIGNED_SHORT - nullPtr - CPUObjShads -> drawCPUShadows (V3 x y z) rad - NoObjShads -> return () - --draw lightmap itself - glEnable GL_DEPTH_TEST - glDepthFunc GL_ALWAYS - --depthFunc $= Just Always - -- bind world position texture bindTO toPos - glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE - --stencilOp $= (OpKeep, OpKeep, OpKeep) - glStencilFunc GL_EQUAL 0 255 - --currentProgram $= ltextShad ^? shadProg --Just (_shadProg ltextShad) - --uniform (_shadUnis ltextShad V.! 0) $= Vector3 x y z - --uniform (_shadUnis ltextShad V.! 1) $= Vector4 r g b rad - glUseProgram (ltextShad ^. shadProg') --Just (_shadProg ltextShad) - glUniform3f (_shadUnis' ltextShad V.! 0) x y z - glUniform4f (_shadUnis' ltextShad V.! 1) r g b rad - --bindVertexArrayObject $= ltextShad ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO ltextShad) - glBindVertexArray $ ltextShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO ltextShad) - glDrawArrays - (marshalEPrimitiveMode (_shadPrim' ltextShad)) - 0 - (fromIntegral (4 :: Int)) - --cleanup: may not be necessary, depending on what comes after... - glDisable GL_CULL_FACE - glDisable GL_STENCIL_TEST + glDepthFunc GL_ALWAYS + glDepthMask GL_FALSE + _ -> do + let llinesShad = _lightingLineShadowShader pdata + lcapShad = _lightingCapShader pdata + lwallShad = _lightingWallShadShader pdata + ltextShad = _lightingTextureShader pdata + -- we assume that the renderbuffer's depth has been correctly set elsewhere + -- we will not be changing that here + glDepthMask GL_FALSE + -- clearColor is specified differently in preloadRender + -- the colors are inverted + glClearColor 1 1 1 1 + glClear GL_COLOR_BUFFER_BIT + -- for each of the lights: + -- 1. stencil out the shadows from this light's point of view + -- 2. calculate lighting based on each fragment's position + -- to consider: adding normals/a "material" for each fragment + glBlendFunc GL_ZERO GL_ONE_MINUS_SRC_COLOR + glEnable GL_STENCIL_TEST + --stencilTest $= Enabled + glStencilOpSeparate GL_FRONT GL_KEEP GL_KEEP GL_INCR_WRAP + --stencilOpSeparate Front $= (OpKeep, OpKeep, OpIncrWrap) + --stencilOpSeparate Back $= (OpKeep, OpKeep, OpDecrWrap) + glStencilOpSeparate GL_BACK GL_KEEP GL_KEEP GL_DECR_WRAP + flip VFSM.mapM_ (VFSM.fromList lightPoints) $ \(V3 x y z, rad, V3 r g b) -> do + glDepthFunc GL_LESS + -- setup stencil + glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE + glClear GL_STENCIL_BUFFER_BIT + glDisable GL_CULL_FACE + --cullFace $= Nothing + glStencilFunc GL_ALWAYS 0 255 + --draw wall shadows + --currentProgram $= Just (_shadProg lwallShad) + glUseProgram (_shadProg' lwallShad) + --uniform (_shadUnis lwallShad V.! 0) + -- $= Vector3 x y z + glUniform3f (_shadUnis' lwallShad V.! 0) x y z + --bindVertexArrayObject $= lwallShad ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO lwallShad) + glBindVertexArray $ lwallShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO lwallShad) + glDrawArrays + (marshalEPrimitiveMode $ _shadPrim' lwallShad) + 0 + (fromIntegral nWalls) + case shadsdrawtype of + GeoObjShads -> do + --draw silhouette shadows + glUseProgram (_shadProg' llinesShad) + glUniform3f (_shadUnis' llinesShad V.! 0) x y z + glUniform1f (_shadUnis' llinesShad V.! 1) rad + glBindVertexArray (_vaoName $ _shadVAO' llinesShad) + glDrawElements + (marshalEPrimitiveMode $ _shadPrim' llinesShad) + (fromIntegral nSils) + GL_UNSIGNED_SHORT + nullPtr + --draw caps on the near plane as required + glEnable GL_CULL_FACE + glCullFace GL_BACK + glUseProgram (_shadProg' lcapShad) + glUniform3f (_shadUnis' lcapShad V.! 0) x y z + glBindVertexArray $ lcapShad ^. shadVAO' . vaoName --Just (_vao $ _shadVAO lcapShad) + glDrawElements + (marshalEPrimitiveMode $ _shadPrim' lcapShad) + (fromIntegral nCaps) + GL_UNSIGNED_SHORT + nullPtr + CPUObjShads -> drawCPUShadows (V3 x y z) rad + NoObjShads -> return () + --draw lightmap itself + glDepthFunc GL_ALWAYS + -- bind world position texture + bindTO toPos + glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE + glStencilFunc GL_EQUAL 0 255 + glUseProgram (ltextShad ^. shadProg') --Just (_shadProg ltextShad) + glUniform3f (_shadUnis' ltextShad V.! 0) x y z + glUniform4f (_shadUnis' ltextShad V.! 1) r g b rad + --bindVertexArrayObject $= ltextShad ^? shadVAO' . vaoName -- Just (_vao $ _shadVAO ltextShad) + glBindVertexArray $ ltextShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO ltextShad) + glDrawArrays + (marshalEPrimitiveMode (_shadPrim' ltextShad)) + 0 + (fromIntegral (4 :: Int)) + --cleanup: may not be necessary, depending on what comes after... + glDisable GL_CULL_FACE + glDisable GL_STENCIL_TEST -lightsToArray :: [(Point3,Float,Point3)] -> [Float] -lightsToArray xs = concat (take 20 $ map t xs ++ repeat [0,0,0,0]) - ++ concat (take 20 $ map s xs ++ repeat [0,0,0,0]) +lightsToArray :: [(Point3, Float, Point3)] -> [Float] +lightsToArray xs = + concat (take 20 $ map t xs ++ repeat [0, 0, 0, 0]) + ++ concat (take 20 $ map s xs ++ repeat [0, 0, 0, 0]) where - t (V3 a b c,_,_) = [a,b,c,1] - s (_,d,V3 e f g) = [e,f,g,d] - --t (V3 a b c,d,V3 e f g) = [a,b,c,1] + t (V3 a b c, _, _) = [a, b, c, 1] + s (_, d, V3 e f g) = [e, f, g, d] + instanceLightMap :: Configuration -> @@ -162,52 +216,53 @@ instanceLightMap :: TO -> IO () instanceLightMap cfig pdata lightPoints nWalls nSils nCaps toPos = do - let llinesShad = _shadowEdgeShader pdata - lcapShad = _shadowCapShader pdata - lwallShad = _shadowWallShader pdata - (xsize,ysize) = getWindowSize cfig + let lcapShad = _shadowCapShader pdata + (xsize, ysize) = getWindowSize cfig withArray (lightsToArray lightPoints) $ \ptr -> glNamedBufferSubData (pdata ^. lightsUBO) 0 620 ptr - - forM_ [0..19] $ \i -> glCopyImageSubData - (pdata ^. rboBaseBloom) - GL_RENDERBUFFER - 0 - 0 0 0 - (pdata ^. fboShadow . _2 . _2 . unTO) - GL_TEXTURE_2D_ARRAY 0 0 0 i (fromIntegral xsize) (fromIntegral ysize) - 1 - glBindFramebuffer GL_FRAMEBUFFER (_unFBO (fst (_fboShadow pdata))) + forM_ [0 .. 19] $ \i -> + glCopyImageSubData + (pdata ^. rboBaseBloom) + GL_RENDERBUFFER + 0 + 0 + 0 + 0 + (pdata ^. fboShadow . _2 . _2 . unTO) + GL_TEXTURE_2D_ARRAY + 0 + 0 + 0 + i + (fromIntegral xsize) + (fromIntegral ysize) + 1 + glBindFramebuffer GL_FRAMEBUFFER $ pdata ^. fboShadow . _1 . unFBO glDepthMask GL_FALSE - -- clearColor is specified differently in preloadRender - -- the colors are inverted glClearColor 0 0 0 0 glClear $ GL_COLOR_BUFFER_BIT + GL_STENCIL_BUFFER_BIT - -- for each of the lights: - -- 1. stencil out the shadows from this light's point of view - -- 2. calculate lighting based on each fragment's position - -- to consider: adding normals/a "material" for each fragment + -- stencil out the shadows from each light's point of view + -- setup stencil glEnable GL_STENCIL_TEST glStencilOpSeparate GL_FRONT GL_KEEP GL_KEEP GL_INCR_WRAP glStencilOpSeparate GL_BACK GL_KEEP GL_KEEP GL_DECR_WRAP - -- this was a loop glDepthFunc GL_LESS - -- setup stencil - glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE + glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE + glDisable GL_BLEND glDisable GL_CULL_FACE glStencilFunc GL_ALWAYS 0 255 --draw wall shadows - glUseProgram (_shadProg' lwallShad) - glBindVertexArray $ lwallShad ^. shadVAO' . vaoName -- Just (_vao $ _shadVAO lwallShad) + glUseProgram $ pdata ^. shadowWallShader . shadProg' + glBindVertexArray $ pdata ^. shadowWallShader . shadVAO' . vaoName -- Just (_vao $ _shadVAO lwallShad) glDrawArrays - (marshalEPrimitiveMode $ _shadPrim' lwallShad) + (marshalEPrimitiveMode $ pdata ^. shadowWallShader . shadPrim') 0 (fromIntegral nWalls) --draw silhouette shadows - glUseProgram (_shadProg' llinesShad) - glBindVertexArray (_vaoName $ _shadVAO' llinesShad) + glUseProgram $ pdata ^. shadowEdgeShader . shadProg' + glBindVertexArray $ pdata ^. shadowEdgeShader . shadVAO' . vaoName glDrawElements - (marshalEPrimitiveMode $ _shadPrim' llinesShad) + (marshalEPrimitiveMode $ pdata ^. shadowEdgeShader . shadPrim') (fromIntegral nSils) GL_UNSIGNED_SHORT nullPtr @@ -215,31 +270,27 @@ instanceLightMap cfig pdata lightPoints nWalls nSils nCaps toPos = do glEnable GL_CULL_FACE glCullFace GL_BACK glUseProgram (_shadProg' lcapShad) - glBindVertexArray $ lcapShad ^. shadVAO' . vaoName --Just (_vao $ _shadVAO lcapShad) + glBindVertexArray $ lcapShad ^. shadVAO' . vaoName glDrawElements (marshalEPrimitiveMode $ _shadPrim' lcapShad) (fromIntegral nCaps) GL_UNSIGNED_SHORT nullPtr - --draw lightmap itself - glEnable GL_DEPTH_TEST + --draw lightmap itself glDepthFunc GL_ALWAYS glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE glStencilFunc GL_EQUAL 0 255 glUseProgram (pdata ^. shadowLightShader . shadProg') -- bind world position texture bindTO toPos - glDisable GL_BLEND glBindVertexArray $ pdata ^. shadowLightShader . shadVAO' . vaoName glDrawArrays (marshalEPrimitiveMode $ pdata ^. shadowLightShader . shadPrim') 0 1 - -- this was the end of the loop glDisable GL_CULL_FACE glDisable GL_STENCIL_TEST - --draw to the lighting framebuffer here glBindFramebuffer GL_FRAMEBUFFER (_unFBO (fst (_fboLighting pdata))) glClearColor 1 1 1 1 @@ -252,6 +303,11 @@ instanceLightMap cfig pdata lightPoints nWalls nSils nCaps toPos = do (marshalEPrimitiveMode EPoints) 0 1 + withArray [GL_COLOR_ATTACHMENT0, GL_DEPTH_STENCIL_ATTACHMENT] $ \ptr -> + glInvalidateNamedFramebufferData + (pdata ^. fboShadow . _1 . unFBO) + 2 + ptr -- assumes that vertices have already been sent to the shader pingPongBetween :: @@ -294,8 +350,10 @@ renderLayer layer shads counts = do bindTO :: TO -> IO () bindTO t = glBindTexture GL_TEXTURE_2D (_unTO t) - --textureBinding Texture2D $= Just t + +--textureBinding Texture2D $= Just t bindFBO :: FBO -> IO () -bindFBO fb = --bindFramebuffer Framebuffer $= fb +bindFBO fb = + --bindFramebuffer Framebuffer $= fb glBindFramebuffer GL_FRAMEBUFFER (_unFBO fb)