@@ -4,19 +4,13 @@ uniform float THICKNESS; // the thickness of the line in pixels
4
4
uniform float MITER_LIMIT; // 1.0: always miter, -1.0: never miter, 0.75: default
5
5
uniform vec2 WIN_SCALE; // the size of the viewport in pixels
6
6
7
- uniform mat4 modelViewProjection;
8
-
9
- uniform vec3 camNearPlanePoint;
10
- uniform vec3 camNearPlaneNormal;
11
-
12
7
layout ( lines_adjacency ) in ;
13
8
layout ( triangle_strip, max_vertices = 7 ) out ;
14
9
15
10
16
- in VertexData{
17
- vec3 worldPosition;
11
+ // in VertexData{
18
12
// vec3 mColor;
19
- } VertexIn[4 ];
13
+ // } VertexIn[4];
20
14
21
15
out VertexData{
22
16
vec2 mTexCoord;
@@ -28,66 +22,61 @@ vec2 toScreenSpace( vec4 vertex )
28
22
return vec2 ( vertex.xy / vertex.w ) * WIN_SCALE;
29
23
}
30
24
31
- vec4 clip_line_point( vec3 pt0, vec3 pt1, vec4 projected )
25
+ vec4 clip_near_plane( vec4 pt1, vec4 pt2 )
32
26
{
33
- // we have line segment given by pt0 and pt1 (in world coordinates) and 'projected' point
34
- // (in clip coordinates) that is one of the endpoints. If the projected point's w >= 1
35
- // then everything is fine because the point is in front of the camera's near plane and
36
- // it is projected correctly. If not, the projected point is wrong and needs to be adjusted.
37
- // we place it at the intersection of the line and near plane to fix its position.
38
-
39
- if (projected.w < 1 )
40
- {
41
- vec3 lineDir = pt1 - pt0;
42
- float d = dot (camNearPlaneNormal, camNearPlanePoint - pt0) / dot (lineDir, camNearPlaneNormal);
43
- if (d > 0 && d < 1 )
44
- {
45
- // figure out the intersection point of line and near plane
46
- vec3 wpIntersect = pt0 + lineDir * d;
47
- vec4 wpIntersectProj = modelViewProjection * vec4 ( wpIntersect, 1.0 );
48
- return wpIntersectProj;
49
- }
50
- }
51
- return projected;
27
+ // Figure out intersection point of line pt1-pt2 and near plane in homogenous coordinates.
28
+ // Near plane is z=-1 in NDC, that means in homogenous coordinates that's z/w=-1
29
+ // Going from line equation P = P1 + u * (P2 - P1) we need to figure out "u"
30
+ // In the above equation P, P1, P2 are vectors, so individual coordinate values are
31
+ // x = x1 + u * (x2 - x1) and so on for y,z,w as well. Now combining near plane equation z/w=-1
32
+ // with line equation gives us the following equation for "u" (it's easy to do the math on paper)
33
+
34
+ float u = (- pt1.z - pt1.w) / ((pt2.z- pt1.z) + (pt2.w - pt1.w));
35
+ return pt1 + (pt2- pt1)* u;
52
36
}
53
37
54
38
void main( void )
55
39
{
56
- // these are original positions in world coordinates
57
- vec3 wp0 = VertexIn[0 ].worldPosition;
58
- vec3 wp1 = VertexIn[1 ].worldPosition;
59
- vec3 wp2 = VertexIn[2 ].worldPosition;
60
- vec3 wp3 = VertexIn[3 ].worldPosition;
40
+ vec4 px0 = gl_in[0 ].gl_Position ;
41
+ vec4 px1 = gl_in[1 ].gl_Position ;
42
+ vec4 px2 = gl_in[2 ].gl_Position ;
43
+ vec4 px3 = gl_in[3 ].gl_Position ;
61
44
62
45
// This implements rejection of lines from Cohen-Sutherland line clipping algorithm.
63
46
// Thanks to that we filter out majority of lines that may otherwise cause issues.
64
- // Lines that can't be trivially rejected, should be further clipped - the clipping
65
- // in the next step is a bit half-baked but seems to work relatively well.
66
- vec4 px1 = gl_in[1 ].gl_Position ;
67
- vec4 px2 = gl_in[2 ].gl_Position ;
47
+ // Lines that can't be trivially rejected, should be further clipped
68
48
int px1c = int (px1.w+ px1.x< 0 ) << 0 | int (px1.w- px1.x< 0 ) << 1 | int (px1.w+ px1.y< 0 ) << 2 | int (px1.w- px1.y< 0 ) << 3 | int (px1.w+ px1.z< 0 ) << 4 | int (px1.w- px1.z< 0 ) << 5 ;
69
49
int px2c = int (px2.w+ px2.x< 0 ) << 0 | int (px2.w- px2.x< 0 ) << 1 | int (px2.w+ px2.y< 0 ) << 2 | int (px2.w- px2.y< 0 ) << 3 | int (px2.w+ px2.z< 0 ) << 4 | int (px2.w- px2.z< 0 ) << 5 ;
70
50
if ((px1c & px2c) != 0 )
71
51
return ; // trivial reject
72
52
73
- // Perform line clipping first. we search for intersection between the line and the near plane.
53
+ // Perform line clipping with near plane if needed. We search for intersection between the line and the near plane.
74
54
// In case the near plane intersects line between segment's endpoints, we need to adjust the line
75
55
// otherwise we would use completely non-sense points when points get 'behind' the camera.
76
- // We do this also for the 'previous' and 'next' segments to get the miters right.
77
- vec4 projp0 = clip_line_point(wp0, wp1, gl_in[0 ].gl_Position );
78
- vec4 projp1 = clip_line_point(wp1, wp2, gl_in[1 ].gl_Position );
79
- vec4 projp2 = clip_line_point(wp1, wp2, gl_in[2 ].gl_Position );
80
- vec4 projp3 = clip_line_point(wp2, wp3, gl_in[3 ].gl_Position );
56
+ // It seems we don't need to clip against other five planes - only the near plane is critical because
57
+ // that turns the coordinates after perspective division in toScreenSpace() into a mess because of w < 1
58
+ if ((px1c & 16 ) != 0 )
59
+ {
60
+ // first point is in front of the near plane - need to clip it
61
+ px1 = clip_near_plane(px1, px2);
62
+ px0 = px1;
63
+ }
64
+ if ((px2c & 16 ) != 0 )
65
+ {
66
+ // second point is in front of the near plane - need to clip it
67
+ px2 = clip_near_plane(px1, px2);
68
+ px3 = px2;
69
+ }
81
70
82
71
// get the four vertices passed to the shader:
83
- vec2 p0 = toScreenSpace( projp0 ); // start of previous segment
84
- vec2 p1 = toScreenSpace( projp1 ); // end of previous segment, start of current segment
85
- vec2 p2 = toScreenSpace( projp2 ); // end of current segment, start of next segment
86
- vec2 p3 = toScreenSpace( projp3 ); // end of next segment
72
+ vec2 p0 = toScreenSpace( px0 ); // start of previous segment
73
+ vec2 p1 = toScreenSpace( px1 ); // end of previous segment, start of current segment
74
+ vec2 p2 = toScreenSpace( px2 ); // end of current segment, start of next segment
75
+ vec2 p3 = toScreenSpace( px3 ); // end of next segment
87
76
88
77
// these are already 'final' depths in range [0,1] so we don't need to further transform them
89
- float p1z = projp1 .z / projp1 .w;
90
- float p2z = projp2 .z / projp2 .w;
78
+ float p1z = px1 .z / px1 .w;
79
+ float p2z = px2 .z / px2 .w;
91
80
92
81
// determine the direction of each of the 3 segments (previous, current, next)
93
82
vec2 v0 = normalize ( p1 - p0 );
0 commit comments