3
votes

I am working on a project where (and I am simplifying a little)

I need to calculate cross sections of 3-dimensional shapes and render them. For example, I may have a list of tetrahedrons (each tetrahedron consists of 4 vertices), or a list of triangular prisms (each triangular prism consists of 6 vertices), or a list of n prisms (each n prism consists of 2 * n vertices), etc. I want to calculate two-dimensional cross sections of them (the two dimensional cross sections would be made up of triangles), and render the cross sections.

The simplest and most efficient way I have thought of for this is sending the 3D vertices to the vertex shader, then sending them to the geometry shader and taking the cross sections there. However, in order to do this, the geometry shader would need to take in primitives with 4 points, or 6 points (more than 3 points). This is a problem, because to my knowledge the geometry shader can only take in points, lines, and triangles, and nothing with more points. I could solve this by storing the attributes of several 3D vertices in a single GLSL vertex, but this would be very complicated and inelegant.

Question:

Is there a way for the geometry shader to handle primitives of custom lengths, similar to the patch primitives used in tessellation shaders? I will still only be outputting triangles from the geometry shader.

Note: By the way, I am kind of new to OpenGL, so tell me if I got any of the terminology wrong.


Edit: By "cross section" I mean any cross section along a plane that is not necessarily aligned with the bases of the prisms. There will therefor be a variable number of triangles resulting per cross section. For example, a plane may intersect a tetrahedron at 0, 3, or 4 points, and the geometry shader (ideally) would take in 4-point primitives and output either 0, 1, or 2 triangles. Also, my question has nothing to do with the actual cross section calculation. I am asking specifically whether there is a way to use a primitive with more than 3 points as an input to the geometry shader. Finally, this is the second question I have posted, so I don't know whether I have formatted things properly. Sorry if I haven't!

1
What do you mean by cross section? I think a diagram might help to understand what you mean. If your cross-sections are always across the prism, then you're effectively just repeating the end geometry of the prism.user673679

1 Answers

3
votes

Is there a way for the geometry shader to handle primitives of custom lengths, similar to the patch primitives used in tessellation shaders?

If you want to work with a geometry shader, there are two straightforward ways to achieve this:

1) Use triangles_adjacency as input primitive type instead of triangles, which provides you with 6 vertices per geometry shader invocation. Usually this is used to provide adjacency information at the three edges of the current triangle, but you can provide whatever data you want via the element buffer. See here for a quick overview of geometry shaders.

2) Use points (or anything else, for that matter) as input primitive type and make use of the built-in variable gl_PrimitiveIDIn. Create a shader storage buffer, texture buffer or simply a texture to hold your geometry data and use this primitive ID to access the data for the current shape. If you have shapes with varying vertex count, you can use an additional index buffer that you access with the primitive id. Then you access the vertex buffer at the offset you got from your index buffer.

The second solution is obviously the more flexible one. A third option is to not do this in the geometry shader in the first place. You execute a compute shader, say one invocation per shape you have, bind writeable shader storage buffers for vertices and indices, do your cross-section calculations in the shader as usual, store the resulting geometry in the buffers and then draw the cross-section geometry as usual. This way, you do not need to take the detour through the vertex shader which transforms vertices you do not want to render.