From c5034b3c4cfa6c930efb76c650dbfb3433e59d26 Mon Sep 17 00:00:00 2001 From: justin Date: Tue, 11 Nov 2025 16:23:39 +0000 Subject: [PATCH] Use ssbos for edge shadows Seems quite slow as is --- shader/lighting/lineShadow.vert | 81 ++++++++++++++++++++++++++++++++- src/Data/Preload/Render.hs | 1 + src/Dodge/Render.hs | 3 ++ src/Preload/Render.hs | 9 +++- src/Render.hs | 17 ++++--- 5 files changed, 102 insertions(+), 9 deletions(-) diff --git a/shader/lighting/lineShadow.vert b/shader/lighting/lineShadow.vert index 42d10dba1..922ac170f 100644 --- a/shader/lighting/lineShadow.vert +++ b/shader/lighting/lineShadow.vert @@ -1,6 +1,83 @@ #version 450 core -layout (location = 0) in vec3 pos; +struct PosColNorm { vec4 pos; vec4 col; vec4 norm; }; +layout (std140, binding = 0) uniform TheMat { mat4 theMat; } ; +layout (std430, binding = 3) readonly buffer Data { PosColNorm data[]; }; +layout (std430, binding = 5) readonly buffer Indices { uint indices[]; }; +layout(location=0)uniform vec3 lightPos; +layout(location=1)uniform float radiusUniform; +float closestPointOnLineParam3 (vec3 a, vec3 b, vec3 p) { + return dot(p - a,b-a) / dot(b-a,b-a); +} +vec3 closestPointOnSeg3 (vec3 a,vec3 b, vec3 p) { + float x = closestPointOnLineParam3(a,b,p); + if (x < 0) { + return a; + } else{ if (x > 1) { return b; } + { return a + (x * (b- a));} + } +} +vec4 shift(vec4 p) { return (vec4(p.xyz + (10000 * (p.xyz - lightPos)), 1)); } +vec4 shiftBy(float x, vec4 p) { + return (vec4(lightPos + (x * normalize(p.xyz - lightPos)), 1)); +} +vec4 projNear (vec4 pos) +{ + // note we project to a specific height + // this is quite brittle, not ideal + vec3 dir = pos.xyz - lightPos ; + float a = (100 - pos.z) / dir.z ; + vec2 xy = (pos.xyz + a * dir).xy ; + return vec4 ( xy, 100 , 1) ; +} +vec4 shiftNear(vec4 pos) +{ + vec4 sp = shift(pos); + if (sp.z > 100) { + return projNear(pos); + } else { + return sp; + } +} +int ks[6] = + {0,1,2 // 2--3 + ,2,1,3 // | | + }; // 0--1 void main() { - gl_Position = vec4(pos,1); + int k = ks[gl_VertexID % 6]; + int i0 = 4*(gl_VertexID / 6); + vec4 p0 = data[indices[i0]].pos; + vec4 p1 = data[indices[i0+1]].pos; + vec3 n0a = data[indices[i0+2]].pos.xyz; + vec3 n1a = data[indices[i0+3]].pos.xyz; + vec3 closepoint = closestPointOnSeg3(p0.xyz,p1.xyz,lightPos); + float ru2 = radiusUniform * radiusUniform; + vec4 mid = 0.5 * (p0 + p1); + 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; + vec4 p2 = shiftNear(p0); + vec4 p3 = shiftNear(p1); + vec4 ps[4] = {p0,p1,p2,p3}; + vec4 sp[4] = {p1,p0,p3,p2}; + gl_Position = vec4(0,0,0,1); + // first 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) > 0) {gl_Position = theMat * sp[k];} + else {gl_Position = theMat * ps[k]; } + //gl_Position = vec4(1,1,1,0); + } + else {gl_Position = vec4(1,1,1,0);} } +//layout (location = 0) in vec3 pos; +//void main() +//{ +// gl_Position = vec4(pos,1); +//} diff --git a/src/Data/Preload/Render.hs b/src/Data/Preload/Render.hs index 3f9f16925..4c0d9d06a 100644 --- a/src/Data/Preload/Render.hs +++ b/src/Data/Preload/Render.hs @@ -46,6 +46,7 @@ data RenderData = RenderData , _wallSSBO :: GLuint , _shapeSSBO :: GLuint , _ishapeSSBO :: GLuint + , _ieshapeSSBO :: GLuint -- , _lightsUBO :: GLuint -- BufferObject id , _vboWindows :: VBO , _vboShapes :: VBO diff --git a/src/Dodge/Render.hs b/src/Dodge/Render.hs index b46522361..3bd0e2585 100644 --- a/src/Dodge/Render.hs +++ b/src/Dodge/Render.hs @@ -138,6 +138,9 @@ doDrawing' win pdata u = do glNamedBufferSubData (pdata ^. ishapeSSBO) 0 (fromIntegral $ nIndices * (sizeOf (0::GLuint))) (pdata ^. shapeEBO . eboPtr) + glNamedBufferSubData (pdata ^. ieshapeSSBO) 0 + (fromIntegral $ nSilIndices * (sizeOf (0::GLuint))) + (pdata ^. silhouetteEBO . eboPtr) setViewport _gr_world_res cfig glBindFramebuffer GL_FRAMEBUFFER (pdata ^. fboBase . _1 . unFBO) glDepthMask GL_TRUE diff --git a/src/Preload/Render.hs b/src/Preload/Render.hs index 81939ac1f..b40ad0430 100644 --- a/src/Preload/Render.hs +++ b/src/Preload/Render.hs @@ -58,6 +58,11 @@ preloadRender = do glNamedBufferStorage ishapessbo ishapessbosize nullPtr GL_DYNAMIC_STORAGE_BIT glBindBufferBase GL_SHADER_STORAGE_BUFFER 4 ishapessbo + ieshapessbo <- mglCreate glCreateBuffers + let ieshapessbosize = fromIntegral (sizeOf (0::GLuint) * 65536) + glNamedBufferStorage ieshapessbo ieshapessbosize nullPtr GL_DYNAMIC_STORAGE_BIT + glBindBufferBase GL_SHADER_STORAGE_BUFFER 5 ieshapessbo + dummyvao <- mglCreate glGenVertexArrays winpull <- makeShaderUsingVAO "pull/window" [vert,frag] pmTriangles (VAO dummyvao) @@ -98,7 +103,8 @@ preloadRender = do --makeShaderUsingVAO "lighting/cap" [vert, geom] pmTriangles shPosVAO makeShaderUsingVAO "lighting/cap" [vert] pmTriangles (VAO dummyvao) lightingLineShadowShad <- - makeShaderUsingVAO "lighting/lineShadow" [vert, geom] pmLinesAdjacency shedgevao + --makeShaderUsingVAO "lighting/lineShadow" [vert, geom] pmLinesAdjacency shedgevao + makeShaderUsingVAO "lighting/lineShadow" [vert] pmTriangles shedgevao ceilingstencilshader <- makeShaderUsingVAO "ceiling/stencil" [vert] pmTriangles (VAO dummyvao) @@ -226,6 +232,7 @@ preloadRender = do , _wallSSBO = wallssbo , _shapeSSBO = shapessbo , _ishapeSSBO = ishapessbo + , _ieshapeSSBO = ieshapessbo -- , _lightsUBO = lightsubo , _vboWindows = winvbo , _vboShapes = shVBO diff --git a/src/Render.hs b/src/Render.hs index 6e648986b..c0e8b982f 100644 --- a/src/Render.hs +++ b/src/Render.hs @@ -186,12 +186,17 @@ renderShadows shadrendertype nWalls nSils nCaps positiontexture normaltexture li glUseProgram (_shaderUINT llinesShad) glUniform3f 0 x y z glUniform1f 1 rad - glBindVertexArray (_vaoName $ _shaderVAO llinesShad) - glDrawElements - (_unPrimitiveMode $ _shaderPrimitive llinesShad) - (fromIntegral nSils) - GL_UNSIGNED_INT - nullPtr + --glBindVertexArray (_vaoName $ _shaderVAO llinesShad) + glBindVertexArray (pdata ^. dummyVAO . vaoName) + glDrawArrays + GL_TRIANGLES + 0 + ((fromIntegral nSils * 6) `div` 4) + --glDrawElements + -- (_unPrimitiveMode $ _shaderPrimitive llinesShad) + -- (fromIntegral nSils) + -- GL_UNSIGNED_INT + -- nullPtr --draw caps on the near plane as required glEnable GL_CULL_FACE glCullFace GL_FRONT