From e7b4e54f9a9f999507a03496d2ff27ae04cea86e Mon Sep 17 00:00:00 2001 From: jgk Date: Sun, 21 Mar 2021 11:11:44 +0100 Subject: [PATCH] Add lighting on walls, imperfect --- shader/lightmapCircle.geom | 8 ++-- shader/lightmapWall.frag | 13 ++++++ shader/lightmapWall.geom | 86 ++++++++++++++++++++++++++++++++++++++ shader/lightmapWall.vert | 7 ++++ shader/wallShadow.geom | 8 ++-- src/Dodge/Rendering.hs | 12 +----- src/Picture/Preload.hs | 7 ++-- src/Picture/Render.hs | 67 +++++++++-------------------- 8 files changed, 140 insertions(+), 68 deletions(-) create mode 100644 shader/lightmapWall.frag create mode 100644 shader/lightmapWall.geom create mode 100644 shader/lightmapWall.vert diff --git a/shader/lightmapCircle.geom b/shader/lightmapCircle.geom index a8790706a..f1f3d2615 100644 --- a/shader/lightmapCircle.geom +++ b/shader/lightmapCircle.geom @@ -18,16 +18,16 @@ void main() cenPosT = vec2 ( (cenPos.x + 1) * 0.5 * winSize.x , (cenPos.y + 1) * 0.5 * winSize.y); dField = vec2 ( 1, 1); - gl_Position = vec4 (cenPos.x + gRad/winSize.x, cenPos.y + gRad/winSize.y, -0.2 , 1); + gl_Position = vec4 (cenPos.x + gRad/winSize.x, cenPos.y + gRad/winSize.y, -0 , 1); EmitVertex(); dField = vec2 (-1, 1); - gl_Position = vec4 (cenPos.x - gRad/winSize.x, cenPos.y + gRad/winSize.y, -0.2 , 1); + gl_Position = vec4 (cenPos.x - gRad/winSize.x, cenPos.y + gRad/winSize.y, -0 , 1); EmitVertex(); dField = vec2 ( 1,-1); - gl_Position = vec4 (cenPos.x + gRad/winSize.x, cenPos.y - gRad/winSize.y, -0.2 , 1); + gl_Position = vec4 (cenPos.x + gRad/winSize.x, cenPos.y - gRad/winSize.y, -0 , 1); EmitVertex(); dField = vec2 (-1,-1); - gl_Position = vec4 (cenPos.x - gRad/winSize.x, cenPos.y - gRad/winSize.y, -0.2 , 1); + gl_Position = vec4 (cenPos.x - gRad/winSize.x, cenPos.y - gRad/winSize.y, -0 , 1); EmitVertex(); EndPrimitive(); diff --git a/shader/lightmapWall.frag b/shader/lightmapWall.frag new file mode 100644 index 000000000..935723836 --- /dev/null +++ b/shader/lightmapWall.frag @@ -0,0 +1,13 @@ +#version 430 core +in vec2 cenPosT; +in float lum; + +in vec3 dField; + +out vec4 fColor; + +void main() +{ + float c = pow (1 - min(1, dot(dField,dField)) , 2) * lum ; + fColor = vec4(c,c,c,c); +} diff --git a/shader/lightmapWall.geom b/shader/lightmapWall.geom new file mode 100644 index 000000000..07e5a31a0 --- /dev/null +++ b/shader/lightmapWall.geom @@ -0,0 +1,86 @@ +#version 430 core +layout (points) in; +layout (triangle_strip, max_vertices = 4) out; + +out vec3 dField; +out float lum; + +uniform vec2 lightPos; +uniform mat4 perpMat; +uniform vec2 radLum; + +float isLHS (vec2 startV, vec2 testV) +{ + return sign( -startV.x * testV.y + startV.y * testV.x); +} +vec4 shiftUp (vec4 v) +{ return vec4 (v.xy , v.z-0.1 , v.w) ; } + +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 (isLHS (p1.xy - lightPos, p2.xy - lightPos) < 0) +{ + lum = radLum.y; + float rad = radLum.x; + + vec4 p3 = vec4 (p1.xy,-0.2,1); + vec4 p4 = vec4 (p2.xy,-0.2,1); + + vec2 d1 = p1.xy - lightPos; + vec2 d2 = p2.xy - lightPos; + + vec4 a1 = shiftUp( perpMat * p1 ); + vec4 a2 = shiftUp( perpMat * p2 ); + vec4 a3 = shiftUp( perpMat * p3 ); + vec4 a4 = shiftUp( perpMat * p4 ); + + dField = vec3( d1.x/rad, d1.y/rad, 0); + gl_Position = a1; + EmitVertex(); + dField = vec3( d1.x/rad, d1.y/rad, 1); + gl_Position = a3; + EmitVertex(); + dField = vec3( d2.x/rad, d2.y/rad, 0); + gl_Position = a2; + EmitVertex(); + dField = vec3( d2.x/rad, d2.y/rad, 1); + gl_Position = a4; + EmitVertex(); + + EndPrimitive(); +} else {} +} + +// // void main() +// // { +// // vec4 frontL4 = worldMat * vec4(gl_in[0].gl_Position.xy, 0 ,1); +// // vec4 frontR4 = worldMat * vec4(gl_in[0].gl_Position.zw, 0 ,1); +// // vec2 frontL = frontL4.xy; +// // vec2 frontR = frontR4.xy; +// // +// // emitLine (frontR); +// // emitLine (frontL); +// // EndPrimitive(); +// // } +// gl_Position = perspective * worldMat * p4; EmitVertex(); +// gl_Position = perspective * worldMat * p3; EmitVertex(); +// gl_Position = perspective * worldMat * p7; EmitVertex(); +// gl_Position = perspective * worldMat * p8; EmitVertex(); +// gl_Position = perspective * worldMat * p5; EmitVertex(); +// gl_Position = perspective * worldMat * p3; EmitVertex(); +// gl_Position = perspective * worldMat * p1; EmitVertex(); +// gl_Position = perspective * worldMat * p4; EmitVertex(); +// gl_Position = perspective * worldMat * p2; EmitVertex(); +// gl_Position = perspective * worldMat * p7; EmitVertex(); +// gl_Position = perspective * worldMat * p6; EmitVertex(); +// gl_Position = perspective * worldMat * p5; EmitVertex(); +//void emitLine (vec2 pa) +//{ +// gl_Position = vec4 (pa, 0, 1); +// EmitVertex(); +// gl_Position = shift (vec4 (pa,0,1)); //vec4 (pa + (200 * (pa - lightPosa)), 0 , 1); +// EmitVertex(); +//} + diff --git a/shader/lightmapWall.vert b/shader/lightmapWall.vert new file mode 100644 index 000000000..15bfe7fc0 --- /dev/null +++ b/shader/lightmapWall.vert @@ -0,0 +1,7 @@ +#version 430 core +layout (location = 0) in vec4 poss; + +void main() +{ + gl_Position = poss; +} diff --git a/shader/wallShadow.geom b/shader/wallShadow.geom index b98b9b652..a029e1180 100644 --- a/shader/wallShadow.geom +++ b/shader/wallShadow.geom @@ -23,12 +23,12 @@ vec4 p1 = vec4 (gl_in[0].gl_Position.xy,0,1); vec4 p2 = vec4 (gl_in[0].gl_Position.zw,0,1); if (isLHS (p1.xy - lightPos, p2.xy - lightPos) < 0) { -vec4 p3 = vec4 (p1.xy,-0.2,1); -vec4 p4 = vec4 (p2.xy,-0.2,1); +vec4 p3 = vec4 (p1.xy,-0.5,1); +vec4 p4 = vec4 (p2.xy,-0.5,1); vec4 p5 = shift(p1); vec4 p6 = shift(p2); -vec4 p7 = vec4 (p6.xy,-0.2,1); -vec4 p8 = vec4 (p5.xy,-0.2,1); +vec4 p7 = vec4 (p6.xy,-0.5,1); +vec4 p8 = vec4 (p5.xy,-0.5,1); vec4 a1 = perpMat * p1; vec4 a2 = perpMat * p2; diff --git a/src/Dodge/Rendering.hs b/src/Dodge/Rendering.hs index 7f9b4c689..e06603b3c 100644 --- a/src/Dodge/Rendering.hs +++ b/src/Dodge/Rendering.hs @@ -505,13 +505,5 @@ wallsForGloom w = map (linePairs . _wlLine) $ filter (not . _wlIsSeeThrough) lightsForGloom' :: World -> [(Point4)] lightsForGloom' w = map getLS (IM.elems $ _lightSources w) ++ map getTLS (_tempLightSources w) - where getLS ls = ( fst $ ssls ls, snd $ ssls ls, _lsRad ls , _lsIntensity ls) - getTLS ls = ( fst $ sstls ls,snd $ sstls ls, _tlsRad ls, _tlsIntensity ls) - ss' v = rotateV (0 - _cameraRot w) (v -.- _cameraPos w) - ss'' (a,b) = (a*2*zoom / _windowX w,b*2*zoom / _windowY w) - ss = ss'' . ss' - ssls = _lsPos - sstls = _tlsPos --- ssls = ss . _lsPos --- sstls = ss . _tlsPos - zoom = _cameraZoom w + where getLS ls = ( fst $ _lsPos ls, snd $ _lsPos ls, _lsRad ls , _lsIntensity ls) + getTLS ls = ( fst $ _tlsPos ls,snd $ _tlsPos ls, _tlsRad ls, _tlsIntensity ls) diff --git a/src/Picture/Preload.hs b/src/Picture/Preload.hs index bb529bc65..3d066fbc9 100644 --- a/src/Picture/Preload.hs +++ b/src/Picture/Preload.hs @@ -23,7 +23,7 @@ import qualified Control.Foldl as F data RenderData = RenderData { _lightSourceShader :: FullShader (Float,Float,Float,Float) , _wallShadowShader :: FullShader (Point2,Point2) - , _wallLightShader :: FullShader (Point3) + , _wallLightShader :: FullShader (Point2,Point2) , _backgroundShader :: FullShader (Point2,Point2,Point2,Point2) , _fullscreenShader :: FullShader () , _wallShader :: FullShader (Point3,Point4) @@ -48,8 +48,9 @@ preloadRender = do wsShad <- makeShaderCustomUnis "wallShadow" [vert,geom,frag] [(0,4)] Points pokeWPStrat ["lightPos","perpMat","facesToDraw"] - wlLightShad <- makeShaderCustomUnis "wallLight" [vert,frag] [(0,3)] TriangleStrip pokeLightWallStrat - ["lightPosRadLum"] + wlLightShad + <- makeShaderCustomUnis "lightmapWall" [vert,geom,frag] [(0,4)] Points pokeWPStrat + ["lightPos","perpMat","radLum"] wlShad <- makeShader "wall" [vert,frag] [(0,3),(1,4)] TriangleStrip pokeWlStrat diff --git a/src/Picture/Render.hs b/src/Picture/Render.hs index 940655306..3892713af 100644 --- a/src/Picture/Render.hs +++ b/src/Picture/Render.hs @@ -61,7 +61,18 @@ renderPicture' pdata rot zoom (tranx,trany) (winx,winy) wallPoints lightPoints clearDepth $= 1 clear [ColorBuffer,DepthBuffer] - nWalls <- F.foldM (pokeShader (_wallShadowShader pdata)) wallPoints +-- calculate perspective matrix + pmat <- (newMatrix RowMajor + $ perspectiveMatrix rot zoom (tranx,trany) (winx,winy) (viewFromx,viewFromy) + ) :: IO (GLmatrix GLfloat) + + nWallLights <- F.foldM (pokeShader $ _wallLightShader pdata) wallPoints + bindShaderBuffers [_wallLightShader pdata] [nWallLights] + currentProgram $= Just (_shaderProgram $ _wallLightShader pdata) + uniform ( (fromJust $ _shaderCustomUnis $ _wallLightShader pdata) !! 1) + $= pmat + + nWalls <- F.foldM (pokeShader $ _wallShadowShader pdata) wallPoints bindShaderBuffers [_wallShadowShader pdata] [nWalls] let (tx,ty) = (tranx,trany) -.- (viewFromx,viewFromy) @@ -69,9 +80,6 @@ renderPicture' pdata rot zoom (tranx,trany) (winx,winy) wallPoints lightPoints currentProgram $= Just (_shaderProgram $ _wallShadowShader pdata) uniform (head $ fromJust $ _shaderCustomUnis $ _wallShadowShader pdata) $= Vector2 viewFromx viewFromy - pmat <- (newMatrix RowMajor - $ perspectiveMatrix rot zoom (tranx,trany) (winx,winy) (viewFromx,viewFromy) - ) :: IO (GLmatrix GLfloat) uniform ( (fromJust $ _shaderCustomUnis $ _wallShadowShader pdata) !! 1) $= pmat uniform ( (fromJust $ _shaderCustomUnis $ _wallShadowShader pdata) !! 2) @@ -80,6 +88,7 @@ renderPicture' pdata rot zoom (tranx,trany) (winx,winy) wallPoints lightPoints cullFace $= Nothing drawShader (_wallShadowShader pdata) nWalls + depthMask $= Disabled blendFunc $= (Zero, OneMinusSrcAlpha) -- blendFuncSeparate $= ((Zero,Zero),(Zero, OneMinusSrcAlpha)) @@ -114,14 +123,14 @@ renderPicture' pdata rot zoom (tranx,trany) (winx,winy) wallPoints lightPoints bindShaderBuffers [_lightSourceShader pdata] [1] stencilFunc $= (Equal, 0, 255) drawShader (_lightSourceShader pdata) 1 - --- currentProgram $= Just (_shaderProgram $ _wallLightShader pdata) --- uniform (head $ fromJust $ _shaderCustomUnis $ _wallLightShader pdata) --- $= Vector4 x y r lum --- cullFace $= Just Front --- depthFunc $= Just Lequal --- drawShader (_wallLightShader pdata) nLightWalls + currentProgram $= Just (_shaderProgram $ _wallLightShader pdata) + uniform (head $ fromJust $ _shaderCustomUnis $ _wallLightShader pdata) + $= Vector2 x y + uniform ( (fromJust $ _shaderCustomUnis $ _wallLightShader pdata) !! 2) + $= Vector2 r lum + drawShader (_wallLightShader pdata) nWallLights + depthMask $= Enabled cullFace $= Nothing stencilTest $= Disabled @@ -176,42 +185,6 @@ renderPicture' pdata rot zoom (tranx,trany) (winx,winy) wallPoints lightPoints ticks4 <- renderFoldable pdata rot zoom (tranx,trany) (winx,winy) $ picToLTree (Just 2) pic bticks <- SDL.ticks --- render walls --- depthFunc $= Nothing --- blendFunc $= (SrcAlpha,OneMinusSrcAlpha) --- -- poke data --- cullFace $= Just Back --- let lights = map (\(x,y,r,g) -> ((x,y),(r,g,0,0))) lightPoints --- wallPairs = map (\(a,b,_,_) -> [(a,(1,1,1,1)),(b,(1,1,1,1))]) wallPoints --- f (x,y) = [(x,y,0),(x,y,0),(x,y,-1)] --- g (x,y) = [(x,y,0),(x,y,-1),(x,y,-1)] --- wp = concatMap (\(a,b,_,_) -> f a ++ g b) wallPoints --- h p = (p,(1,0,0,1)) --- wp2 = ((200,200),(-200,200),(0,0),(0,0)) --- wp3 = ((-200,200),(-200,-200),(0,0),(0,0)) --- i <- F.foldM (pokeShader (_wallShader pdata)) $ concat $ mkShadFromWall <$> [wp2,wp3] <*> [(300,50,200,0)] --- --- -- bind buffers --- bindShaderBuffers [_wallShader pdata] [i] --- --- -- draw call --- drawShaders [_wallShader pdata] [i] --- depthFunc $= Just Lequal - ------- blendFunc $= (One,Zero) ------- let f (x,y) = (x,y,0) ------- h (x,y) = (x,y,-1) ------- g (a,b) = [f a,f a,h a,f b,h b,h b] ------- wp = concatMap g [((200,200),(-200,200))] ------- nLightWalls <- F.foldM (pokeShader (_wallLightShader pdata)) wp ------- bindShaderBuffers [_wallLightShader pdata] [nLightWalls] ------- currentProgram $= Just (_shaderProgram $ _wallLightShader pdata) ------- uniform (head $ fromJust $ _shaderCustomUnis $ _wallLightShader pdata) ------- $= Vector4 (0::Float) 0 200 0.5 ------- cullFace $= Just Front ------- depthFunc $= Just Lequal ------- drawShader (_wallLightShader pdata) nLightWalls - resetShaderUniforms (map extractProgAndUnis $ _listShaders pdata) endWallTicks <- SDL.ticks