Difference between revisions of "Primitive"

From OpenGL.org
Jump to: navigation, search
m (Patches)
(Provoking vertex)
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{missing}}
+
{{pipeline float}}
  
 
'''Primitives''' are ways that OpenGL interprets vertex streams, converting them from vertices into triangles, lines, points, and so forth.
 
'''Primitives''' are ways that OpenGL interprets vertex streams, converting them from vertices into triangles, lines, points, and so forth.
Line 14: Line 14:
 
There is only one kind of point primitive: {{enum|GL_POINTS}}. This will cause OpenGL to interpret each individual vertex in the stream as a point.
 
There is only one kind of point primitive: {{enum|GL_POINTS}}. This will cause OpenGL to interpret each individual vertex in the stream as a point.
  
Points are squares or circles of a given size. The size can be given in two methods: by the program or by the context's state. To switch between them, use {{apifunc|glEnable|glDisable(GL_PROGRAM_POINT_SIZE)}}. If {{enum|GL_PROGRAM_POINT_SIZE}} is enabled, then the point size comes from a built-in variable: {{code|float gl_PointSize}}. If it is disabled, the point size is constant for all points in a primitive, and is set by the {{apifunc|glPointSize}} function.
+
Points are squares or circles of a given size. The size can be given in two methods: by the program or by the context's state. Use {{apifunc|glEnable|(GL_PROGRAM_POINT_SIZE)}} to set the point side from the program. If {{enum|GL_PROGRAM_POINT_SIZE}} is enabled, then the point size comes from a [[Vertex_Shader#Outputs|built-in output variable]]: {{code|float gl_PointSize}}. If it is disabled, the point size is constant for all points in a primitive, and is set by the {{apifunc|glPointSize}} function.
  
 
Regardless of how the point size is defined, it must be greater than 0, or else undefined behavior results. There is an implementation-defined range for point sizes, and the size given by either method is clamped to that range. You can query the range with {{enum|GL_POINT_SIZE_RANGE}} (returns 2 floats). There is also a point granularity that you can query with {{enum|GL_POINT_SIZE_GRANULARITY}}; the implementation will clamp sizes to its granularity as needed.
 
Regardless of how the point size is defined, it must be greater than 0, or else undefined behavior results. There is an implementation-defined range for point sizes, and the size given by either method is clamped to that range. You can query the range with {{enum|GL_POINT_SIZE_RANGE}} (returns 2 floats). There is also a point granularity that you can query with {{enum|GL_POINT_SIZE_GRANULARITY}}; the implementation will clamp sizes to its granularity as needed.
Line 20: Line 20:
 
=== Point Fragment Inputs ===
 
=== Point Fragment Inputs ===
  
Because a single point can generate multiple fragments, it is useful to know exactly where on the point a particular fragment is. A [[Fragment Shader]] gets the same input values for all user-defined inputs ({{code|gl_FragCoord}} will change, per the fragment's lcoation); therefore, the fragment shader must do its own interpolation.
+
Because a single point can generate multiple fragments (based on the size), it is useful to know exactly where on the point a particular fragment is. A [[Fragment Shader]] gets the same input values for all user-defined inputs ({{code|gl_FragCoord}} will change, per the fragment's location). Therefore, the fragment shader cannot rely on user-defined inputs to tell it's position in the point. So it must do its own interpolation.
  
To assist in this, the fragment shader can use the built-in input {{code|vec2 gl_PointCoord}}. This gives coordinates on the range [0, 1]. The location of (0, 0) depends on the point parameter setting for {{enum|GL_POINT_SPRITE_COORD_ORIGIN}}: if it is set to {{enum|GL_LOWER_LEFT}}, then (0, 0) is the bottom-left coordinate. While if it is {{enum|GL_UPPER_LEFT}}, then (0, 0) is the top-left coordinate.
+
To assist in this, the fragment shader can use the [[Fragment_Shader#System_inputs|built-in input]] {{code|vec2 gl_PointCoord}}. This gives coordinates on the range [0, 1]. The location of (0, 0) depends on the point parameter setting for {{enum|GL_POINT_SPRITE_COORD_ORIGIN}}: if it is set to {{enum|GL_LOWER_LEFT}}, then (0, 0) is the bottom-left coordinate. While if it is {{enum|GL_UPPER_LEFT}}, then (0, 0) is the top-left coordinate.
  
 
== Line Primitives ==
 
== Line Primitives ==
Line 28: Line 28:
 
There are 3 kinds of line primitives, based on different interpretations of a vertex stream.
 
There are 3 kinds of line primitives, based on different interpretations of a vertex stream.
  
* {{enum|GL_LINES}}: Vertices 0 and 1 are considered a line. Vertices 2 and 3 are considered a line. And so on. The user must specify an even number of vertices in the stream to use this.
+
* {{enum|GL_LINES}}: Vertices 0 and 1 are considered a line. Vertices 2 and 3 are considered a line. And so on. If the user specifies a non-even number of vertices, then the extra vertex is ignored.
* {{enum|GL_LINE_STRIP}}: The adjacent vertices are considered lines. Thus, if you pass ''n'' vertices, you will get ''n''-1 lines.
+
* {{enum|GL_LINE_STRIP}}: The adjacent vertices are considered lines. Thus, if you pass ''n'' vertices, you will get ''n''-1 lines. If the user only specifies 1 vertex, the rendering command is ignored.
* {{enum|GL_LINE_LOOP}}: As line strips, except that the first and last vertices are also used as a line. Thus, you get ''n'' lines for ''n'' input vertices.
+
* {{enum|GL_LINE_LOOP}}: As line strips, except that the first and last vertices are also used as a line. Thus, you get ''n'' lines for ''n'' input vertices. If the user only specifies 1 vertex, the rendering command is ignored.
  
 
== Triangle Primitives ==
 
== Triangle Primitives ==
Line 38: Line 38:
 
There are 3 kinds of triangle primitives, based again on different interpretations of the vertex stream:
 
There are 3 kinds of triangle primitives, based again on different interpretations of the vertex stream:
  
* {{enum|GL_TRIANGLES}}: Vertices 0, 1, and 2 form a triangle. Vertices 3, 4, and 5 form a triangle. And so on. The vertex stream must be a number of vertices divisible by 3 to work.
+
* {{enum|GL_TRIANGLES}}: Vertices 0, 1, and 2 form a triangle. Vertices 3, 4, and 5 form a triangle. And so on.
 
* {{enum|GL_TRIANGLE_STRIP}}: Every group of 3 adjacent vertices forms a triangle. The [[Face Culling|face direction]] of the strip is determined by the winding of the first triangle. A vertex stream of ''n'' length will generate ''n''-2 triangles.
 
* {{enum|GL_TRIANGLE_STRIP}}: Every group of 3 adjacent vertices forms a triangle. The [[Face Culling|face direction]] of the strip is determined by the winding of the first triangle. A vertex stream of ''n'' length will generate ''n''-2 triangles.
 
* {{enum|GL_TRIANGLE_FAN}}: The first vertex is always held fixed. From there on, every group of 2 adjacent vertices form a triangle with the first. So with a vertex stream, you get a list of triangles like so: (0, 1, 2) (0, 2, 3), (0, 3, 4), etc. A vertex stream of ''n'' length will generate ''n''-2 triangles.
 
* {{enum|GL_TRIANGLE_FAN}}: The first vertex is always held fixed. From there on, every group of 2 adjacent vertices form a triangle with the first. So with a vertex stream, you get a list of triangles like so: (0, 1, 2) (0, 2, 3), (0, 3, 4), etc. A vertex stream of ''n'' length will generate ''n''-2 triangles.
 +
 +
Any incomplete primitives will be ignored. For example, using {{enum|GL_TRIANGLES}} with a number of vertices not divisible by 3 will ignore the incomplete primitive at the end. Rendering with less than 3 vertices will result in nothing rendering.
  
 
Here are some examples that can be more illustrative:
 
Here are some examples that can be more illustrative:
Line 74: Line 76:
  
 
== Adjacency Primitives ==
 
== Adjacency Primitives ==
 +
{{missing}}
  
 
These are special primitives that are expected to be used specifically with [[Geometry Shaders]] (GS). These primitives give the geometry shader more vertices to work with for each input primitive. Normally, when using any of the above primitives, the GS gets merely one of the base type. If you use a GS with a {{enum|GL_TRIANGLE_STRIP}}, each execution of the GS will only see the 3 vertices of one particular triangle. These special primitive modes allow the GS to access vertex data for adjacent triangles.
 
These are special primitives that are expected to be used specifically with [[Geometry Shaders]] (GS). These primitives give the geometry shader more vertices to work with for each input primitive. Normally, when using any of the above primitives, the GS gets merely one of the base type. If you use a GS with a {{enum|GL_TRIANGLE_STRIP}}, each execution of the GS will only see the 3 vertices of one particular triangle. These special primitive modes allow the GS to access vertex data for adjacent triangles.
  
 
== Patches ==
 
== Patches ==
 +
{{main|Tessellation#Patches}}
 +
 +
The {{enum|GL_PATCH}} primitive type can only be used when [[Tessellation]] is active. It is a primitive with a user-defined number of vertices, which is then tessellated based on the [[Tessellation Control Shader|control]] and [[Tessellation Evaluation Shader|evaluation shaders]] into regular points, lines, or triangles as appropriate.
  
The {{enum|GL_PATCH}} primitive type can only be used with [[Tessellation Shader]]s. It is a primitive with a user-defined number of vertices, which is then tessellated based on the control and evaluation shaders into regular points, lines, or triangles as appropriate.
+
The number of vertices per patch is defined by calling {{apifunc|glPatchParameter|i}} with {{enum|GL_PATCH_VERTICES}} and some number of vertices, which must be less than {{enum|GL_MAX_PATCH_VERTICES}}. If the number of vertices in a patch is {{param|v}}, then the system will interpret every {{param|v}} vertices as a separate patch, much like {{enum|GL_LINES}} and {{enum|GL_TRIANGLES}}. So if you want strip-like behavior, you will need to use indices.
  
The number of vertices per patch is defined by calling {{apifunc|glPatchParameter|i}} with {{enum|GL_PATCH_VERTICES}} and some number of vertices, which must be less than {{enum|GL_MAX_PATCH_VERTICES}}. If the number of vertices is {{param|v}}, then the system will interpret every {{param|v}} vertices as a separate patch, much like {{enum|GL_LINES}} and {{enum|GL_TRIANGLES}}.
+
As with other incomplete primitive types, incomplete patches are ignored. So if you render with a number of vertices not divisible by {{param|v}}, then those last vertices are ignored.
  
 
== Provoking vertex ==
 
== Provoking vertex ==
  
One of the vertices in an output primitive is designated the "provoking vertex". This vertex has special meanings for the primitive. For example, when using [[Geometry Shader#Layered rendering|layered rendering]], the only value written to {{code|gl_Layer}} that matters is the one output with the provoking vertex. Flat-shaded interpolated values also come from the provoking vertex.
+
One of the vertices in an output primitive is designated the "provoking vertex". This vertex has special meanings for the primitive. For example, when using flat-shading on output variables, only outputs from the provoking vertex are used; every fragment generated by that primitive gets it's input from the output of the provoking vertex.
  
Each primitive type differently defines which index in the vertex stream defines the provoking vertex for a particular output primitive. There is a way to change the provoking vertex convention (primarily for D3D compatibility):
+
Each primitive type defines which index in the vertex stream defines the provoking vertex for a particular output primitive. There is a way to change the provoking vertex convention (primarily for [[D3D Compatibility]]):
  
 
  void {{apifunc|glProvokingVertex}}(GLenum {{param|provokeMode}});
 
  void {{apifunc|glProvokingVertex}}(GLenum {{param|provokeMode}});
  
{{param|provokeMode}} can be one of the two enumerators listed in the following table. This table defines which vertex index (using ''one-based indices'') is the provoking vertex for a particular primitive type. The {{param|i}} represents the ''one-based index'' of the primitive being drawn. For example, if you draw {{enum|GL_TRIANGLE_FANS}} with 5 vertices, {{param|i}} will range over [1, 3]. Thus, when using last vertex conventions, the provoking vertex of primitive index 2 will be the vertex index 4.
+
{{param|provokeMode}} can be one of the two enumerators listed in the following table; the default is {{enum|GL_LAST_VERTEX_CONVENTION}}. This table defines which vertex index (using ''one-based indices'') is the provoking vertex for a particular primitive type. The {{param|i}} represents the ''one-based index'' of the primitive being drawn. For example, if you draw {{enum|GL_TRIANGLE_FANS}} with 5 vertices, {{param|i}} will range over [1, 3]. Thus, when using last vertex conventions, the provoking vertex of primitive index 2 will be the vertex index 4.
  
Again, this table uses ''one-based indices''.
+
'''Again, this table uses ''one-based indices''.'''
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 146: Line 152:
 
|}
 
|}
  
Patches do not have a provoking vertex, since {{enum|GL_PATCH}} can only be used with [[Tessellation Shader]]s.
+
Patches do not have a provoking vertex, since {{enum|GL_PATCH}} can only be used with [[Tessellation]]. And by the time tessellation is finished, the primitive isn't a {{enum|GL_PATCH}} anymore. The output primitive of tessellation does have a provoking vertex.
  
 
== Primitive Restart ==
 
== Primitive Restart ==
Line 156: Line 162:
  
 
* [[Vertex Specification]]
 
* [[Vertex Specification]]
 +
** [[Vertex Rendering]]
 
* [[Point Rasterization]]
 
* [[Point Rasterization]]
 
* [[Line Rasterization]]
 
* [[Line Rasterization]]

Revision as of 17:44, 31 January 2013

Primitives are ways that OpenGL interprets vertex streams, converting them from vertices into triangles, lines, points, and so forth.

Vertex Stream

A vertex stream is an ordered list of vertices sent by an OpenGL drawing command. These get processed by a Vertex Shader into post-transform vertices.

Primitives define how OpenGL interprets a vertex stream. OpenGL can draw a vertex stream as points, lines or triangles. The primitive used to interpret a stream is given by the command used to render that stream.

Point Primitives

There is only one kind of point primitive: GL_POINTS. This will cause OpenGL to interpret each individual vertex in the stream as a point.

Points are squares or circles of a given size. The size can be given in two methods: by the program or by the context's state. Use glEnable(GL_PROGRAM_POINT_SIZE) to set the point side from the program. If GL_PROGRAM_POINT_SIZE is enabled, then the point size comes from a built-in output variable: float gl_PointSize​. If it is disabled, the point size is constant for all points in a primitive, and is set by the glPointSize function.

Regardless of how the point size is defined, it must be greater than 0, or else undefined behavior results. There is an implementation-defined range for point sizes, and the size given by either method is clamped to that range. You can query the range with GL_POINT_SIZE_RANGE (returns 2 floats). There is also a point granularity that you can query with GL_POINT_SIZE_GRANULARITY; the implementation will clamp sizes to its granularity as needed.

Point Fragment Inputs

Because a single point can generate multiple fragments (based on the size), it is useful to know exactly where on the point a particular fragment is. A Fragment Shader gets the same input values for all user-defined inputs (gl_FragCoord​ will change, per the fragment's location). Therefore, the fragment shader cannot rely on user-defined inputs to tell it's position in the point. So it must do its own interpolation.

To assist in this, the fragment shader can use the built-in input vec2 gl_PointCoord​. This gives coordinates on the range [0, 1]. The location of (0, 0) depends on the point parameter setting for GL_POINT_SPRITE_COORD_ORIGIN: if it is set to GL_LOWER_LEFT, then (0, 0) is the bottom-left coordinate. While if it is GL_UPPER_LEFT, then (0, 0) is the top-left coordinate.

Line Primitives

There are 3 kinds of line primitives, based on different interpretations of a vertex stream.

  • GL_LINES: Vertices 0 and 1 are considered a line. Vertices 2 and 3 are considered a line. And so on. If the user specifies a non-even number of vertices, then the extra vertex is ignored.
  • GL_LINE_STRIP: The adjacent vertices are considered lines. Thus, if you pass n vertices, you will get n-1 lines. If the user only specifies 1 vertex, the rendering command is ignored.
  • GL_LINE_LOOP: As line strips, except that the first and last vertices are also used as a line. Thus, you get n lines for n input vertices. If the user only specifies 1 vertex, the rendering command is ignored.

Triangle Primitives

A triangle is a primitive formed by 3 vertices. It is the 2D shape with the smallest number of vertices, so renderers are typically designed to render them. Since it is created from only 3 vertices, it is also guaranteed to be planar.

There are 3 kinds of triangle primitives, based again on different interpretations of the vertex stream:

  • GL_TRIANGLES: Vertices 0, 1, and 2 form a triangle. Vertices 3, 4, and 5 form a triangle. And so on.
  • GL_TRIANGLE_STRIP: Every group of 3 adjacent vertices forms a triangle. The face direction of the strip is determined by the winding of the first triangle. A vertex stream of n length will generate n-2 triangles.
  • GL_TRIANGLE_FAN: The first vertex is always held fixed. From there on, every group of 2 adjacent vertices form a triangle with the first. So with a vertex stream, you get a list of triangles like so: (0, 1, 2) (0, 2, 3), (0, 3, 4), etc. A vertex stream of n length will generate n-2 triangles.

Any incomplete primitives will be ignored. For example, using GL_TRIANGLES with a number of vertices not divisible by 3 will ignore the incomplete primitive at the end. Rendering with less than 3 vertices will result in nothing rendering.

Here are some examples that can be more illustrative:

GL_TRIANGLES:

Indices:     0 1 2 3 4 5 ...
Triangles:  {0 1 2}
                  {3 4 5}

GL_TRIANGLE_STRIP:

Indices:     0 1 2 3 4 5 ...
Triangles:  {0 1 2}
              {1 2 3}  drawing order is (2 1 3) to maintain proper winding
                {2 3 4}
                  {3 4 5}  drawing order is (4 3 5) to maintain proper winding

GL_TRIANGLE_FAN:

Indices:     0 1 2 3 4 5 ...
Triangles:  {0 1 2}
            {0} {2 3}
            {0}   {3 4}
            {0}     {4 5}

Quads

A quad is a 4 vertex quadrilateral primitive. The four vertices are expected to be coplanar; failure to do so can lead to undefined results.

A quad is typically rasterized as a pair of triangles. This is not defined by the GL spec, but it is allowed by it. This can lead to some artifacts due to how vertex/geometry shader outputs are interpolated over the 2 generated triangles.

  • GL_QUADS: Vertices 0-3 form a quad, vertices 4-7 form another, and so on. The vertex stream must be a number of vertices divisible by 4 to work.
  • GL_QUAD_STRIP: Similar to triangle strips, a quad strip uses adjacent edges to form the next quad. In the case of quads, the third and fourth vertices of one quad are used as the edge of the next quad. So vertices 0-3 are a quad, 2-6 are a quad, and so on. A vertex stream of n length will generate (n - 2) / 2 quads. As with triangle strips, the winding order of quads is changed for every other quad.

Adjacency Primitives

These are special primitives that are expected to be used specifically with Geometry Shaders (GS). These primitives give the geometry shader more vertices to work with for each input primitive. Normally, when using any of the above primitives, the GS gets merely one of the base type. If you use a GS with a GL_TRIANGLE_STRIP, each execution of the GS will only see the 3 vertices of one particular triangle. These special primitive modes allow the GS to access vertex data for adjacent triangles.

Patches

The GL_PATCH primitive type can only be used when Tessellation is active. It is a primitive with a user-defined number of vertices, which is then tessellated based on the control and evaluation shaders into regular points, lines, or triangles as appropriate.

The number of vertices per patch is defined by calling glPatchParameteri with GL_PATCH_VERTICES and some number of vertices, which must be less than GL_MAX_PATCH_VERTICES. If the number of vertices in a patch is v​, then the system will interpret every v​ vertices as a separate patch, much like GL_LINES and GL_TRIANGLES. So if you want strip-like behavior, you will need to use indices.

As with other incomplete primitive types, incomplete patches are ignored. So if you render with a number of vertices not divisible by v​, then those last vertices are ignored.

Provoking vertex

One of the vertices in an output primitive is designated the "provoking vertex". This vertex has special meanings for the primitive. For example, when using flat-shading on output variables, only outputs from the provoking vertex are used; every fragment generated by that primitive gets it's input from the output of the provoking vertex.

Each primitive type defines which index in the vertex stream defines the provoking vertex for a particular output primitive. There is a way to change the provoking vertex convention (primarily for D3D Compatibility):

void glProvokingVertex(GLenum provokeMode​);

provokeMode​ can be one of the two enumerators listed in the following table; the default is GL_LAST_VERTEX_CONVENTION. This table defines which vertex index (using one-based indices) is the provoking vertex for a particular primitive type. The i​ represents the one-based index of the primitive being drawn. For example, if you draw GL_TRIANGLE_FANS with 5 vertices, i​ will range over [1, 3]. Thus, when using last vertex conventions, the provoking vertex of primitive index 2 will be the vertex index 4.

Again, this table uses one-based indices.

Primitive type GL_FIRST_VERTEX_CONVENTION GL_LAST_VERTEX_CONVENTION
GL_POINTS i​ i​
GL_LINES 2i​ - 1 2i​
GL_LINE_LOOP i​ i​ + 1, if i​ < the number of vertices.

1 if i​ is equal to the number of vertices.

GL_LINE_STRIP i​ i​ + 1
GL_TRIANGLES 3i​ - 2 3i​
GL_TRIANGLE_STRIP i​ i​ + 2
GL_TRIANGLE_FAN i​ + 1 i​ + 2
GL_LINES_ADJACENCY 4i​ - 2 4i​ - 1
GL_LINE_STRIP_ADJACENCY i​ + 1 i​ + 2
GL_TRIANGLES_ADJACENCY 6i​ - 5 6i​ - 1
GL_TRIANGLE_STRIP_ADJACENCY 2i​ - 1 2i​ + 3

Patches do not have a provoking vertex, since GL_PATCH can only be used with Tessellation. And by the time tessellation is finished, the primitive isn't a GL_PATCH anymore. The output primitive of tessellation does have a provoking vertex.

Primitive Restart

Setting a primitive restart index will cause the interpretation of the primitive to be reset when that index is reached in the vertex stream. The vertex data at that index will not be processed, nor will a vertex be inserted into the vertex stream for that index value.

See Also