mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
They're actually guaranteed for the first and last segments due to the first and last points being duplicated in the buffer (simplifies design). This also handles the rare case where a vector appears to go directly into or out of the screen. Everything works nicely if only one of n1 or n2 is 0, and for the very rare case of both n1 and n2 being 0, then a final normal of 0 is reasonable.
79 lines
1.8 KiB
GLSL
79 lines
1.8 KiB
GLSL
attribute vec4 last, current, next;
|
|
attribute vec3 barycentric;
|
|
attribute float texoff;
|
|
|
|
uniform mat4 proj, view;
|
|
uniform vec2 viewport;
|
|
uniform float width;
|
|
|
|
varying vec2 texcoord;
|
|
varying vec3 vBC;
|
|
|
|
vec4
|
|
transform (vec3 coord)
|
|
{
|
|
return proj * view * vec4 (coord, 1.0);
|
|
}
|
|
|
|
vec2
|
|
project (vec4 coord)
|
|
{
|
|
vec3 device = coord.xyz / coord.w;
|
|
vec2 clip = (device * 0.5 + 0.5).xy;
|
|
return clip * viewport;
|
|
}
|
|
|
|
vec4
|
|
unproject (vec2 screen, float z, float w)
|
|
{
|
|
vec2 clip = screen / viewport;
|
|
vec2 device = clip * 2.0 - 1.0;
|
|
return vec4 (device * w, z, w);
|
|
}
|
|
|
|
float
|
|
estimateScale (vec3 position, vec2 sPosition)
|
|
{
|
|
vec4 view_pos = view * vec4 (position, 1.0);
|
|
vec4 scale_pos = view_pos - vec4 (normalize (view_pos.xy) * width,
|
|
0.0, 0.0);
|
|
vec2 screen_scale_pos = project (proj * scale_pos);
|
|
return distance (sPosition, screen_scale_pos);
|
|
}
|
|
|
|
void
|
|
main (void)
|
|
{
|
|
vec2 t, n1, n2, n;
|
|
vec2 sLast = project (transform (last.xyz));
|
|
vec2 sNext = project (transform (next.xyz));
|
|
vec4 dCurrent = transform (current.xyz);
|
|
vec2 sCurrent = project (dCurrent);
|
|
float off = current.w;
|
|
|
|
texcoord = vec2 (texoff * 0.7, off * 0.5 + 0.5);
|
|
vBC = barycentric;
|
|
|
|
t = sLast - sCurrent;
|
|
n1 = vec2 (0.0);
|
|
if (dot (t, t) > 0.001)
|
|
n1 = normalize (t);
|
|
t = sCurrent - sNext;
|
|
n2 = vec2 (0.0);
|
|
if (dot (t, t) > 0.001)
|
|
n2 = normalize (t);
|
|
n = vec2 (0.0);
|
|
if (n1 != -n2)
|
|
n = normalize (n1 + n2);
|
|
else if (dot (n1, n1) > 0.001)
|
|
n = n1;
|
|
else if (dot (n2, n2) > 0.001)
|
|
n = n2;
|
|
|
|
// rotate the normal by 90 degrees and scale by the desired width
|
|
vec2 dir = vec2 (n.y, -n.x) * off;
|
|
float scale = estimateScale (current.xyz, sCurrent);
|
|
vec2 pos = sCurrent + dir * scale;
|
|
|
|
gl_Position = unproject (pos, dCurrent.z, dCurrent.w);
|
|
}
|