Uniforms (uniform variable)

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

Although not really a form of storage, uniforms are an important way to get data into shaders and to hook them up to your application. You have already seen how to pass data to a vertex shader using vertex attributes, and you have seen how to pass data from stage to stage using interface blocks. Uniforms allow you to pass data directly from your application into any shader stage. There are two flavors of uniforms, which differ based on how they are declared. The first are uniforms declared in the default block and the second are uniform blocks, whose values are stored in buffer objects. We will discuss both now.

uniform is an important way of passing parameters to the shader. You already know how to transfer vertex shader how to pass data between the data and the shader. uniform allows you to directly from the application to send parameter data to any stage of the shader. There are two types of uniform, one is the default block, one is uniform blocks. We will discuss both storage.

Default Block Uniforms

While attributes are needed for per-vertex positions, surface normals, texture coordinates, and so on, a uniform is how we pass data into a shader that stays the same —is uniform—for an entire primitive batch or longer. Probably the single most common uniform for a vertex shader is the transformation matrix. We use transformation matrices in our vertex shaders to manipulate vertex positions and other vectors. Any shader variable can be specified as a uniform, and uniforms can be in any of the shader stages (even though we discuss only vertex and fragment shaders in this chapter). Making a uniform is as simple as placing the keyword uniform at the beginning of the variable declaration:

Each vertex has such properties position, normals, texture coordinates, etc.. The uniform is a drawcall terms for all stages of the drawcall These values ​​uniform variables use the same set of values. For example, the transformation matrix is ​​the most common of uniform variables. Any shader variables can be used to uniform way to affirm that any shader stage can be used uniform. Affirming uniform is very simple to use uniform in front of the modified variables:

uniform float fTime;
uniform int iIndex;
uniform vec4 vColorValue;
uniform mat4 mvpMatrix;
Uniforms are always considered to be; and they cannot be assigned values by your shader code. However, you can initialize their default values at declaration time in a manner such as this:

uniform variables can not be assigned in the shader, but you can at any course in the shader declared it time to give it a default value:

uniform int answer = 42;
If you declare the same uniform in multiple shader stages, each of those stages will “see” the same value of that uniform.

If you use the same uniform shader variables in different stages, each shader uniform value in use are exactly the same.

Arranging Your Uniforms (manage your uniform variable)

After a shader has been compiled and linked into a program object, you can use one of the many functions defined by OpenGL to set the shader’s values (assuming you don’t want the defaults defined by the shader). Just as with vertex attributes, these functions refer to uniforms by their location within their program object. It is possible to specify the locations of uniforms in your shader code by using a location layout qualifier. When you do this, OpenGL will try to assign the locations that you specify to the uniforms in your shaders. The location layout qualifier looks like this:

Once you have created a GPU program, you can use the OpenGL API to set the value of the uniform variable. Like attributes, setting uniform when we need to set their position through uniform variables. You can specify a binding to the modifier layout uniform variables in shader position to go, when you use a layout modifier after, OpenGL will try to use these bindings location you specify:

layout (location = 17) uniform vec4 myUniform;
Notice the similarity between the location layout qualifer for uniforms and the one we’ve used for vertex shader inputs. In this case, myUniform will be allocated to location 17. If you don’t specify a location for your uniforms in your shader code, OpenGL will automatically assign locations to them for you. You can figure out which locations were assigned by calling the glGetUniformLocation() function, whose prototype is

We note that in this way the property almost. The above code to myUniform this variable specifies the binding location for shader 17. If you do not specify the location of these bindings, then OpenGL is automatically assigned position to them. You can use glGetUniformLocation to get to these locations.

GLint glGetUniformLocation(GLuint program,const GLchar* name);
This function returns a signed integer that represents the location of the variable named by name in the program specified by program. For example, to get the location of a uniform variable named vColorValue, we would do something like this:

The first parameter is the GPU program, and the second parameter is the name of the uniform variable. This API returns a signed integer, is the digital representation of the position variable, the following sample code to obtain uniform vColorValue this position variables:

GLint iLocation = glGetUniformLocation(myProgram, "vColorValue");
In the previous example, passing "myUniform" to glGetUniformLocation() would result in the value 17 being returned. If you know a priori where your uniforms are because you assigned locations to them in your shaders, then you don’t need to find them and you can avoid the calls to glGetUniformLocation(). This is the recommended way of doing things.

In the previous example, the position 17 is myUniform. If you know in advance the location of these your uniform, you will not have to call the API.

If the return value of glGetUniformLocation() is −1, it means the uniform name could not be located in the program. You should bear in mind that even if a shader compiles correctly, a uniform name may still “disappear” from the program if it is not used directly in at least one of the attached shaders—even if you assign it a location explicitly in your shader source code. You do not need to worry about uniform variables being optimized away, but if you declare a uniform and then do not use it, the compiler will toss it out. Also, know that shader variable names are case sensitive, so you must get the case right when you query their locations

If the API returns the result is -1, then they said they could not find the uniform. Note that even if your shader syntax error-free, if the value of the uniform will not be directly or indirectly use, then this uniform will be optimized away the last of the shader, so this uniform just does not exist. Then it should be noted that, shader variables are case-sensitive, so you have the right to write the full name of the case.

Setting Uniforms (set uniform variable)

OpenGL supports a large number of data types both in the shading language and in the API. To to allow you to pass all this data around, it includes a huge number of functions just for setting the value of uniforms. A single scalar or vector data type can be set with any of the following variations on the glUniform*() function. For example, consider the following four variables declared in a shader:

There are a lot of API may be used to set the value of the uniform, they are beginning to glUniform, followed by subsequent data type. For example, following the shader uniform variables:

layout (location = 0) uniform float fTime;
layout (location = 1) uniform int iIndex;
layout (location = 2) uniform vec4 vColorValue;
layout (location = 3) uniform bool bSomeFlag;
To find and set these values in the shader, your C/C++ code might look something like this:

To set these variables, you can write code in C ++:

glUseProgram(myShader);
glUniform1f(0, 45.2f);
glUniform1i(1, 42);
glUniform4f(2, 1.0f, 0.0f, 0.0f, 1.0f);
glUniform1i(3, GL_FALSE);
Note that we used an integer version of glUniform() to pass in a bool value. Booleans can also be passed in as floats, with 0.0 representing false and any non-zero value representing true. The glUniform() function also comes in flavors that take a pointer, potentially to an array of values. These forms end in the letter v, indicating that they consume a vector, and take a count value that represents how many elements are in each array of x number of components, where x is the number at the end of the function name. For example, suppose you had this uniform with four components:

We note that we are using the API traditional values ​​of integer glUniform related to the Boolean type, you can also use the same type of floating-point, 0.0 is false, nonzero if true. glUniform series of API is classified, which is a kind of transmission array. This API ending with v, represents the incoming parameter is an array, and there are a number of values ​​expressed x elements in each array, where x is generally the tail of the API name. For example, we have an array of the following four elements:

uniform vec4 vColor;
In C/C++, you could represent this as an array of floats:

In C ++, you can use the following code represents a four-dimensional array each

GLfloat vColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
But this is a single array of four values, so passing it into the shader would look like this:

But this is only a four-dimensional vector, so we gave it a value that use C ++ code as follows:

glUniform4fv(iColorLocation, 1, vColor);
Now suppose you had an array of color values in your shader:

Now let's assume we have a set of color values ​​of:

uniform vec4 vColors[2];
Then in C++, you could represent the data and pass it in like this:

Way we express this value in C ++ as well as to the shader variable assignment is as follows:

GLfloat vColors[4][2] = { { 1.0f, 1.0f, 1.0f, 1.0f } ,
{ 1.0f, 0.0f, 0.0f, 1.0f } };
...
glUniform4fv(iColorLocation, 2, vColors);
At its simplest, you can set a single floating-point uniform like this:

The easiest, so you can be like the code below to float a uniform variable assignment:

GLfloat fValue = 45.2f;
glUniform1fv(iLocation, 1, &fValue);
Finally, we see how to set a matrix uniform. Shader matrix data types only come in the single- and double-precision floating-point variety, so we have far less variation. To set the values in uniform matrices, we call the glUniformMatrix() commands. In all of these functions, the variable count represents the number of matrices stored at the pointer parameter m (yes, you can have arrays of matrices!). The Boolean flag transpose is set to GL_FALSE if the matrix is already stored in column-major ordering (the way OpenGL prefers). Setting this value to GL_TRUE causes the matrix to be transposed when it is copied into the shader. This might be useful if you are using a matrix library that uses a row-major matrix layout instead (for example, some other graphics APIs use row-major ordering and you might want to use a library designed for one of them)

Finally, we see how to set up a matrix-type uniform. shader matrix data types only a single and double precision both. Set matrix, we use glUniformMatrix series of API. In all these functions, there is a count to indicate the number of matrices stored in the pointer m. Boolean parameter tells OpenGL need to transpose, if you are with us in OpenGL mathematics completion of person, you do not need is a matrix transpose.

In our tutorial, we are using this uniform mode of operation, because this model is common to the whole platform can be done. Second, our students can see, this book is not for the novice to see, it is to give people learned to read. You can try to recall the difference between our curriculum and this book.

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