#version 450 core 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{ return (x > 1 ? b: 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); return (sp.z > 100 ? projNear(pos) : sp); } int ks[6] = {0,1,2 // 2--3 ,2,1,3 // | | }; // 0--1 void main() { 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); // 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) { vec4 sp[4] = {p1,p0,p3,p2}; gl_Position = theMat * sp[k];} else { vec4 ps[4] = {p0,p1,p2,p3}; gl_Position = theMat * ps[k]; } } else {gl_Position = vec4(1,1,1,0);} } //layout (location = 0) in vec3 pos; //void main() //{ // gl_Position = vec4(pos,1); //}