Feeding Vertex Shaders from Buffers input data from the buffer to the shader

Monday to Friday, a day, 7 am Beijing time on time updates -

In Chapter 2, “Our First OpenGL Program,” you were briefly introduced to the vertex array object (VAO). During that discussion, we explained how the VAO represented the inputs to the vertex shader—though at the time, we didn’t use any real inputs to our vertex shaders and opted instead for hard-coded arrays of data. Then, in Chapter 3 we introduced the concept of vertex attributes, but we discussed only how to change their static values. Although the vertex array object stores these static attribute values for you, it can do a lot more. Before we can proceed, we need to create a vertex array object to store our vertex array state and bind it to our context so that we can use it:

In the second chapter, we have contact with VAO, and where we have explained how to VAO shader input data - the data although at that time we did not really use VAO but the use of hard-coded. In the third chapter, we introduced the concept of vertex attributes, but we just discussed how to change their static values. VAO can store not only those static properties for you, it can do more. Before we begin, we need to create an object of a VAO to store our vertex array state, and bind it to our context, so that we can use it

GLuint vao;
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);
Now that we have our VAO created and bound, we can start filling in its state. Rather than using hard-coded data in the vertex shader, we can instead rely entirely on the value of a vertex attribute and ask OpenGL to fill it automatically using the data stored in a buffer object that we supply. Each vertex attribute gets to fetch data from a buffer bound to one of several vertex buffer bindings. To set the binding that a vertex attribute uses to reference a buffer, call the glVertexArrayAttribBinding() function:

Now we have created VAO, we can do a major event. This time we use a buffer object provides data instead of using hard-coded. Each vertex attribute to be bound to the target node from the buffer up data acquisition. In order for vertex attributes know where to go to get data on that node buffers, we call to set glVertexArrayAttribBinding

void glVertexArrayAttribBinding(GLuint vaobj,GLuint attribindex,GLuint bindingindex);
The glVertexArrayAttribBinding() function tells OpenGL that when the vertex array object named vaobj is bound, the vertex attribute at the index specified in attribindex should source its data from the buffer bound at bindingindex. To tell OpenGL which buffer object our data is in and where in that buffer object the data resides, we use the glVertexArrayVertexBuffer() function to bind a buffer to one of the vertex buffer bindings. We use the glVertexArrayAttribFormat() function to describe the layout and format of the data, and finally we enable automatic filling of the attribute by calling glEnableVertexAttribArray(). The prototype of glVertexArrayVertexBuffer() is

This function tells OpenGL, when vaobj the VAO is bound to the context, to get data on that bindingindex vertex attributes on attribindex to buffer. In order to inform OpenGL which buffers the data and the data pattern in the memory of the buffer in, we use glVertexArrayVertexBuffer to set them. GlVertexArrayAttribFormat we use to describe the format of the data, that is, the distribution of memory friends. Students do not know the distribution of memory can look at our C ++ Tricks course, do not speak basic C ++ syntax, only to deepen the understanding of C ++ through some small examples. And finally, we call the function to start glEnableVertexAttribArray let OpenGL automatically go to the buffer where the data is sent to the shader processing in accordance with the mode set. glVertexArrayVertexBuffer function as follows:

void glVertexArrayVertexBuffer(GLuint vaobj,
GLuint bindingindex,
GLuint buffer,
GLintptr offset,
GLsizei stride);
Here, the first parameter is the vertex array object whose state you’re modifying. The second parameter, bindingindex, is the index of the vertex buffer, which matches the parameter sent to glVertexArrayAttribBinding(). The buffer parameter specifies the name of the buffer object that we’re binding. The last two parameters, offset and stride, tell OpenGL where in the buffer object the attribute data lies. offset says where the first vertex’s data starts and stride says how far apart each vertex is. Both are measured in bytes. Next, we have glVertexArrayAttribFormat(), whose prototype is

Here, the first parameter is the VAO, the second parameter is the index buffer object, that one correspondence with the index glVertexArrayAttribBinding set up inside. The third parameter is the buffer object. The last two parameters tell OpenGL memory offset and stride pattern of these data, offset data tells OpenGL starting position, between a stride tell OpenGL same attribute data interval, it is byte size.

void glVertexArrayAttribFormat(GLuint vaobj,
GLuint attribindex,
GLint size,
GLenum type,
GLboolean normalized,
GLuint relativeoffset);
For glVertexArrayAttribFormat(), the first parameter is again the vertex array whose state we’re modifying. attribindex is the index of the vertex attribute. You can define a large number of attributes as input to a vertex shader and then refer to them by their index, as explained in the “Vertex Attributes” section in Chapter 3. size is the number of components that are stored in the buffer for each vertex and type is the type of the data, which would normally be one of the types in Table 5.3.

The first parameter is glVertexArrayAttribFormat VAO, attribindex is the index of the vertex attributes. You can define a number of properties, and then try to refer them to the index. refers to the size parameter is the number of each vertex part, the type refers to the type of data, generally referred to those in Table 5.3.

The normalized parameter tells OpenGL whether the data in the buffer should be normalized (scaled between 0.0 and 1.0) before being passed to the vertex shader or if it should be left alone and passed as is. This parameter is ignored for floating-point data, but for integer data types, such as GL_UNSIGNED_BYTE or GL_INT, it is important. For example, if GL_UNSIGNED_BYTE data is normalized, it is divided by 255 (the maximum value representable by an unsigned byte) before being passed to a floating-point input to the vertex shader. The shader will therefore see values of the input attribute between 0.0 and 1.0. However, if the data is not normalized, it is simply cast to floating-point values and the shader will receive numbers between 0.0 and 255.0, even though the input to the vertex shader consists of floating-point data. The stride parameter tells OpenGL how many bytes are between the start of one vertex’s data and the start of the next, but you can set this parameter to 0 to let OpenGL calculate it for you based on the values of size and type. Finally, relative offset is the offset from the vertex’s data where the specific attribute’s data starts. This all seems pretty complex, but the pseudocode to compute the location in a buffer object is fairly simple:

normalized parameter tells OpenGL, whether data needs to be scaled to between 0 and 1 prior to transmitted shader. For GL_FLOAT type, this parameter will be ignored OpenGL, but for GL_UNSIGNED_BYTE or GL_INT type of data, this parameter is very important. For GL_UNSIGNED_BYTE, if your incoming data is 255, if need here to tell OpenGL scale, then the data is received by the shader 1.0, if you do not need to tell OpenGL scaling, the data received by the shader is such a 255.0 floating-point number. stride parameter tells OpenGL data interval. Finally, the relative offset data indicating a certain attribute data in the vertex all offset data. While these concepts may seem complex, but it calculates the offset pseudocode is simple:

location = binding[attrib.binding].memory + // Start of data store in memory
binding[attrib.binding].offset + // Offset of vertex attribute in buffer
binding[attrib.binding].stride vertex.index + // Start of this* vertex
vertex.relative_offset; // Start of attribute relative to vertex
Finally, glEnableVertexAttribArray() and the converse glDisableVertexAttribArray() have the prototypes:

Finally, the inverse operation glDisableVertexAttribArray glEnableVertexAttribArray and has the following functions stated:

void glEnableVertexAttribArray(GLuint index);
When a vertex attribute is enabled, OpenGL will feed data to the vertex shader based on the format and location information you’ve provided with glVertexArrayVertexBuffer() and glVertexArrayAttribFormat(). When the attribute is disabled, the vertex shader will be provided with the static information you provide with a call to glVertexAttrib(). Listing 5.4 shows how to use glVertexArrayVertexBuffer() and glVertexArrayAttribFormat() to configure a vertex attribute. Notice that we also call glEnableVertexArrayAttrib() after setting up the offset, stride, and format information. This tells OpenGL to use the data in the buffer to fill the vertex attribute rather than using data we provide through one of the glVertexAttrib() functions.

When a vertex attribute is enabled, OpenGL will be sent to the shader parameter according to those set up in front of us. If the vertex attribute is disabled, the OpenGL shader will then send you glVertexAttrib use some of those functions fixed data set. Listing 5.4 shows how to configure glVertexArrayAttribFormat glVertexArrayVertexBuffer and vertex attributes. Note that we set the same information offset, stride and format of the call glEnableVertexArrayAttrib. This is telling OpenGL, we use the data buffer as a shader input parameter Russian accession to the WTO glVertexAttrib those things function settings.

// First, bind a vertex buffer to the VAO
glVertexArrayVertexBuffer(vao, // Vertex array object
0, // First vertex buffer
binding
buffer, // Buffer object
0, // Start from the beginning
sizeof(vmath::vec4)); // Each vertex is one vec4
// Now, describe the data to OpenGL, tell it where it is, and turn on automatic
// vertex fetching for the specified attribute
glVertexArrayAttribFormat(vao, // Vertex array object
0, // First attribute
4, // Four components
GL_FLOAT, // Floating-point data
GL_FALSE, // Normalized - ignored for floats
0); // First element of the vertex
glEnableVertexArrayAttrib(vao, 0);
Listing 5.4: Setting up a vertex attribute

After Listing 5.4 has been executed, OpenGL will automatically fill the first attribute in the vertex shader with data it has read from the buffer that was bound to the VAO by glVertexArrayVertexBuffer(). We can modify our vertex shader to use only its input vertex attribute rather than a hardcoded array. This updated shader is shown in Listing 5.5.

When the list is performed 5.4 times, OpenGL will automatically use the data buffer glVertexArrayVertexBuffer binding on VAO's shader to fill in the first property. We now modify shader, let shader to use such input data, rather than hard-coded data. Listing 5.5 shows our latest version of the shader code how to write

#version 450 core
layout (location = 0) in vec4 position;
void main(void)
{
gl_Position = position;
}
Listing 5.5: Using an attribute in a vertex shader

As you can see, the shader of Listing 5.5 is greatly simplified over the original shader shown in Chapter 2. Gone is the hard-coded array of data. As an added bonus, this shader can be used with an arbitrary number of vertices. You can literally put millions of vertices’ worth of data into your buffer object and draw them all with a single command such as a call to glDrawArrays(). If you are done using data from a buffer object to fill a vertex attribute, you can disable that attribute again with a call to glDisableVertexAttribArray(), whose prototype is

As you can see, the list of 5.5 compared to the previous shader that much easier. Removed hard-coded data. The shader can use any number of vertices. It can be said, you can put millions of data in the buffer, and then use a drawing instruction will draw them out. If you are finished using the vertex buffer in the property, you can use glDisableVertexAttribArray disable this property.

void glDisableAttribArray(GLuint index);
Once you have disabled the vertex attribute, it goes back to being static and passing the value you specify with glVertexAttrib*() to the shader.

When you disable this property, call the shader future when the data is passed to the shader to use those data glVertexAttrib * function set up.

Translations of this day to get here, see you tomorrow, bye ~

Get the latest plot first time, please pay attention to the Eastern Han Dynasty academy and the heart of the public graphic No.

Han College, waiting for you to play Oh

Guess you like

Origin blog.51cto.com/battlefire/2430611