#version 150 core layout( triangles ) in; layout( triangle_strip, max_vertices = 24 ) out; struct Section { vec4 equation; vec3 center; }; struct SectionsData { int sectionsCount; Section sections[8]; }; in VertexData { vec3 position; } v_in[]; out FragData { vec3 fragPosition; vec3 fragNormal; } v_out; uniform SectionsData sectionsData; uniform mat4 mvp; const float radius = 1000.0; void emitQuad(Section section) { vec4 equation = section.equation; vec3 center = section.center; v_out.fragNormal = equation.xyz; // generate tangent and bitangent vec3 u = vec3(1.0f, 1.0f, 1.0f); // 2 vectors a (xa, ya, za), b (xb, yb, zb) are orthogonal if: // xaxb + yayb + zazb = 0 <=> // zb = -(xaxb + yayb) / za // yb = -(xaxb + zazb) / ya // xb = -(yayb + zazb) / xa if (equation.x != 0) u.x = -(u.y * equation.y + u.z * equation.z) / equation.x; else if (equation.y != 0) u.y = -(u.x * equation.x + u.z * equation.z) / equation.y; else if (equation.z != 0) u.z = -(u.x* equation.x + u.y * equation.y) / equation.z; u = normalize(u); vec3 v = normalize(cross(u, equation.xyz)) * radius; u *= radius; v_out.fragPosition = v_in[0].position; gl_Position = mvp * vec4(center + u + v, 1.0); EmitVertex(); v_out.fragPosition = v_in[1].position; gl_Position = mvp * vec4(center + u - v, 1.0); EmitVertex(); v_out.fragPosition = v_in[2].position; gl_Position = mvp * vec4(center - u + v, 1.0); EmitVertex(); v_out.fragPosition = v_in[0].position; gl_Position = mvp * vec4(center - u - v, 1.0); EmitVertex(); EndPrimitive(); } void main() { for (int i = 0; i < sectionsData.sectionsCount; ++i) { emitQuad(sectionsData.sections[i]); } }