From d35a41944c45c716f3e880aa5362eb76a4be7771 Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 1 Nov 2025 11:24:08 +0000 Subject: [PATCH] Start implementing ceiling stencil shader --- shader/lighting/wallShadow.geom | 67 +++++++++++++++++++++------------ src/Data/Preload/Render.hs | 1 + src/Dodge/Render.hs | 24 +++++++----- src/Preload/Render.hs | 3 ++ 4 files changed, 60 insertions(+), 35 deletions(-) diff --git a/shader/lighting/wallShadow.geom b/shader/lighting/wallShadow.geom index 4df12a823..0f6b76581 100644 --- a/shader/lighting/wallShadow.geom +++ b/shader/lighting/wallShadow.geom @@ -19,11 +19,29 @@ vec2 closestPointOnSeg (vec2 a,vec2 b, vec2 p) { } } // End include 2023-03-13 15:33:44.438312149 UTC +vec2 closestPointOnLine (vec2 a,vec2 b, vec2 p) { + float x = closestPointOnLineParam(a,b,p); + return a + (x * (b- a)); +} +vec2 invclosestPointOnLine (vec2 a,vec2 b, vec2 p) { + float x = dot (p-a,p-a)/ dot(p-a,b-a); + return a + x*(b- a); +} vec2 shift(vec2 p) { return vec2(lightPos.xy + (rad * normalize(p - lightPos.xy))); } -float isLHS(vec2 startV, vec2 testV) { - return sign(-startV.x * testV.y + startV.y * testV.x); +float detV(vec2 p, vec2 q) { + return p.x*q.y - p.y*q.x; +} +float isLHS(vec2 p, vec2 q) { + return sign(-detV(p,q)); +} +// the following does NOT check for division by zero: do not reuse this unless +// you are certain this cannot happen +vec2 intersectLL(vec2 p1,vec2 p2,vec2 q1,vec2 q2){ + float den = detV (p1-p2,q1-q2); + float t = detV (p1-q1,q1-q2); + return p1 + (t/den)*(p2-p1); } // constructs a "bridge" shape void main() { @@ -31,21 +49,36 @@ void main() { vec2 p2 = gl_in[0].gl_Position.zw; vec2 closepoint = closestPointOnSeg(p1,p2,lightPos.xy); if (isLHS(p1 - lightPos.xy, p2 - lightPos.xy) < 0 && distance(closepoint,lightPos.xy) < rad) { - // this is a point far along the ray from the light source to the midpoint - // of the wall. Necessary in case the light source is very close to the - // wall + vec2 xxxy = p1 + (0.25 * (p2 -p1)); + vec2 xt = shift(xxxy); + vec2 xo = invclosestPointOnLine(lightPos.xy,p1,xt); + vec2 xyyy = p1 + (0.75 * (p2 -p1)); + vec2 yt = shift(xyyy); + vec2 yo = invclosestPointOnLine(lightPos.xy,p2,yt); + + vec2 xoo = (distance(xo, lightPos.xy) < distance(p1, lightPos.xy) + || distance(p1,lightPos.xy)>rad + ? p1 : xo); + vec2 yoo = (distance(yo, lightPos.xy) < distance(p2, lightPos.xy) + || distance(p2,lightPos.xy)>rad + ? p2 : yo); + + vec2 mo = intersectLL(xoo,xt,yoo,yt); + vec2 closeshift = (rad * normalize(closepoint - lightPos.xy)) + lightPos.xy - closepoint; vec2 shifto = (rad * normalize(closepoint - lightPos.xy)) + closepoint; - vec2 p1cs = p1 + closeshift; - vec2 p1o = vec2( distance(p1,lightPos.xy) > rad ? p1cs : shift(p1) ); - vec2 p2cs = p2 + closeshift; - vec2 p2o = vec2( distance(p2,lightPos.xy) > rad ? p2cs : shift(p2) ); + //vec2 p1o = vec2( distance(p1,lightPos.xy) > rad ? p1 : shift(p1) ); + vec2 p1o = xoo; + //vec2 p2o = vec2( distance(p2,lightPos.xy) > rad ? p2 : shift(p2) ); + vec2 p2o = yoo; gl_Position = theMat * vec4(p1o,-500,1); EmitVertex(); gl_Position = theMat * vec4(p1,-500,1); EmitVertex(); gl_Position = theMat * vec4(p1o,100,1); EmitVertex(); gl_Position = theMat * vec4(p1,100,1); EmitVertex(); gl_Position = theMat * vec4(shifto,100,1); EmitVertex(); + //gl_Position = theMat * vec4(xt,100,1); EmitVertex(); + //gl_Position = theMat * vec4(mo,100,1); EmitVertex(); gl_Position = theMat * vec4(p2,100,1); EmitVertex(); gl_Position = theMat * vec4(p2o,100,1); EmitVertex(); gl_Position = theMat * vec4(p2,-500,1); EmitVertex(); @@ -53,22 +86,6 @@ void main() { EndPrimitive(); // be carefull with the winding... -// gl_Position = theMat * vec4(p2o,100,1); EmitVertex(); -// gl_Position = theMat * vec4(p2,100,1); EmitVertex(); -// gl_Position = theMat * vec4(p2o,0,1); EmitVertex(); -// gl_Position = theMat * vec4(p2,0,1); EmitVertex(); - -/// gl_Position = theMat * vec4(p2,100,1); EmitVertex(); -/// gl_Position = theMat * vec4(p2,-500,1); EmitVertex(); -/// gl_Position = theMat * vec4(p2o,100,1); EmitVertex(); -/// gl_Position = theMat * vec4(p2o,-500,1); EmitVertex(); -/// gl_Position = theMat * vec4(p2cs,100,1); EmitVertex(); -/// gl_Position = theMat * vec4(p2cs,-500,1); EmitVertex(); -/// gl_Position = theMat * vec4(p1cs,100,1); EmitVertex(); -/// gl_Position = theMat * vec4(p1cs,-500,1); EmitVertex(); -/// gl_Position = theMat * vec4(p1o,100,1); EmitVertex(); -/// gl_Position = theMat * vec4(p1o,-500,1); EmitVertex(); - EndPrimitive(); } else { } diff --git a/src/Data/Preload/Render.hs b/src/Data/Preload/Render.hs index 575c32c8e..d2dcb4088 100644 --- a/src/Data/Preload/Render.hs +++ b/src/Data/Preload/Render.hs @@ -15,6 +15,7 @@ data RenderData = RenderData , _lightingLineShadowShader :: Shader , _lightingCapShader :: Shader , _lightingTextureShader :: Shader + , _ceilingStencilShader :: Shader , _alphaDivideShader :: Shader , _windowShader :: Shader , _fullscreenShader :: Shader diff --git a/src/Dodge/Render.hs b/src/Dodge/Render.hs index 0501acb89..6e3e3769e 100644 --- a/src/Dodge/Render.hs +++ b/src/Dodge/Render.hs @@ -122,28 +122,33 @@ doDrawing' win pdata u = do glDepthMask GL_TRUE glDisable GL_BLEND glDepthFunc GL_LESS - with 1 $ - glClearNamedFramebufferfv + -- clear depth and stencil buffers + glStencilMask 255 -- to alter the entire stencil + glClearNamedFramebufferfi (pdata ^. fboBase . _1 . unFBO) - GL_DEPTH + GL_DEPTH_STENCIL + 0 + 1 0 -- draw wall occlusions from the camera's point of view glDisable GL_CULL_FACE +-- glEnable GL_STENCIL_TEST +-- glStencilFunc unless (debugOn Remove_LOS cfig) $ do - glUseProgram (pdata ^. lightingWallShadShader . shaderUINT) + glUseProgram (pdata ^. ceilingStencilShader . shaderUINT) glProgramUniform3f - (pdata ^. lightingWallShadShader . shaderUINT) + (pdata ^. ceilingStencilShader . shaderUINT) 0 vfx vfy 20 glProgramUniform1f - (pdata ^. lightingWallShadShader . shaderUINT) + (pdata ^. ceilingStencilShader . shaderUINT) 1 1000 -- this should be the furthest on screen distance from the viewpoint - glBindVertexArray $ pdata ^. lightingWallShadShader . shaderVAO . vaoName + glBindVertexArray $ pdata ^. ceilingStencilShader . shaderVAO . vaoName glDrawArrays - (_unPrimitiveMode $ pdata ^. lightingWallShadShader . shaderPrimitive) + (_unPrimitiveMode $ pdata ^. ceilingStencilShader . shaderPrimitive) 0 (fromIntegral trueNWalls) -- clear color and normals @@ -182,12 +187,11 @@ doDrawing' win pdata u = do glEnable GL_STENCIL_TEST glStencilFunc GL_ALWAYS 0 255 glStencilOp GL_INCR GL_INCR GL_INCR - with 0 $ \ptr -> + with 0 $ glClearNamedFramebufferiv (pdata ^. fboBase . _1 . unFBO) GL_STENCIL 0 - ptr glDrawArrays (_unPrimitiveMode $ pdata ^. chasmShader . shaderPrimitive) 0 diff --git a/src/Preload/Render.hs b/src/Preload/Render.hs index b2afd7119..2455ab14a 100644 --- a/src/Preload/Render.hs +++ b/src/Preload/Render.hs @@ -73,6 +73,8 @@ preloadRender = do makeShaderUsingVAO "lighting/cap" [vert, geom] pmTriangles shPosVAO lightingLineShadowShad <- makeShaderUsingVAO "lighting/lineShadow" [vert, geom] pmLinesAdjacency shedgevao + ceilingstencilshader <- + makeShaderUsingVBO "ceiling/stencil" [vert, geom] (toFloatVAs [4]) pmPoints wallvbo putStrLn "Setup 2D shaders" bslist <- makeShaderVBO "dualTwoD/basic" [vert, frag] (toFloatVAs [3, 4]) pmTriangles @@ -161,6 +163,7 @@ preloadRender = do , _lightingCapShader = lightingCapShad , _lightingLineShadowShader = lightingLineShadowShad , _lightingWallShadShader = lightingWallShadShad + , _ceilingStencilShader = ceilingstencilshader , _windowShader = windowshader , _fullscreenShader = fsShad , _alphaDivideShader = alphadivideshader