I wrote a geometric shader to calculate the intersection of the grid and the plane, but at the intersection between the two lines there are sometimes gaps of 1 pixel wide.

The shader first calculates the sign distances of the vertices of the triangle to the plane. He then checks to see if the two distances have a different sign to determine if there is an intersection with the edge. If so, it emits a vertex at the intersection, which is calculated as the weighted average between the points of the edge.
#version 330 layout(triangles) in; layout(line_strip, max_vertices = 3) out; out vec3 vertexPosition; uniform vec3 planePos; uniform vec3 planeNormal; uniform mat4 mvpMatrix; uniform vec2 screenSize; void intersection(in vec4 a, in float distA, in vec4 b, in float distB) { if (sign(distA) * sign(distB) <= 0.0f && !(sign(distA) == 0 && sign(distB) == 0)) { float fa = abs(distA); float fb = abs(distB); float fab = fa + fb; vec4 ptIntersection; // Don't divide by zero. if (fab < 0.001) ptIntersection = (a + b) * 0.5; else ptIntersection = (fa * b + fb * a) / fab; gl_Position = mvpMatrix * ptIntersection; vertexPosition = gl_Position.xyw; EmitVertex(); } } void main() { vec4 a = gl_in[0].gl_Position; vec4 b = gl_in[1].gl_Position; vec4 c = gl_in[2].gl_Position; float distA = dot(a.xyz - planePos, planeNormal); float distB = dot(b.xyz - planePos, planeNormal); float distC = dot(c.xyz - planePos, planeNormal); intersection(a, distA, b, distB); intersection(b, distB, c, distC); intersection(c, distC, a, distA); }
I know this is cheap, because I ignored the special case where all three points lie on a plane. !(sign(distA) == 0 && sign(distB) == 0) guarantees that if two points lie on the plane, a vertex will not be selected for this edge. Therefore, if all three are on the plane, there will be no way out. But I think this is not necessarily a bad thing. I like that there is no crazy branching, and I would like to keep it that way if possible.
So, I wonder: why do I see these gaps? Let them say that there are two triangles (a, b, c) and (c, b, d). a and b above the plane, c and d below. For the first triangle, the shader generates the intersection with (b, c), for the second - the intersection with (c, b). Assuming that adding two floats is commutative, the intersection function is symmetrical in inputs, so the results should be the same. Why am I still seeing these spaces?