93 lines
3.3 KiB
GLSL
93 lines
3.3 KiB
GLSL
#version 450 core
|
|
layout(points) in;
|
|
//layout(triangle_strip, max_vertices = 18) out;
|
|
layout(triangle_strip, max_vertices = 9) out;
|
|
layout(std140, binding = 0) uniform TheMat { mat4 theMat; };
|
|
layout(location=0) uniform vec3 lightPos;
|
|
layout(location=1) uniform float rad;
|
|
//float rad = rad;
|
|
// Preprocessed to include ../functions.glsl
|
|
float closestPointOnLineParam (vec2 a, vec2 b, vec2 p) {
|
|
return dot(p - a,b-a) / dot(b-a,b-a);
|
|
}
|
|
vec2 closestPointOnSeg (vec2 a,vec2 b, vec2 p) {
|
|
float x = closestPointOnLineParam(a,b,p);
|
|
if (x < 0) {
|
|
return a;
|
|
} else{ if (x > 1) { return b; }
|
|
{ return a + (x * (b- a));}
|
|
}
|
|
}
|
|
// 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 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() {
|
|
vec2 p1 = gl_in[0].gl_Position.xy;
|
|
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) {
|
|
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 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();
|
|
gl_Position = theMat * vec4(p2o,-500,1); EmitVertex();
|
|
EndPrimitive();
|
|
// be carefull with the winding...
|
|
|
|
EndPrimitive();
|
|
} else {
|
|
}
|
|
}
|