Must shader uniforms (like the projection matrix that does not change very often) be uploaded once per vertex array object? Or does the bound variables have nothing to do with the active VAO, and the shader are only connected with the vertex object when drawn?
(E.g. does a shader stand for its own until vertex data is sent to it via a draw command, or is it somehow bound to the vao created?)
Uniforms have nothing to do with VAOs; they're completely different data. Uniforms are program object state. VAOs are entirely separate objects.
As with most state, uniform data set into a program will remain that way until you change it.
Related
In my specific case, I'm trying to bind a vertex buffer object into a uniform buffer object.
For more details, in my opaque object rendering pipeline in deferred shading, I create a G buffer then render light volumes one point light at a time using a light vbo.
I then need all these lights as a ubo available for iteration in forward rendering for translucent objects.
Texture objects are directly and forever associated with the target type with which they are first used. This is not the case for buffer objects.
There is no such thing as a "vertex buffer object" or a "uniform buffer object" (ignore the name of the corresponding extensions). There are only "buffer objects", which can be used for various OpenGL operations, like providing arrays of vertex data, or the storage for uniform blocks, or any number of other things. It is 100% fine to use a buffer as a source for vertex data, then use the same buffer (and same portion of that buffer) as a source for uniform data.
When a texture (2D) is supplied to a shader as a 'uniform' input, it is first uploaded to OpenGL using glTexImage2D() and then using glUniform1i() it is associated to shader uniform.
eg code :
Texture data
glTexImage2D(): is used to transfer texture data to the server side.
glGetUniformLocation(): is used to access shader uniform handle.
glUniform1i(): associates the data pointed by texture unit to the shader 'uniform' input.
but when we pass matrix (eg matrix4x4) to a shader as a 'uniform' input, when don't use any specific function to upload it to OpenGL. We just used glUniform..() to associate the data with the shader input which we also used in the case of associating texture data that is already present in OpenGL memory.
Matrix data
glGetUniformLocation(): to access shader uniform handle
glUniformMatrix4fv(): to associate matrix data to the shader uniform input.
Where does the matrix data live in each step in the process of passing it to a shader as a uniform input?
Does matrix data always live on client side/ CPU accessible memory and fetched every frame by server side?
If it is uploaded to OpenGL:
which step/function call uploads the data?
where does the data live in OpenGL memory?
how its memory location is pointed?
associates the data pointed by texture unit to the shader 'uniform' input.
No, this sets the "value" of the uniform variable (uniforms are not "inputs") to be the texture unit index where the sampler can find the texture that this uniform represents. The value is just a value; it is no different from the way you set the value of any uniform variable.
It's just that in GLSL, you don't access the "value" of the sampler uniform variable; you use texture accessing functions on it instead.
If you change the texture bound to that texture unit before you render with the shader, then the shader will see the new texture. It is not directly associated with any texture; the shader is only associated with a texture unit index.
Where does the matrix data live in each step in the process of passing it to a shader as a uniform input?
There's only one step in the "process" of passing uniform values to shaders. You make a glUniform* call, and the "process" is complete; the particular uniform now has that particular value.
This is no different from setting pretty much any state in OpenGL. If you make a glTexParameter call, that performs the "process" of setting the state value you pass into the proper place in the OpenGL texture object.
Does matrix data always live on client side/ CPU accessible memory and fetched every frame by server side?
It lives wherever the implementation chooses to put it. However, all OpenGL functions are finished with the pointers you pass them by the time they return. So you don't have to worry about your CPU memory.
I am want to know if the uniform and vertex attribute variable values remain if the shader program is unbound and then rebound
Basically I want to ask this question Do uniform values remain in GLSL shader if unbound?. But I want to know if this applies to both uniforms and attribure variables?
If I do this
glUseProgram(shader1);
// Now set uniforms.
glUniform4fv(m_uniforms[COLOR_HANDLE], 1, color.AsFloat());
glUniformMatrix4fv(m_uniforms[MVP_HANDLE], 1, false, matrix);
glBindBuffer(GL_ARRAY_BUFFER, bufferIndex);
glEnableVertexAttribArray(m_attributes[POSITION_HANDLE1]);
glEnableVertexAttribArray(m_attributes[POSITION_HANDLE2]);
glVertexAttribPointer(m_attributes[POSITION_HANDLE], 3, GL_FLOAT, false, 3 * sizeof(GLfloat), 0);
Now save the current program, vao, vbo binded.
Then use second program
glUseProgram(shader2);
//bind some new vao, vbo, set some uniform, vertex attribute variable.
element.draw();
Then again use the first shader program. Rebind the vbo, vao
glUseProgram(shader1); //Here, do the uniforms and attributes set in first shader program remain?
element.draw();
Does this mean that complete state is restored and draw calls will work. I think this should work if the uniforms and attribute values are retained. So when I restore the client program with glUseProgram, all uniforms and attributes set by client will be restored.
If not, then how can I save complete state. Onething is client has to set them again. but if that is not an option, what is other way around. How can I save the full state and restore it later. Is it even possible ?
PS: I need to do it for opengl 2.0, opengl 3.2+, opengl es 2.0, opengles 3.0
Uniforms
Uniforms are part of the shader program object. Thus they keep saved even when the program object is unbound. The OpenGL 4.5 Specification says to this:
7.6 Uniform Variables
Uniforms in the default uniform block, except for subroutine uniforms, are
program object-specific state. They retain their values once loaded, and their values
are restored whenever a program object is used, as long as the program object has
not been re-linked.
Attributes
Attribute bindings are part of the VAO state. When no VAO is bound then the default VAO is used (which is btw. not allowed in Core Profile). When using VAOs, restoring attribute bindings is quite simple since it is sufficient to rebind the VAO. In the other case, I would have a look at the "Associated Gets" section here.
I am writing an OpenGL3+ application and have some confusion about the use of VAOs. Right now I just have one VAO, a normalised quad set around the origin. This single VAO contains 3 VBOs; one for positions, one for surface normals, and one GL_ELEMENT_ARRAY_BUFFER for indexing (so I can store just 4 vertices, rather than 6).
I have set up some helper methods to draw objects to the scene, such as drawCube() which takes position and rotation values and follows the procedure;
Bind the quad VAO.
Per cube face:
Create a model matrix that represents this face.
Upload the model matrix to the uniform mat4 model vertex shader variable.
Call glDrawElements() to draw the quad into the position for this face.
I have just set about the task of adding per-cube colors and realised that I can't add my color VBO to the single VAO as it will change with each cube, and this doesn't feel right.
I have just read the question; OpenGL VAO best practices, which tells me that my approach is wrong, and that I should use more VAOs to save the work of setting the whole scene up every time.
How many VAOs should be used? Clearly my approach of having 1 is not optimal, should there be a VAO for every static surface in the scene? What about ones that move?
I am writing to a uniform variable for each vertex, is that correct? I read that uniform shader variables should not change mid-frame, if I am able to write different values to my uniform variable, how do uniforms differ from simple in variables in a vertex shader?
Clearly my approach of having 1 is not optimal, should there be a VAO for every static surface in the scene?
Absolutely not. Switching VAOs is costly. If you allocate one VAO per object in your scene, you need to switch the VAO before rendering such objects. Scale that up to a few hundred or thousand objects currently visible and you get just as much VAO changes. The questions is, if you have multiple objects which share a common memory layout, i.e. sizes/types/normalization/strides of elements are the same, why would you want to define multiple VAOs that all store the same information? You control the offset where you want to start pulling vertex attributes from directly with a corresponding draw call.
For non-indexed geometry this is trivial, since you provide a first (or an array of offsets in the multi-draw case) argument to gl[Multi]DrawArrays*() which defines the offset into the associated ARRAY_BUFFER's data store.
For indexed geometry, and if you store indices for multiple objects in a single ELEMENT_ARRAY_BUFFER, you can use gl[Multi]DrawElementsBaseVertex to provide a constant offset for indices or manually offset your indices by adding a constant offset before uploading them to the buffer object.
Being able to provide offsets into a buffer store also implies that you can store multiple distinct objects in a single ARRAY_BUFFER and corresponding indices in a single ELEMENT_ARRAY_BUFFER. However, how large buffer objects should be depends on your hardware and vendors differ in their recommendations.
I am writing to a uniform variable for each vertex, is that correct? I read that uniform shader variables should not change mid-frame, if I am able to write different values to my uniform variable, how do uniforms differ from simple in variables in a vertex shader?
First of all, a uniforms and shader input/output variables declared as in/out differ in various instances:
input/output variables define an interface between shader stages, i.e. output variables in one shader stage are backed by a corresponding and equally named input variable in the following stage. A uniform is available in all stages if declared with the same name and is constant until changed by the application.
input variables inside a vertex shader are filled from an ARRAY_BUFFER. Uniforms inside a uniform block are backed a UNIFORM_BUFFER.
input variables can also be written directly using the glVertexAttrib*() family of functions. single uniforms are written using the glUniform*() family of functions.
the values of uniforms are program state. the values of input variables are not.
The semantic difference should also be obvious: uniforms, as their name suggests, are usually constant among a set of primitives, whereas input variables usually change per vertex or fragment (due to interpolation).
EDIT: To clarify and to factor in Nicol Bolas' remark: Uniforms cannot be changed by the application for a set of vertices submitted by a single draw call, neither can vertex attributes by calling glVertexAttrib*(). Vertex shader inputs backed by a buffer objects will change either once per vertex or at some specific rate set by glVertexAttribDivisor.
EDIT2: To clarify how a VAO can theoretically store multiple layouts, you can simply define multiple arrays with different indices but equal semantics. For instance,
glVertexAttribPointer(0, 4, ....);
and
glVertexAttribPointer(1, 3, ....);
could define two arrays with indices 0 and 1, component sized 3 and 4 and both refer to position attributes of vertices. However, depending on what you want to render, you can bind a hypothetical vertex shader input
// if you have GL_ARB_explicit_attrib_location or GL3.3 available, use explicit
// locations
/*layout(location = 0)*/ in vec4 Position;
or
/*layout(location = 1)*/ in vec3 Position;
to either index 0 or 1 explicitly or glBindAttribLocation() and still use the same VAO. AFAIK, the spec says nothing about what happens if an attribute is enabled but not sourced by the current shader but I suspect implementation to simply ignore the attribute in that case.
Whether you source the data for said attributes from the same or a different buffer object is another question but of course possible.
Personally I tend to use one VBO and VAO per layout, i.e. if my data is made up of an equal number of attributes with the same properties, I put them into a single VBO and a single VAO.
In general: You can experiment with this stuff a lot. Do it!
I have a fragment shader that uses a few uniforms which are set on a per-object basis. Is there a way to store these uniforms on the graphics card somehow? I've heard of (but cannot find a tutorial for) vertex buffer objects--is there a trick to storing the information in there, so that I don't need to re-set the variables every time I draw a new object?
Each object has very few vertices, but they are completely static.
There are indeed Uniform Buffer Objects in later versions of OpenGL http://www.opengl.org/wiki/Uniform_Buffer_Object
If you use the same shader program ID for all the objects, then you can just set the uniforms once before you render your objects as their value will stay the same until you set them again. So e.g. in your code where you load and compile the shader source, set the uniform variables that are common for all the objects, then render your objects, only setting the per-object uniforms.
The uniform buffer idea in one of the answers can be used if you have different shaders for different objects but you want to share some data between them. This is not necessary in your case as you mention a single shader.