Using Multiple Vertex Shader Inputs

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

As you have learned, you can get OpenGL to feed data into your vertex shaders and use data you’ve placed in buffer objects. You can also declare multiple inputs to your vertex shaders, and assign each one a unique location that can be used to refer to it. Combining these things together means that you can get OpenGL to provide data to multiple vertex shader inputs simultaneously. Consider the input declarations to a vertex shader shown in Listing 5.6.

You've learned how to use the input data buffer is used for the shader, you can also define multiple input your vertex shader attributes. The combination of these things all the time, it means you can simultaneously give shader input multiple sets of data. Let's look at the code in Listing 5.6

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
Listing 5.6: Declaring two inputs to a vertex shader

Listing 5.6 declare the two input data of the vertex shader

If you have a linked program object whose vertex shader has multiple inputs, you can determine the locations of those inputs by calling

If you generate a GPU program how a set of input data, then you can use the following API to get a certain location bind input data.

GLint glGetAttribLocation(GLuint program,const GLchar * name);
Here, program is the name of the program object containing the vertex shader and name is the name of the vertex attribute. In our example declarations of Listing 5.6, passing "position" to glGetAttribLocation() will cause it to return 0, and passing "color" will cause it to return 1. Passing something that is not the name of a vertex shader input will cause glGetAttribLocation() to return −1. Of course, if you always specify locations for your vertex attributes in your shader code, then glGetAttribLocation() should return whatever you specified. If you don’t specify locations in shader code, OpenGL will assign locations for you, and those locations will be returned by glGetAttribLocation(). There are two ways to connect vertex shader inputs to your application’s data, referred to as separate attributes and interleaved attributes. When attributes are separate, they are located either in different buffers or at least at different locations in the same buffer. For example, if you want to feed data into two vertex attributes, you could create two buffer objects, bind each to a different vertex buffer binding with a call to glVertexArrayVertexBuffer(), and then specify the two indices of the two vertex buffer binding points that you used when you call glVertexArrayAttribBinding() for each. Alternatively, you could place the data at different offsets within the same buffer, bind it to a single vertex buffer binding with one call to glVertexArrayVertexBuffer(), and then call glVertexArrayAttribBinding() for both attributes, passing the same binding index to each. Listing 5.7 shows this approach.

The first parameter is the GPU program, the second parameter is the name of vertex attributes. In our code in Listing 5.6, the name of this parameter if pass position, then the API returns 0 if pass color, then the API will return 1. If you pass a name that does not exist, then the API returns -1. of course, if you are in the shader code to define the attributes of the binding location, then you will always get you set up with those positions consistent return value. If you do not set the binding position of the attribute in the shader, OpenGL will then allocate these positions for you, you can get to those positions by this API. There are two ways you can transfer data to the shader attributes, one is separate, the other called interleaved. When using separate transmission of data, your data will be stored in different buffer objects, the same or different locations stored in a buffer object inside. For example, you want to transfer data to two properties in the shader, you can create two buffer object, then call glVertexArrayVertexBuffer bind to their respective binding to a different node of the buffer, and then specify the two as they were by glVertexArrayAttribBingding they use an index. Alternatively, you can put the data in different location in the same buffer, and then use the same method as above to do with it. Listing 5.7 shows how to do these operations

GLuint buffer[2];
GLuint vao;
static const GLfloat positions[] = { ... };
static const GLfloat colors[] = { ... };
// Create the vertex array object
glCreateVertexArrays(1, &vao)
// Get create two buffers
glCreateBuffers(2, &buffer[0]);
// Initialize the first buffer
glNamedBufferStorage(buffer[0], sizeof(positions), positions, 0);
// Bind it to the vertex array - offset zero, stride = sizeof(vec3)
glVertexArrayVertexBuffer(vao, 0, buffer[0], 0, sizeof(vmath::vec3));
// Tell OpenGL what the format of the attribute is
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
// Tell OpenGL which vertex buffer binding to use for this attribute
glVertexArrayAttribBinding(vao, 0, 0);
// Enable the attribute
glEnableVertexArrayAttrib(vao, 0);
// Perform similar initialization for the second buffer
glNamedBufferStorage(buffer[1], sizeof(colors), colors, 0);
glVertexArrayVertexBuffer(vao, 1, buffer[1], 0, sizeof(vmath::vec3));
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 1, 1);
glEnableVertexAttribArray(1);
Listing 5.7: Multiple separate vertex attributes

Listing 5.7: Incoming data for the vertex attributes separate ways

In both cases of separate attributes, we have used tightly packed arrays of data to feed both attributes. This is effectively structure-of-arrays (SoA) data. We have a set of tightly packed, independent arrays of data. However, it’s also possible to use an array of-structures (AoS) form of data. Consider how the following structure might represent a single vertex:

Two kinds of separate data transmission way we have used a very compact data block. Of course, you can also use the AOS, we take a look at this structure below.

struct vertex
{
// Position
float x;
float y;
float z;
// Color
float r;
float g;
float b;
};
Now we have two inputs to our vertex shader (position and color) interleaved together in a single structure. Clearly, if we make an array of these structures, we have an AoS layout for our data. To represent this with calls to glVertexArrayVertexBuffer(), we have to use its stride parameter. The stride parameter tells OpenGL how far apart in bytes the beginning of each vertex’s data is. If we leave it as 0, OpenGL will use the same data for every vertex. However, to use the vertex structure declared above, we can simply use sizeof(vertex) for the stride parameter and everything will work out. Listing 5.8 shows the code to do this

Now we use interleaved way of two properties shader input data. Obviously, if we have a set of such types of data structures, we are using the AOS data block. We use glVertexArrayVertexBuffer to set the time, we need to use it in stride parameters. stride parameter tells the interval between the two OpenGL vertex, if we write this parameter 0, then all the vertices using the same data. Using this data structure is very simple, we directly use the sizeof (vertex) to be assigned to stride parameters. Listing 5.8 shows the sample code in this manner just discussed

GLuint vao;
GLuint buffer;
static const vertex vertices[] = { ... };
// Create the vertex array object
glCreateVertexArrays(1, &vao);
// Allocate and initialize a buffer object
glCreateBuffers(1, &buffer);
glNamedBufferStorage(buffer, sizeof(vertices), vertices, 0);
// Set up two vertex attributes - first positions
glVertexArrayAttribBinding(vao, 0, 0);
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, offsetof(vertex,x));
glEnableVertexArrayAttrib(0);
// Now colors
glVertexArrayAttribBinding(vao, 1, 0);
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, GL_FALSE, offsetof(vertex,
r));
glEnableVertexArrayAttrib(1);
// Finally, bind our one and only buffer to the vertex array object
glVertexArrayVertexBuffer(vao, 0, buffer);
Listing 5.8: Multiple interleaved vertex attributes

Listing 5.8: Using the interleaved mode is more attributes of the input data shader

After executing the code in Listing 5.8, you can bind the vertex array object and start pulling data from the buffers bound to it. After the vertex format information has been set up with calls to glVertexArrayAttribFormat (), you can change the vertex buffers that are bound with further calls to glVertexArrayAttribBinding () . if you want to render a lot of geometry stored in different buffers but with similar vertex formats, simply call glVertexArrayAttribBinding () to switch buffers and start drawing from them.
when finished executing the code in Listing 5.8 after that, you can hold it up to paint. After using glVertexArrayAttribFormat set up the buffer, you can call glVertexArrayAttribBinding to modify the current buffer object. If you want to render many similarities memory, but stored in the buffer of different geometric shapes, you can simply call glVertexArrayAttribBinding to switch the input buffer, then call the drawing function.

Loading Objects from Files (loaded from a file object)

As you can see, you could potentially use a large number of vertex attributes in a single vertex shader. As we progress through various techniques, you will see that we’ll regularly use four or five vertex attributes, and possibly more. Filling buffers with data to feed all of these attributes and then setting up the vertex array object and all of the vertex attribute pointers can be a chore. Further, encoding all of your geometry data directly in your application isn’t practical for anything but the simplest models. Therefore, it makes sense to store model data in files and load it into your application. There are plenty of model file formats out there, and most modeling programs support several of the more common formats.

As you can see, you may need to use a large number of vertex attributes in the shader. With further study, we often need to often use four or five vertex attributes, maybe more. Hand shop and go live this very troublesome. In addition, these handwritten geometry data directly in the application, and you will endocrine disorders. Therefore, the model file is loaded from the selection looks very good. There are many types of models, many modeling software supports some of the more common model format.

For the purpose of this book, we have devised a simple object file definition called an .SBM file, which stores the information we need without being either too simple or too overly engineered. Complete documentation for the format is found in Appendix B, “The SBM File Format.” The sb7 framework also includes a loader for this model format, called sb7::object. To load an object file, create an instance of sb7::object and call its load function as follows:

In order to learn, we have to format using the model of a suffix called SBM. The full format of the format described in Appendix B. Framework code we provide the code to load the tutorial format, sb7 :: object. You can load a sbm by the following code model
SB7 :: Object my_object;
my_object.load ( "filename.sbm");
the If the this IS Operation successful, at The Model by Will BE INTO loaded at The instance of SB7 :: Object and you by Will be able to render it. During loading , the class will create and set up the object's vertex array object and then configure all of the vertex attributes contained in the model file. The class also includes a render function that binds the object's vertex array object and calls the appropriate drawing command. For example , calling

If the load is successful, then you can render it. When loaded, this class will configure all of the VAO and vertex attributes. This class also includes rendering API interface, after which bound VAO, then call the drawing function. For example follows

my_object.render();
will render a single copy of the object with the current shaders. In many of the examples in the remainder of this book, we’ll simply use our object loader to load object files (several of which are included with the book’s source code) and render them.

Above the interface will use the current shader to render the model. In the remainder of this book, we will use the model classes to load and render models.

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/2430889