'''Vertex Rendering''' is the process of taking vertex data specified in arrays and rendering one or more [[Primitive]]s with this vertex data.

'''Vertex Rendering''' is the process of taking vertex data specified in arrays and rendering one or more [[Primitive]]s with this vertex data.

Line 10:

Line 11:

The {{enum|GL_INVALID_OPERATION}} error can happen when issuing any rendering command for many reasons, most of which have little to do with the actual rendering command itself. The following represent conditions you must ensure are valid when issuing a rendering command.

The {{enum|GL_INVALID_OPERATION}} error can happen when issuing any rendering command for many reasons, most of which have little to do with the actual rendering command itself. The following represent conditions you must ensure are valid when issuing a rendering command.

−

* A non-zero [[Vertex Array Object]] must be bound (though no arrays have to be enabled, so it can be a freshly-created buffer object).

+

* A non-zero [[Vertex Array Object]] must be bound (though no arrays have to be enabled, so it can be a freshly-created vertex array object).

* The current framebuffer must be complete. The [[Default Framebuffer]] (if present) is always complete, so this usually happens with [[Framebuffer Object]]s.

* The current framebuffer must be complete. The [[Default Framebuffer]] (if present) is always complete, so this usually happens with [[Framebuffer Object]]s.

* The current program object or program pipeline object must be successfully linked and valid for the current state. This includes:

* The current program object or program pipeline object must be successfully linked and valid for the current state. This includes:

Line 19:

Line 20:

* Textures used by the current programs' samplers and/or images must be complete.

* Textures used by the current programs' samplers and/or images must be complete.

* If a [[Geometry Shader]] is present, the {{param|mode}} primitive type must be compatible with the primitive input that the GS uses.

* If a [[Geometry Shader]] is present, the {{param|mode}} primitive type must be compatible with the primitive input that the GS uses.

−

* If transform feedback is active, no geometry shader is present, the primitive mode provided to the rendering command must match the transform feedback mode.

+

* If [[Transform Feedback]] is active, and no geometry shader is present, the primitive mode provided to the rendering command must match the transform feedback mode.

* If transform feedback is active, and a geometry shader is present, the output primitive type from the geometry shader must match the transform feedback mode.

* If transform feedback is active, and a geometry shader is present, the output primitive type from the geometry shader must match the transform feedback mode.

* If the {{param|mode}} is {{enum|GL_PATCH}}, a [[Tessellation Shader]] must be active.

* If the {{param|mode}} is {{enum|GL_PATCH}}, a [[Tessellation Shader]] must be active.

−

* Buffer objects being read from or written to by an OpenGL rendering call must not be mapped. For example:

+

* If a [[Tessellation Shader]] is active, the {{param|mode}} must be {{enum|GL_PATCH}}.

+

* Buffer objects being read from or written by an OpenGL rendering call must not be mapped. This includes, but is not limited to:

** A buffer bound for [[Vertex Specification|attribute or index data]].

** A buffer bound for [[Vertex Specification|attribute or index data]].

** A buffer bound for [[Transform Feedback]] when that is active.

** A buffer bound for [[Transform Feedback]] when that is active.

Line 46:

Line 48:

{ 0 1 2 3 65535 2 3 4 5 }

{ 0 1 2 3 65535 2 3 4 5 }

−

If you render this as a triangle strip normally, you get 7 triangles. If you render it with {{apifunc|glPrimitiveRestartIndex|(65535)}} and the primitive restart enabled, then you will get 4 triangles:

+

If you render this as a triangle strip normally, you get 7 triangles. If you render it with {{apifunc|glPrimitiveRestartIndex|(65535)}} and {{enum|GL_PRIMITIVE_RESTART}} enabled, then you will get 4 triangles:

+

{0 1 2}, {1 2 3}, {2 3 4}, {3 4 5}

{0 1 2}, {1 2 3}, {2 3 4}, {3 4 5}

Primitive restart works with ''any'' rendering function. Even the indirect ones.

Primitive restart works with ''any'' rendering function. Even the indirect ones.

−

{{warning|It is technically legal to use this with non-indexed rendering. You should not do this, as it will not give you a useful result.}}

+

{{warning|It is technically legal to use primitive restart with non-indexed rendering. You should not do this, as it will not give you a useful result.}}

== Direct rendering ==

== Direct rendering ==

Line 69:

Line 72:

*{{param|count}} and {{param|indices}} parameters define the range of indices.

*{{param|count}} and {{param|indices}} parameters define the range of indices.

**{{param|count}} defines how many indices to use.

**{{param|count}} defines how many indices to use.

−

**{{param|indices}} defines the offset into the index buffer object (bound to {{enum|GL_ELEMENT_ARRAY_BUFFER}}, stored in the VAO) to begin reading data.

+

**{{param|indices}} defines the offset into the index buffer object (bound to {{enum|GL_ELEMENT_ARRAY_BUFFER}}, [[Vertex_Specification#Index_buffers|stored in the VAO]]) to begin reading data.

*{{param|type}} field describes what the type of the indices are:

*{{param|type}} field describes what the type of the indices are:

**{{enum|GL_UNSIGNED_BYTE}}: index range: [0, 255]

**{{enum|GL_UNSIGNED_BYTE}}: index range: [0, 255]

Line 81:

Line 84:

Rendering with a different VAO from the last rendering command is usually a relatively expensive operation. So many of the optimization mechanisms are based on you storing the data for several meshes in the same buffer objects with the same vertex formats and other VAO data.

Rendering with a different VAO from the last rendering command is usually a relatively expensive operation. So many of the optimization mechanisms are based on you storing the data for several meshes in the same buffer objects with the same vertex formats and other VAO data.

−

Binding a VAO or modifying VAO state is often an expensive operation. And there are many cases where you want to render a number of distinct meshes with a single draw call. All of the meshes must be in the same VAO, as must all of the index arrays if you are doing indexed rendering. Also, of course, they must use the same shader program with the same uniform values.

+

Binding a VAO or modifying VAO state is often an expensive operation. And there are many cases where you want to render a number of distinct meshes with a single draw call. All of the meshes must be in the same VAO (and therefore the same buffer objects and index buffers). Also, of course, they must use the same shader program with the same uniform values.

To render multiple primitives from a VAO at once, use this:

To render multiple primitives from a VAO at once, use this:

Line 154:

Line 157:

It is often useful to be able to render multiple copies of the same mesh in different locations. If you're doing this with small numbers, like 5-20 or so, multiple draw commands with shader uniform changes between them (to tell which is in which location) is reasonably fast in performance. However, if you're doing this with large numbers of meshes, like 5,000+ or so, then it can be a performance problem.

It is often useful to be able to render multiple copies of the same mesh in different locations. If you're doing this with small numbers, like 5-20 or so, multiple draw commands with shader uniform changes between them (to tell which is in which location) is reasonably fast in performance. However, if you're doing this with large numbers of meshes, like 5,000+ or so, then it can be a performance problem.

−

''Instancing'' is a way to get around this. The idea is that your vertex shader has some internal mechanism for deciding where each instance of the rendered mesh goes based on a single number. Perhaps it has a table (stored in a [[Buffer Texture]] or [[Uniform Buffer Object]]) that it indexes with the instance number to get the per-instance data it needs. Perhaps it uses an attribute divisor for certain attributes, which increments for each instance. Or perhaps it has a simple algorithm for computing the location of an instance based on its number.

+

''Instancing'' is a way to get around this. The idea is that your vertex shader has some internal mechanism for deciding where each instance of the rendered mesh goes based on a single number. Perhaps it has a table (stored in a [[Buffer Texture]] or [[Uniform Buffer Object]]) that it indexes with the instance number to get the per-instance data it needs. Perhaps it uses an [[Vertex_Specification#Instanced_arrays|attribute divisor]] for certain attributes, which increments for each instance. Or perhaps it has a simple algorithm for computing the location of an instance based on its number.

Regardless of the mechanism, if you want to do instanced rendering, you call:

Regardless of the mechanism, if you want to do instanced rendering, you call:

It will send the same vertices {{param|instancecount}} number of times, as though you called {{code|glDrawArrays/Elements}} in a loop of {{param|instancecount}} length. However, the vertex shader is given a special input value: {{code|gl_InstanceID}}. It will receive a value on the half-open range [0, {{param|instancecount}}) based on which instance of the mesh is being rendered. This is the only mechanism the vertex shader has for differentiating between instances; it is up to the shader itself to decide how to use this information.

+

It will send the same vertices {{param|instancecount}} number of times, as though you called {{code|glDrawArrays/Elements}} in a loop of {{param|instancecount}} length. However, the vertex shader is given a special input value: {{code|gl_InstanceID}}. It will receive a value on the half-open range [0, {{param|instancecount}}) based on which instance of the mesh is being rendered. {{code|gl_InstanceID}} and [[Vertex_Specification#Instanced_arrays|using instanced attribute arrays]] are the only mechanisms for being able to differentiate between instances.

−

In OpenGL 4.2 or with ARB_base_instance, the starting instance can be specified with "BaseInstance" commands, as follows:

+

In OpenGL 4.2 or with {{extref|base_instance}}, the starting instance can be specified with "BaseInstance" commands, as follows:

The {{param|baseinstance}} specifies the first instance. The {{param|instancecount}} still represents the number of instances. Thus, {{code|gl_InstanceID}} represents a value on the half-open range [{{param|baseinstance}}, {{param|instancecount}) + {{param|baseinstance}}).

+

The {{param|baseinstance}} specifies the first instance. The {{param|instancecount}} still represents the number of instances. Thus, {{code|gl_InstanceID}} represents a value on the half-open range [{{param|baseinstance}}, {{param|instancecount}} + {{param|baseinstance}}). The [[Vertex_Specification#Instanced_arrays|attribute divisor]] will also follow the base instance.

=== Range ===

=== Range ===

Line 228:

Line 231:

}}

}}

−

[[Transform Feedback]] objects can be used to render the results of a feedback operation. These are the effective equivalent of a {{apifunc|glDrawArrays}} or {{apifunc|glDrawArraysInstanced}} call, where appropriate.

+

When using [[Transform Feedback]] to generate vertices for rendering, you often use a [[Query_Object#Primitive_queries|asynchronous query object]] to get the number of primitives, and then use this number to compute the number of vertices for {{apifunc|glDrawArrays}} or {{apifunc|glDrawArraysInstanced}} call, where appropriate.

−

The most important thing to note is that the ''only'' thing these functions do is issue the rendering call. They ''do not bind the transform feedback buffers''. They do not modify any [[Vertex Array Object|VAO state]]. The only thing pulled from the transform feedback object is the number of primitives that were rendered to that stream. It is your responsibility to set up the vertex arrays for actually rendering before making these calls.

+

However, using a query object for this requires a GPU->CPU->GPU transfer of information. You have to read from the query object on the CPU, then transfer that information to your draw call.

−

The purpose of this feature is to avoid the GPU->CPU->GPU round-trip for the number of vertices written to a transform feedback stream. This is better even than using a [[Query Object]], as any waiting will happen on the GPU rather than the CPU.

+

This feature allows a way to bypass this. These functions allow the user to draw everything that was rendered during a transform feedback operation, without the CPU having to explicitly read the value back.

+

+

{{note|The ''only'' thing these functions do is issue the rendering call. They ''do not bind the transform feedback buffers''. They do not modify any [[Vertex Array Object|VAO state]]. The only thing pulled from the transform feedback object is the number of primitives that were rendered to that stream. It is your responsibility to set up the vertex arrays for actually rendering before making these calls.}}

To perform non-instanced rendering from a transform feedback object, these functions are used:

To perform non-instanced rendering from a transform feedback object, these functions are used:

Causes of rendering failure

The GL_INVALID_OPERATION error can happen when issuing any rendering command for many reasons, most of which have little to do with the actual rendering command itself. The following represent conditions you must ensure are valid when issuing a rendering command.

A non-zero Vertex Array Object must be bound (though no arrays have to be enabled, so it can be a freshly-created vertex array object).

The current program object or program pipeline object must be successfully linked and valid for the current state. This includes:

If there is a tessellation or geometry shader present, then there must also be a vertex shader present.

For program pipelines, separate program objects cannot come between two shader stages that are defined by a single object. So if you have program A which has a vertex and fragment shader, you cannot put program B with a geometry shader between them.

If any active program(s) have two (or more) samplers of different texture types, but are associated with the same texture unit. The same goes for image binding.

This list is not comprehensive. If you know of more, please add them here.

Common

Rendering can take place as non-indexed rendering or indexed rendering. Indexed rendering uses an element buffer to decide which index in the vertex arrays values are pulled from. This is explained in more detail in the Vertex Specification article.

All non-indexed rendering commands are of the form, gl*Draw*Arrays*​, where the *​ values can be filled in with different words. All indexed rendering commands are of the form, gl*Draw*Elements*​.

Primitive Restart

Primitive restart functionality allows you to tell OpenGL that a particular index value means, not to source a vertex at that index, but to begin a new primitive of the same type with the next vertex. In essence, it is an alternative to glMultiDrawElements​ (see below). This allows you to have an element buffer that contains multiple triangle strips or fans (or similar primitives where the start of a primitive has special behavior).

The way it works is with the function glPrimitiveRestartIndex​. This function takes an index value. If this index is found in the index array, the system will start the primitive processing again as though a second rendering command had been issued. If you use a BaseVertex drawing function, this test is done before the base vertex is added to the restart. Using this feature also requires using glEnable(GL_PRIMITIVE_RESTART)​ to activate it, and the corresponding glDisable​ to turn it off.

Here is an example. Let's say you have an index array as follows:

{ 0 1 2 3 65535 2 3 4 5 }

If you render this as a triangle strip normally, you get 7 triangles. If you render it with glPrimitiveRestartIndex(65535)​ and GL_PRIMITIVE_RESTART enabled, then you will get 4 triangles:

{0 1 2}, {1 2 3}, {2 3 4}, {3 4 5}

Primitive restart works with any rendering function. Even the indirect ones.

Warning: It is technically legal to use primitive restart with non-indexed rendering. You should not do this, as it will not give you a useful result.

Direct rendering

These vertex rendering commands provide the various rendering parameters directly as parameters passed to the functions. This contrasts with other rendering commands (see later sections), were some parameters are pulled from OpenGL object sources.

indices​ defines the offset into the index buffer object (bound to GL_ELEMENT_ARRAY_BUFFER, stored in the VAO) to begin reading data.

type​ field describes what the type of the indices are:

GL_UNSIGNED_BYTE: index range: [0, 255]

GL_UNSIGNED_SHORT: index range: [0, 65535]

GL_UNSIGNED_INT: index range: [0, 232 - 1].

Multi-Draw

The basic drawing functions are all you really need in order to send vertices for rendering. However, there are a number of ways to draw that optimize certain rendering cases.

Rendering with a different VAO from the last rendering command is usually a relatively expensive operation. So many of the optimization mechanisms are based on you storing the data for several meshes in the same buffer objects with the same vertex formats and other VAO data.

Binding a VAO or modifying VAO state is often an expensive operation. And there are many cases where you want to render a number of distinct meshes with a single draw call. All of the meshes must be in the same VAO (and therefore the same buffer objects and index buffers). Also, of course, they must use the same shader program with the same uniform values.

Multi-draw is useful for circumstances where you know that you are going to draw a lot of separate primitives of the same kind that all use the same shader. Typically, this would be a single conceptual object that you would always draw together in the same way. You simply pack all of the vertex data into the same VAO and buffer objects, using the various offsets to pick and choose between them.

Base Index

All of the glVertexAttribPointer​ calls define the format of the vertices. That is, the way the vertex data is stored in the buffer objects. Changing this format is somewhat expensive in terms of performance.

If you have a number of meshes that all share the same vertex format, it would be useful to be able to put them all in a single set of buffer objects, one after the other. If we have two meshes, A and B, then their data would look like this:

The glDrawArrays​ call takes a start index. If we are using unindexed rendering, then this is all we need. We call glDrawArrays​ once with 0 as the start index and nn as the array count. Then we call it again with nn as the start index and mm as the array count.

Indexed rendering is often very useful, both for memory saving and performance. So it would be great if we can preserve this performance saving optimization when using indexed rendering.

In indexed rendering, each mesh also has an index buffers. glDrawElements​ takes an offset into the index buffer, so we can use the same mechanism to select which sets of indices to use.

The problem is the contents of these indices. The third vertex of mesh B is technically index 02. However, the actual index is determined by the location of that vertex relative to where the format was defined. And since we're trying to avoid redefining the format, the format still points to the start of the buffer. So the third vertex of mesh B is actually at index 02 + nn.

We could in fact store these indices in the index buffer that way. We could go through all of mesh B's indices and add nn to them. But we don't have to.

This works as glDrawElements​ does, except that basevertex​ is added to each index before pulling from the vertex data. So for mesh A, we pass a base vertex of 0 (or just use glDrawElements​), and for mesh B, we pass a base vertex of nn.

Note: When combining with primitive restart, the restart test happens before the base index is added to the index.

Instancing

It is often useful to be able to render multiple copies of the same mesh in different locations. If you're doing this with small numbers, like 5-20 or so, multiple draw commands with shader uniform changes between them (to tell which is in which location) is reasonably fast in performance. However, if you're doing this with large numbers of meshes, like 5,000+ or so, then it can be a performance problem.

Instancing is a way to get around this. The idea is that your vertex shader has some internal mechanism for deciding where each instance of the rendered mesh goes based on a single number. Perhaps it has a table (stored in a Buffer Texture or Uniform Buffer Object) that it indexes with the instance number to get the per-instance data it needs. Perhaps it uses an attribute divisor for certain attributes, which increments for each instance. Or perhaps it has a simple algorithm for computing the location of an instance based on its number.

Regardless of the mechanism, if you want to do instanced rendering, you call:

It will send the same vertices instancecount​ number of times, as though you called glDrawArrays/Elements​ in a loop of instancecount​ length. However, the vertex shader is given a special input value: gl_InstanceID​. It will receive a value on the half-open range [0, instancecount​) based on which instance of the mesh is being rendered. gl_InstanceID​ and using instanced attribute arrays are the only mechanisms for being able to differentiate between instances.

In OpenGL 4.2 or with ARB_base_instance, the starting instance can be specified with "BaseInstance" commands, as follows:

The baseinstance​ specifies the first instance. The instancecount​ still represents the number of instances. Thus, gl_InstanceID​ represents a value on the half-open range [baseinstance​, instancecount​ + baseinstance​). The attribute divisor will also follow the base instance.

Range

Implementations of OpenGL can often find it useful to know how much vertex data is being used in a buffer object. For non-indexed rendering, this is pretty easy to determine: the first​ and count​ parameters of the Arrays functions gives you appropriate information. For indexed rendering, this is more difficult, as the index buffer can use potentially any index up to its size.

Still for optimization purposes, it is useful for implementations to know the range of indexed rendering data. Implementations may even read index data manually to determine this.

The "Range" series of glDrawElements​ commands allows the user to specify that this indexed rendering call will never cause indices outside of the given range of values to be sourced. The call works as follows:

Unlike the "Arrays" functions, the start​ and end​ parameters specify the minimum and maximum index values (from the element buffer) that this draw call will use (rather than a first and count-style). If you try to violate this restriction, you will get implementation-behavior (ie: rendering may work fine or you may get garbage).

There is one index that is allowed outside of the area bound by start​ and end​: the primitive restart index. If primitive restart is set and enabled, it does not have to be within the given boundary.

Implementations may have a specific "sweet spot" for the range of indices, such that using indices within this range will have better performance. They expose such values with a pair of glGetIntegerv​ enumerators. To get the best performance, end​ - start​ should be less than or equal to GL_MAX_ELEMENTS_VERTICES, and count​ (the number of indices to be rendered) should be less than or equal to GL_MAX_ELEMENTS_INDICES.

Combinations

It is often useful to combine these optimization techniques. Primitive restart can be combined with any of them, so long as they are using indexed rendering. The primitive restart comparison test, in the case of BaseVertex calls, is done before the base index is added to the index from the mesh.

Base vertex can be combined with any one of MultiDraw, Range, or Instancing. These functions are:

However, using a query object for this requires a GPU->CPU->GPU transfer of information. You have to read from the query object on the CPU, then transfer that information to your draw call.

This feature allows a way to bypass this. These functions allow the user to draw everything that was rendered during a transform feedback operation, without the CPU having to explicitly read the value back.

Note: The only thing these functions do is issue the rendering call. They do not bind the transform feedback buffers. They do not modify any VAO state. The only thing pulled from the transform feedback object is the number of primitives that were rendered to that stream. It is your responsibility to set up the vertex arrays for actually rendering before making these calls.

To perform non-instanced rendering from a transform feedback object, these functions are used:

Indirect rendering

Indirect rendering is the process of issuing a rendering command to OpenGL, except that most of the parameters to that command come from GPU storage provided by a Buffer Object. For example, glDrawArrays​ takes a primitive type, the number of vertices, and the starting vertex. When using the indirect rendering command glDrawArraysIndirect​, the starting vertex and number of vertices to render would instead be stored in a buffer object.

The purpose of this is to allow GPU processes to fill these values in. This could be a compute shader, a specially designed geometry shader coupled with transform feedback, or an OpenCL/CUDA process. The idea is to avoid the GPU->CPU->GPU round-trip; the GPU decides what range of vertices to render with. All the CPU does is decide when to issue the rendering command, as well as which Primitive is used with that command.

The indirect rendering functions take their data from the buffer currently bound to the GL_DRAW_INDIRECT_BUFFER binding. Thus, any of these functions will fail if no buffer is bound to that binding.

All of the indirect rendering functions allow the following features:

Indexed rendering

Base vertex (for indexed rendering)

Instanced rendering

Base instance (if GL 4.2 or ARB_base_instance is available)

Thus, they act as the largest combination of features of the supported implementation.

The drawcount​ is the number of indirect rendering commands to issue; the stride​ is the byte offset from one rendering command to the next. It can be set to zero; if so, then the array of indirect commands is assumed to be tightly backed (ie: 16-byte stride). The stride​ must be a multiple of 4.

The mode​ and type​ parameters work as they do in regular glDrawElements​-style functions. As with other indirect functions, the indirect​ is the byte-offset into the GL_DRAW_INDIRECT_BUFFER to find the indirect data structure.

The drawcount​ is the number of indirect rendering commands to issue; the stride​ is the byte offset from one rendering command to the next. It can be set to zero; if so, then the array of indirect commands is assumed to be tightly backed (ie: 20-byte stride). The stride​ must be a multiple of 4.

Conditional rendering

Conditional rendering is a mechanism for making the execution of one or more rendering commands conditional on the result of an Occlusion Query operation. This feature allows you to render some cheap object, then use an occlusion query to see if any of it is visible. If it is, then you can render the expensive object, but if it isn't, then you can save time and performance.

All rendering commands issued within the boundaries of these two functions will only execute if the occlusion condition specified by id​ is tested to be true. For GL_SAMPLES_PASSED queries, it is considered true (and thus rendering commands are executed) if the number of samples is not zero.

The mode​ parameter determines how the discarding of the rendering functions is performed. It can be one of the following:

GL_QUERY_WAIT​: OpenGL will wait until the query result is returned, then decide whether to execute the rendering command. This ensures that the rendering commands will only be executed if the query fails. Note that it is OpenGL that's waiting, not (necessarily) the CPU.

GL_QUERY_NO_WAIT​: OpenGL may execute the rendering commands anyway. It will not wait to see if the query test is true or not. This is used to prevent pipeline stalls if the time between the query test and the execution of the rendering commands is too short.

GL_QUERY_BY_REGION_WAIT: OpenGL will wait until the query result is returned, then decide whether to execute the rendering command. However, the rendered results will be clipped to the samples that were actually rasterized in the occlusion query. Thus, the rendered result can never appear outside of the occlusion query area.

GL_QUERY_BY_REGION_NO_WAIT: As above, except that it may not wait until the occlusion query is finished. The region clipping still holds.

Note that "wait" in this case does not mean that glEndConditionalRender​ itself will stall on the CPU. It means that the first command within the conditional rendering scope will not be executed by the GPU until the query has returned. So the CPU will continue processing, but the GPU itself may have a pipeline stall.