3

After a lot of searching, I still am confused about what the glVertexAttrib... functions (glVertexAttrib1d, glVertexAttrib1f, etc.) do and what their purpose is.

My current understanding from reading this question and the documentation is that their purpose is to somehow set a vertex attribute as constant (i.e. don't use an array buffer). But the documentation also talks about how they interact with "generic vertex attributes" which are defined as follows:

Generic attributes are defined as four-component values that are organized into an array. The first entry of this array is numbered 0, and the size of the array is specified by the implementation-dependent constant GL_MAX_VERTEX_ATTRIBS. Individual elements of this array can be modified with a glVertexAttrib call that specifies the index of the element to be modified and a value for that element.

It says that they are all "four-component values", yet it is entirely possible to have more or less components than that in a vertex attribute.

What is this saying exactly? Does this only work for vec4 types? What would be the index of a "generic vertex attribute"? A clear explanation is probably what I really need.

  • @BDL That is similar, but it doesn’t fully answer how you could specify a value for types that have more than four-components (`mat4` for example). –  Aug 07 '18 at 10:41
  • @BDL Are you sure? The [docs](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttrib.xhtml) say that you can. Also, I’m pretty sure this isn’t for OpenGL ES; the docs list the functions under normal OpenGL. –  Aug 07 '18 at 10:49
  • 2
    @BDL: in the spec, "generic" just means that it is a user-defined attribute in the vertex shader, and not one of the legacy deprecated built-ins like `glVertex`,`glNormal`,`glTexCoord` and so on. This distinction has nothing to do with vertex attrtibute or not. The spec uses the term "current values" to refer to the non-array values of these attributes (which is a terminological remnant form legacy begin/end drawing, where you always updated the current values and DrawArrays was specified in terms of begin/end execution) – derhass Aug 07 '18 at 13:03

1 Answers1

6

In OpenGL, a vertex is specified as a set of vertex attributes. With the advent of the programmable pipleine, you are responsible for writing your own vertex processing functionality. The vertex shader does process one vertex, and gets this specific vertex' attributes as input.

These vertex attributes are called generic vertex attributes, since their meaning is completely defined by you as the application programmer (in contrast to the legacy fixed function pipeline, where the set of attributes were completely defined by the GL).

The OpenGL spec requires implementors to support at least 16 different vertex attributes. So each vertex attribute can be identified by its index from 0 to 15 (or whatever limit your implementation allows, see glGet(GL_MAX_VERTEX_ATTRIBS,...)).

A vertex attribute is conceptually treated as a four-dimensional vector. When you use less than vec4 in a shader, the additional elements are just ignored. If you specify less than 4 elements, the vector is always filled to the (0,0,0,1), which makes sense for both RGBA color vectors, as well as homogenous vertex coordinates.

Though you can declare vertex attributes of mat types, this will just be mapped to a number of consecutive vertex attribute indices.

The vertex attribute data can come from either a vertex array (nowadays, these are required to lie in a Vertex Buffer Object, possibly directly in VRAM, in legacy GL, they could also come from the ordinary client address space) or from the current value of that attribute. You enable the fetching from attribute arrays via glEnableVertexAttribArray.If a vertex array for a particular attribute you access in your vertex shader is enabled, the GPU will fetch the i-th element from that arry when processing vertex i. FOr all other attributes you access, you will get the current value for that array.

The current value can be set via the glVertexAttrib[1234]* family of GL functions. They cannot be changed durint the draw call, so they remain constant during the whole draw call - just like uniform variables.

One important thing worth noting is that by default, vertex attributes are always floating point, ad you must declare in float/vec2/vec3/vec4 in the vertex shader to acces them. Setting the current value with for example glVertexAttrib4ubv or using GL_UNISGNED_BYTE as the type parameter of glVertexAttribPointer will not change this. The data will be automatically converted to floating-point.

Nowadays, the GL does support two other attribute data types, though: 32 bit integers, and 64 bit double precision floating-point values. YOu have to declare them as int/ivec*, uint/uvec* or double/dvec* respectively in the shader, and you have to use completely separate functions when setting up the array pointer or current values: glVertexAttribIPointer and glVertexAttribI* for signed/unsigned integers and glVertexAttribLPointer and glVertexAttribL* for doubles ("long floats").

derhass
  • 43,833
  • 2
  • 57
  • 78
  • 1
    I never knew that each attribute was internally a `vec4`... This made a lot of sense, thanks! –  Aug 07 '18 at 18:14
  • “When you use less than vec4 in a shader, the additional elements are just ignored.” I think the phrase "less than" should be "more than". – Evan Aug 22 '19 at 02:18
  • @Evan no. "less than" is exactly what I meant there. (and "more than" doesn't make any sense because there does not even exist anything more than `vec4` for each attribute slot to begin with) – derhass Aug 22 '19 at 17:49
  • I get what you mean. You mean given parameters are more than asked, then additional elements are ignored. Right? – Evan Aug 27 '19 at 07:32
  • @Evan Actually I mean it in a more general way. I wrote "A vertex attribute is conceptually treated as a four-dimensional vector." Always! No matter how many components you supply in your vertex array, and no matter how many components you consume in the shader. That was the key point I made in the whole paragraph. The scenario "the shader uses more / less components than supplied in the array" is just a distraction, as there is no direct connection between these two sides (on a conceptual level). – derhass Aug 27 '19 at 12:35