Name EXT_instanced_arrays Name Strings GL_EXT_instanced_arrays Contributors Contributors to ARB_instanced_arrays desktop OpenGL extension from which this extension borrows heavily Abhijit Bhelande, Apple Benj Lipchak, Apple Contact Benj Lipchak, Apple (lipchak 'at' apple.com) Status Complete Version Last Modified Date: June 26, 2013 Revision: 2 Number OpenGL ES Extension #156 Dependencies OpenGL ES 2.0 is required. This extension is written against the OpenGL ES 2.0 Specification. OES_element_index_uint affects the definition of this extension. Overview A common use case in GL for some applications is to be able to draw the same object, or groups of similar objects that share vertex data, primitive count and type, multiple times. This extension provides a means of accelerating such use cases while reducing the number of API calls, and keeping the amount of duplicate data to a minimum. This extension introduces an array "divisor" for generic vertex array attributes, which when non-zero specifies that the attribute is "instanced." An instanced attribute does not advance per-vertex as usual, but rather after every conceptual draw calls. (Attributes which aren't instanced are repeated in their entirety for every conceptual draw call.) By specifying transform data in an instanced attribute or series of instanced attributes, vertex shaders can, in concert with the instancing draw calls, draw multiple instances of an object with one draw call. IP Status No known IP claims. New Tokens Accepted by the parameters of GetVertexAttribfv and GetVertexAttribiv: VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE New Procedures and Functions void VertexAttribDivisorEXT(uint index, uint divisor); void DrawArraysInstancedEXT(enum mode, int first, sizei count, sizei instanceCount); void DrawElementsInstancedEXT(enum mode, sizei count, enum type, const void *indices, sizei instanceCount); Additions to Chapter 2 of the OpenGL ES 2.0 Specification Modify section 2.8 (Vertex Arrays), p. 21 (insert before section Transferring Array Elements, p. 21) "The command void VertexAttribDivisorEXT(uint index, uint divisor); modifies the rate at which generic vertex attributes advance, which is useful when rendering multiple instances of primitives in a single draw call (see DrawArraysInstancedEXT and DrawElementsInstancedEXT below). If is zero, the attribute at slot advances once per vertex. If is non-zero, the attribute advances once per instances of the primitives being rendered. An attribute is referred to as instanced if its value is non-zero. An INVALID_VALUE error is generated if is greater than or equal to the value of MAX_VERTEX_ATTRIBS." (replace all occurrences of "DrawArrays or DrawElements" with "DrawArrays, DrawElements, or the other Draw* commands", for example the first sentence of Transferring Array Elements, p. 21) "When an array element i is transferred to the GL by DrawArrays, DrawElements, or the other Draw* commands described below, each generic attribute is expanded to four components." (replace second through fourth paragraphs of Transferring Array Elements) "The command void DrawArraysOneInstance(enum mode, int first, sizei count, int instance); does not exist in the GL, but is used to describe functionality in the rest of this section. This command constructs a sequence of geometric primitives by successively transferring elements for vertices. Elements through + − 1 of each enabled non-instanced array are transferred to the GL. specifies what kind of primitives are constructed, as defined in section 2.6.1. If an enabled vertex attribute array is instanced (it has a non-zero as specified by VertexAttribDivisorEXT), the element that is transferred to the GL, for all vertices, is given by: floor(instance / divisor) If an array corresponding to a generic attribute is not enabled, then the corresponding element is taken from the current generic attribute state (see section 2.7). Otherwise, if an array is enabled, the corresponding current generic attribute value is unaffected by the execution of DrawArraysOneInstance. Specifying < 0 results in undefined behavior. Generating the error INVALID_VALUE is recommended in this case. The command void DrawArrays(enum mode, int first, sizei count); is equivalent to the command sequence DrawArraysOneInstance(mode, first, count, 0); The command void DrawArraysInstancedEXT(enum mode, int first, sizei count, sizei instanceCount); behaves identically to DrawArrays except that instances of the range of elements are executed and the value of advances for each iteration. Those attributes that have non-zero values for , as specified by VertexAttribDivisorEXT, advance once every instances. It has the same effect as: if (mode, count, or instanceCount is invalid) generate appropriate error else { for (i = 0; i < instanceCount; i++) { DrawArraysOneInstance(mode, first, count, i); } } The command void DrawElementsOneInstance(enum mode, sizei count, enum type, const void *indices, int instance); does not exist in the GL, but is used to describe functionality in the rest of this section. This command constructs a sequence of geometric primitives by successively transferring elements for vertices. The ith element transferred by DrawElementsOneInstance will be taken from element [i] of each enabled non-instanced array, where specifies the location in memory of the first index of the element array being specified. must be one of UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT indicating that the index values are of GL type ubyte, ushort, or uint respectively. specifies what kind of primitives are constructed, as defined in section 2.6.1. If an enabled vertex attribute array is instanced (it has a non-zero as specified by VertexAttribDivisorEXT), the element that is transferred to the GL, for all vertices, is given by: floor(instance / divisor) If an array corresponding to a generic attribute is not enabled, then the corresponding element is taken from the current generic attribute state (see section 2.7). Otherwise, if an array is enabled, the corresponding current generic attribute value is unaffected by the execution of DrawElementsOneInstance. The command void DrawElements(enum mode, sizei count, enum type, const void *indices); behaves identically to DrawElementsOneInstance with the parameter set to zero; the effect of calling DrawElements(mode, count, type, indices); is equivalent to the command sequence: if (mode, count or type is invalid) generate appropriate error else DrawElementsOneInstance(mode, count, type, indices, 0); The command void DrawElementsInstancedEXT(enum mode, sizei count, enum type, const void *indices, sizei instanceCount); behaves identically to DrawElements except that instances of the set of elements are executed and the value of advances between each set. Instanced attributes are advanced as they do during execution of DrawArraysInstancedEXT. It has the same effect as: if (mode, count, instanceCount, or type is invalid) generate appropriate error else { for (int i = 0; i < instanceCount; i++) { DrawElementsOneInstance(mode, count, type, indices, i); } } (append to first sentence of last paragraph of Transferring Array Elements) "..., and n integers representing vertex attribute divisors." (append to last sentence of last paragraph of Transferring Array Elements) "..., the divisors are each zero." Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State Requests) In section 6.1.8, add to the list of pnames accepted by GetVertexAttrib*v: VERTEX_ATTRIB_ARRAY_DIVISOR_EXT Dependencies on OES_element_index_uint If OES_element_index_uint is not supported, remove references to UNSIGNED_INT as a valid for DrawElements*. Errors INVALID_VALUE is generated by VertexAttribDivisorEXT if is greater than or equal to MAX_VERTEX_ATTRIBS. INVALID_ENUM is generated by DrawElementsInstancedEXT if is not one of UNSIGNED_BYTE, UNSIGNED_SHORT or UNSIGNED_INT. INVALID_VALUE is generated by DrawArraysInstancedEXT if , , or is less than zero. INVALID_VALUE is generated by DrawElementsInstancedEXT if or is less than zero. INVALID_ENUM is generated by DrawArraysInstancedEXT or DrawElementsInstancedEXT if is not one of the kinds of primitives accepted by DrawArrays and DrawElements. New State Changes to table 6.2, p. 136 (Vertex Array Data) Initial Get Value Type Get Command Value Description Sec. --------- ---- ----------- ------- ----------- ---- VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 16* x Z+ GetVertexAttribiv 0 Vertex attrib array 2.8 instance divisor Issues None Revision History #1 November 11 2012, Abhijit Bhelande and Benj Lipchak - initial conversion from ARB to APPLE for ES2 #2 June 26 2013, Benj Lipchak - promotion from APPLE to EXT