So, I've been trying to draw a cylinder out of a line strip adjacency primitive with the geometry shader and it works for 4 vertices, but I want to make it so I that can apply it to longer line strips. The problem is that, it messes up completely after the fourth vertex. I know that the primitive gives the shader access to adjacency information, but I'm not sure how to access it, so my question is:
How do I use the adjacency information? And, Would it be possible to do this for multiple lines with the same drawing call?
I would very much appreciate pseudo code examples if you can provide it.
A geometry shader takes as input a set of vertices that form a single primitive e.g. a point or a triangle. The geometry shader can then transform these vertices as it sees fit before sending them to the next shader stage.
The Geometry Shader (GS) stage processes entire primitives: triangles, lines, and points, along with their adjacent vertices. It is useful for algorithms including Point Sprite Expansion, Dynamic Particle Systems, and Shadow Volume Generation. It supports geometry amplification and de-amplification.
Geometry shaders are natively not supported by WebGL.
A Fragment Shader is the Shader stage that will process a Fragment generated by the Rasterization into a set of colors and a single depth value. The fragment shader is the OpenGL pipeline stage after a primitive is rasterized. For each sample of the pixels covered by a primitive, a "fragment" is generated.
The following diagram comes from the D3D10 documentation, but I feel it conveys primitive topology better than the diagrams in the OpenGL specification.
What you need to understand is that when you use a primitive type w/Adjacency (e.g. GL_LINE_STRIP_ADJACENCY
) you actually have to supply additional data in your index buffer.
Do you see the dotted lines in the diagram? Those are extra indices that you have to insert into your index buffer (or simply as extra vertices if you are not using indexed drawing commands).
You will add an extra index to the beginning and end of your line strip to provide adjacent vertex information (denoted as 0 and 5 in the diagram above).
0,9,36,4,52,1,8 (7 indices, 6 lines)
Lines produced:
<0,9>
<9,36>
<36,4>
<4,52>
<52,1>
<1,8>
L-hand: 45
R-hand: 63
[45],0,9,36,4,52,1,8,[63] (9 indices, **still** 6 lines)
+ Vertices [45] and 36 are adjacent to line <0,9> (first line)
+ Vertices 52 and [63] are adjacent to line <1,8> (last line)
As you can see, 2 extra indices (denoted using [X]
) had to be added, because the first and last lines would otherwise have no vertex preceding or following them. Those indices do not form lines in the strip, they are just there to fill-in adjacency information where it would otherwise be undefined.
#version 330
// 4 vertices per-primitive -- 2 for the line (1,2) and 2 for adjacency (0,3)
layout (lines_adjacency) in;
// Standard fare for drawing lines
layout (line_strip, max_vertices = 2) out;
void main (void) {
// The two vertices adjacent to the line that you are currently processing
vec4 prev_vtx = gl_in [0].gl_Position;
vec4 next_vtx = gl_in [3].gl_Position;
gl_Position = gl_in [1].gl_Position; // First vertex in the line
EmitVertex ();
gl_Position = gl_in [2].gl_Position; // Second vertex in the line
EmitVertex ();
}
The Geometry Shader follows the description given in the OpenGL specification:
OpenGL 4.4 Core Profile Specification - 10.1.12 Line Strips with Adjacency - p. 306
A line segment is drawn from the
i
+ 2nd vertex to thei
+ 3rd vertex for eachi
= 0, 1, . . . ,n
− 1, where there aren
+ 3 vertices passed. If there are fewer than four vertices, all vertices are ignored. For line segmenti
, thei
+ 1st andi
+ 4th vertex are considered adjacent to thei
+ 2nd andi
+ 3rd vertices, respectively (see figure 10.3)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With