Opengl 3/4 : Can I bind the same buffer object to different targets - c++

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.

Related

Memory data flow for uniform variables?

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.

Bind an SSBO to a fragment shader

I have a an SSBO which stores vec4 colour values for each pixel on screen and is pre populated with values by a compute shader before the main loop.
I'm now trying to get this data onscreen which I guess involves using the fragment shader (Although if you know a better method for this I'm open to suggestions)
So I'm trying to get the buffer or at least the data in it to the fragment shader so that I can set the colour of each fragment to the corresponding value in the buffer but I cannot find any way of doing this?
I have been told that I can bind the SSBO to the fragment shader but I don't know how to do this? Other thoughts I had was somehow moving the data from the SSBO to a texture but I can't work that out either
UPDATE:
In response thokra's excellent answer and following comments here is the code to set up my buffer:
//Create the buffer
GLuint pixelBufferID;
glGenBuffers(1, &pixelBufferID);
//Bind it
glBindBuffer(GL_SHADER_STORAGE_BUFFER, pixelBufferID);
//Set the data of the buffer
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vec4) * window.getNumberOfPixels, new vec4[window.getNumberOfPixels], GL_DYNAMIC_DRAW);
//Bind the buffer to the correct interface block number
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferID);
Then I call the compute shader and this part works, I check the data has been populated correctly. Then in my fragment shader, just as a test:
layout(std430, binding=0) buffer PixelBuffer
{
vec4 data[];
} pixelBuffer
void main()
{
gl_FragColor = pixelBuffer.data[660000];
}
What I've noticed is that it seems to take longer and longer the higher the index so at 660000 it doesn't actually crash its just taking an silly amount of time.
Storage buffers work quite similarly to uniform buffers. To get a sense of how those work I suggest something like this. The main differences are that storage buffer can hold substantially higher amounts of data and the you can randomly read from and write to them.
There are multiple angles of working this, but I'll start with the most basic one - the interface block inside your shader. I will only describe a subset of the possibilities when using interface blocks but it should be enough to get you started.
In contrast to "normal" variables, you cannot specify buffer variables in the global scope. You need to use an interface block (Section 4.3.9 - GLSL 4.40 Spec) as per Section 4.3.7 - GLSL 4.40 Spec:
The buffer qualifier can be used to declare interface blocks (section 4.3.9 “Interface Blocks”), which are then referred to as shader storage blocks. It is a compile-time error to declare buffer variables at global scope (outside a block).
Note that the above mentioned section differs slightly from the ARB extension.
So, to get access to stuff in your storage buffer you'll need to define a buffer interface block inside your fragment shader (or any other applicable stage):
layout (binding = 0) buffer BlockName
{
float values[]; // just as an example
};
Like with any other block without an instance name, you'll refer to the buffer storage as if values were at global scope, e.g.:
void main()
{
// ...
values[0] = 1.f;
// ...
}
On the application level the only thing you now need to know is that the buffer interface block BlockName has the binding 0 after the program has been successfully linked.
After creating a storage buffer object with your application, you first bind the buffer to the binding you specified for the corresponding interface block using
glBindBufferBase(GLenum target​, GLuint index​, GLuint buffer​);
for binding the complete buffer to the index or
glBindBufferRange(GLenum target​, GLuint index​, GLuint buffer​, GLintptr offset​, GLsizeiptr size​);
for binding a subset specified by an offset and a number of of the buffer to the index.
Note that index refers to the binding specified in your layout for the corresponding interface block.
And that's basically it. Be aware that there are certain limits for the storage buffer size, the number of binding points, maximum storage block sizes and so on. I refer you to the corresponding sections in the GL and GLSL specs.
Also, there is a minimal example in the ARB extension. Reading the issues sections of extension also often provides further insight into the exposed functionality and the rationale behind it. I advise you to read through it.
Leave a comment if you run into problems.

OpenGL How Many VAOs

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!

Must shader uniforms be uploaded once for every VAO?

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.

Storing per-object data for fragment shader

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.