Opengl - Is glDrawBuffers modification stored in a FBO? No? - opengl

I try to create a FrameBuffer with 2 textures attaching to it (Multi Render Targets). Then in every time step, both textures are cleared and painted, as following code. (Some part will be replaced as pseudo code to make it shorter.)
Version 1
//beginning of the 1st time step
initialize(framebufferID12)
//^ I quite sure it is done correctly,
//^ Note : there is no glDrawBuffers() calling
loop , do once every time step {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID12);
//(#1#) a line will be add here in version 2 (see belowed) <------------
glClearColor (0.5f, 0.0f, 0.5f, 0.0f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// paint a lot of object here , using glsl (Shader .frag, .vert)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
All objects are painted correctly to both texture, but only the first texture (ATTACHMENT0) is cleared every frame, which is wrong.
Version 2
I try to insert a line of code ...
glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ;
at (#1#) and it works as expected i.e. clear all two textures.
(image http://s13.postimg.org/66k9lr5av/gl_Draw_Buffer.jpg)
Version 3
From version 2, I move that glDrawBuffers() statement to be inside frame buffer initialization like this
initialize(int framebufferID12){
int nameFBO = glGenFramebuffersEXT();
int nameTexture0=glGenTextures();
int nameTexture1=glGenTextures();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,nameFBO);
glBindTexture(nameTexture0);
glTexImage2D( .... ); glTexParameteri(...);
glFramebufferTexture2DEXT( ATTACHMENT0, nameTexture0);
glBindTexture(nameTexture1);
glTexImage2D( .... ); glTexParameteri(...);
glFramebufferTexture2DEXT( ATTACHMENT0, nameTexture1);
glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ; //<--- moved here ---
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
return nameFBO ;
}
It is no longer work (symptom like version 1), why?
The opengl manual said that "changes to context state will be stored in this object", so the state modification from glDrawBuffers() will be stored in "framebufferID12" right? Then, why I have to call it every time step (or every time I change FBO)
I may misunderstand some opengl's concept, someone enlighten me please.
Edit 1: Thank j-p. I agree that it is make sense, but shouldn't the state be recorded in the FBO already?
Edit 2 (accept answer): Reto Koradi's answer is correct! I am using a not-so-standard library called LWJGL.

Yes, the draw buffers setting is part of the framebuffer state. If you look at for example the OpenGL 3.3 spec document, it is listed in table 6.23 on page 299, titled "Framebuffer (state per framebuffer object)".
The default value for FBOs is a single draw buffer, which is GL_COLOR_ATTACHMENT0. From the same spec, page 214:
For framebuffer objects, in the initial state the draw buffer for fragment color zero is COLOR_ATTACHMENT0. For both the default framebuffer and framebuffer objects, the initial state of draw buffers for fragment colors other then zero is NONE.
So it's expected that if you have more than one draw buffer, you need the explicit glDrawBuffers() call.
Now, why it doesn't seem to work for you if you make the glDrawBuffers() call as part of the FBO setup, that's somewhat mysterious. One thing I notice in your code is that you're using the EXT form of the FBO calls. I suspect that this might have something to do with your problem.
FBOs have been part of standard OpenGL since version 3.0. If there's any way for you to use OpenGL 3.0 or later, I would strongly recommend that you use the standard entry points. While the extensions normally still work even after the functionality has become standard, I would always be skeptical how they interact with other features. Particularly, there were multiple extensions for FBO functionality before 3.0, with different behavior. I wouldn't be surprised if some of them interact differently with other OpenGL calls compared to the standard FBO functionality.
So, try using the standard entry points (the ones without the EXT in their name). That will hopefully solve your problem.

Related

OpenGL: Repeated use of transform feedback buffers overwrites already established textures

I have a working implementation of this technique for view frustum culling of instanced geometry. The gist of the technique is that we use a vertex shader to check if the bounds of an object lie within the view frustum, and if they do we output the position of that object, using a transform feedback buffer and a geometry shader, to a texture. We can then, during an actual rendering pass, use that texture, along with a query of how many positions we emitted, to acquire the relevant position data for the object we're rendering, and number of draws to specify in our call to glDrawElementsInstanced. One difference between what I do, and what the article does, is that I emit a full transformation matrix, rather than a simple position vector, to the texture, but I doubt that has any bearing on my problem.
The actual problem: Currently I have this setup so that, for each object type being rendered (i.e. tree, box, rock, whatever), the actual rendering pass follows immediately upon the frustum cull rendering pass. This works, and gives the intended results. What I want to do instead, however, is to go over all my drawcommands and do all the frustum culling for the various objects first, and only thereafter do all the actual rendering, to avoid a bunch of unnecessary state changes (i.e. switching back and forth between shader programs). When I do this, however, I encounter the problem that previously established textures -- the ones I use for reading positions from during the actual rendering passes -- all seem to be overwritten by the latest call to the frustum culling function, meaning that all textures established seemingly contain only the position information from the last frustum cull call.
For example: I render, in order, 4 trees, 10 boxes and 3 rocks, and what I will see instead is a tree, a box, and a rock, at all the (three) positions where I would expect only the 3 rocks to be. I cannot for the life of me figure out why this is, because I quite clearly bind new buffers and textures to the TRANSFORM_FEEDBACK_BUFFER every time I call the function. Why are the previously used textures still receiving the new data from the latest call?
Code, in C, for the frustum culling function:
void fcullidraw(drawcommand *tar) {
/* printf("Fculling %s\n", tar->res->name); */
mesh *rmesh = &tar->res->amod->meshes[0];
/* glDeleteTextures(1, &rmesh->ctex); */
if(rmesh->ctbuf == 0)
glGenBuffers(1, &rmesh->ctbuf);
glBindBuffer(GL_TEXTURE_BUFFER, rmesh->ctbuf);
glBufferData(GL_TEXTURE_BUFFER, sizeof(instancedata) * tar->nodraws, NULL, GL_DYNAMIC_COPY);
if(rmesh->ctex == 0)
glGenTextures(1, &rmesh->ctex);
glBindTexture(GL_TEXTURE_BUFFER, rmesh->ctex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, rmesh->ctbuf);
if(rmesh->cquery == 0)
glGenQueries(1, &rmesh->cquery);
checkactiveshader(tar->tar, findshader("icull"));
glEnable(GL_RASTERIZER_DISCARD);
glUniform1f(activeshader->radius, tar->res->amesh->bbox.radius);
glUniform3fv(activeshader->extent, 1, (const GLfloat*)&tar->res->amesh->bbox.ext);
glUniform3fv(activeshader->cp, 1, (const GLfloat*)&tar->res->amesh->bbox.cp);
glBindVertexArray(tar->res->amod->meshes[0].vao);
glBindBuffer(GL_ARRAY_BUFFER, tar->res->amod->meshes[0].posarray);
glBufferData(GL_ARRAY_BUFFER, sizeof(mat4_t) * tar->nodraws, tar->posarray, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, rmesh->ctbuf);
glBeginTransformFeedback(GL_POINTS);
glBeginQuery(GL_PRIMITIVES_GENERATED, rmesh->cquery);
glDrawArrays(GL_POINTS, 0, tar->nodraws);
glEndQuery(GL_PRIMITIVES_GENERATED);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);
glGetQueryObjectuiv(rmesh->cquery, GL_QUERY_RESULT, &rmesh->visibleinstances);
}
tar and rmesh obviously vary between each call to this function. Do note that I have left in a few lines of comments here containing code to delete the buffers and textures between each rendering cycle, rather than simply overwriting them, but using that code instead has no effect on the error mode.
I'm stumped. I feel that the textures and buffers are well defined and clearly kept separate, so I do not understand how the textures from previous calls to fcullidraw are somehow still bound to and being overwritten by the TransformFeedback, if that is indeed what is happening, and it certainly seems to be, because the earlier objects will read in the entire transformation matrix of the rock quite neatly, with the "right" rotation, translation, and everything.
The article linked does do the operations in the order I want to do them -- i.e. first repeated frustum culls, and then repeated rendering -- and I'm not sure I see what I do differently. Might be some small and obvious thing, and I might be an idiot, but in that case I'd love to know why and how I am that.
EDIT: I pushed on and updated my implementation with a refinement of the original technique, suggested here, which gets rid of the writing-to-texture method altogether, in favor of instead simply writing to a buffer bound to the VAO, and set to update once per rendered instance with a VertexAttribDivisor. This method looks at lot cleaner on the whole, and incidentally had the additional side effect of not having my original problem at all, as I'm no longer writing to and uploading textures. This is, thus, no longer a practical problem for me, but the answer to the theoretical question does still elude me, so if anyone has ideas I'm still all ears.

OpenGL new textures replacing old ones after deletion

I've run into a bit of a confusing problem with OpenGL, it's rather simple but I've failed to find any directly related information.
What I'm trying to do
I'm creating several new textures every frame, and right after creation I bind them, use them for drawing, and then delete them right after.
The Problem
If I delete every texture right after it was used, the last one to be drawn replaces the previous ones(but their different geometry works as it should). If I batch my deletions after all drawing has been done, it works as expected, but if I do any draw calls at all after deleting the textures, the texture used in the last drawcall replaces the old ones(which could be some common permanent sprite texture).
Results from debugging
I've tried using glFlush(), which didn't seem to do anything at all, not deleting the textures at all gives the correct behaviour, and also not drawing anything at all between deleting the textures and calling SwapBuffers() works.
Code
This is not what my code looks like, but this is what the relevant parts boil down to:
int Tex1, Tex2, Tex3;
glGenTextures(1, &Tex1);
glBindTexture(GL_TEXTURE_2D, Tex1);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex1
glGenTextures(1, &Tex2);
glBindTexture(GL_TEXTURE_2D, Tex2);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex2
// I delete some textures here.
glDeleteTextures(1, &Tex1);
glDeleteTextures(1, &Tex2);
// If I comment out this section, everything works correctly
// If I leave it in, this texture replaces Tex1 and Tex2, but
// the geometry is correct for each geometry batch.
glGenTextures(1, &Tex3);
glBindTexture(GL_TEXTURE_2D, Tex3);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex3
glDeleteTextures(1, &Tex3);
// ...
SwapBuffers();
I suspect this might have something to do with OpenGL buffering my draw calls,
and by the time they are actually processed the textures are deleted? It doesn't really make sense to me though, why would drawing something else after deleting the previous textures cause this behaviour?
More context
The generated textures are text strings, that may or may not change each frame, right now I create new textures for each string each frame and then render the texture and discard it right after. The bitmap data is generated with Windows GDI.
I'm not really looking for advice on efficiency, ideally I want an answer that can quote the documentation on the expected/correct behaviour for rendering using temporary textures like this, as well as possible common gotchas with this approach.
The expected behavior is clear. You can delete the objects as soon as you are done using them. In your case, after you made the draw calls that use the textures, you can call glDeleteTextures() on those textures. No additional precautions are required from your side.
Under the hood, OpenGL will typically execute the draw calls asynchronously. So the texture will still be used after the draw call returns. But that's not your problem. The driver is responsible for tracking and managing the lifetime of objects to keep them around until they are not used anymore.
The clearest expression of this I found in the spec is on page 28 of the OpenGL 4.5 spec:
If an object is deleted while it is currently in use by a GL context, its name is immediately marked as unused, and some types of objects are automatically unbound from binding points in the current context, as described in section 5.1.2. However, the actual underlying object is not deleted until it is no longer in use.
In your code, this means that the driver can't delete the textures until the GPU completed the draw call using the texture.
Why that doesn't work in your case is hard to tell. One possibility is always that something in your code unintentionally deletes the texture earlier than it should be. With complex software architectures, that happens much more easily than you might think. For example, a really popular cause is that people wrap OpenGL objects in C++ classes, and let those C++ objects go out of scope while the underlying OpenGL object is still in use.
So you should definitely double check (for example by using debug breakpoints or logging) that no code that deletes textures is invoked at unexpected times.
The other option is a driver bug. While object lifetime management is not entirely trivial, it is so critical that it's hard to imagine it being broken for a very basic case. But it's certainly possible, and more or less likely depending on vendor and platform.
As a workaround, you could try not deleting the texture objects, and only specifying new data (using glTexImage2D()) for the same objects instead. If the texture size does not change, it would probably be more efficient to only replace the data with glTexSubImage2D() anyway.

OpenGL what do I have to do before drawing a triangle?

Most of the tutorials, guides and books that I've found out there are related to OpenGL, explains how to draw a triangle and initialize OpenGL. That's fine. But when they try to explain it they just list a bunch of functions and parameters like:
glClear()
glClearColor()
glBegin()
glEnd()
...
Since I'm not very good at learning things by memory, I always need an answer to "why are we doing this?" so that I'll write that bunch of functions because I remember that I have to set a certain things before doing somethings else and so on not because the tutorial told me so.
Could please someone explain to me what do I have to define to OpenGL (only pure OpenGL, I'm using SFML as background library but that really doesn't matter) before starting to draw something with glBegin() and glEnd()?
Sample answer:
You have to first tell OpenGL what color does it need to clear the
screen with. Because each frame needs to be cleared by the previous
before we start to draw the current one...
First you should know, that OpenGL is a state machine. That means, that apart from creating the OpenGL context (which is done by SFML) there's no such thing as initialization!
Since I'm not very good at learning things by memory,
This is good…
I always need an answer to "why are we doing this?"
This is excellent!
Could please someone explain to me what do I have to define to OpenGL (only pure OpenGL, I'm using SFML as background library but that really doesn't matter) before starting to draw something with glBegin() and glEnd()?
As I already told: OpenGL is a state machine. That basically means, that there are two kinds of calls you can do: Setting state and executing operations.
For example glClearColor sets a state variable, that of the clear color, which value is used for clearing the active framebuffer color to, when a call to glClear with the GL_COLOR_BUFFER_BIT flag set. There exists a similar function glClearDepth for the depth value (GL_DEPTH_BUFFER_BIT flag to glClear).
glBegin and glEnd belong to the immediate mode of OpenGL, which have been deprecated. So there's little reason in learning them. You should use Vertex Arrays instead, preferrably through Vertex Buffer Objects.
But here it goes: glBegin sets OpenGL in a state that it should now draw geometry, of the kind of primitive selected as parameter to glBegin. GL_TRIANGLES for example means, that OpenGL will now interpret every 3 calls to glVertex as forming a triangle. glEnd tells OpenGL that you've finished that batch of triangles. Within a glBegin…glEnd block certain state changes are disallowed. Among those everything that has to do with transforming the geometry and generating the picture, which matrices, shaders, textures, and some others.
One common misconception is, that OpenGL is initialized. This is due to badly written tutorials which have a initGL function or similar. It's a good practice to set all state from scratch when beginning to render a scene. But since a single frame may contain several scenes (think of a HUD or split screen gaming) this happens several times a scene.
Update:
So how do you draw a triangle? Well, it's simple enough. First you need the geometry data. For example this:
GLfloat triangle[] = {
-1, 0, 0,
+1, 0, 0,
0, 1, 0
};
In the render function we tell OpenGL that the next calls to glDrawArrays or glDrawElements shall fetch the data from there (for the sake of simplicity I'll use OpenGL-2 functions here):
glVertexPointer(3, /* there are three scalars per vertex element */
GL_FLOAT, /* element scalars are float */
0, /* elements are tightly packed (could as well be sizeof(GLfloat)*3 */
trignale /* and there you find the data */ );
/* Note that glVertexPointer does not make a copy of the data!
If using a VBO the data is copied when calling glBufferData. */
/* this switches OpenGL into a state that it will
actually access data at the place we pointed it
to with glVertexPointer */
glEnableClientState(GL_VERTEX_ARRAY);
/* glDrawArrays takes data from the supplied arrays and draws them
as if they were submitted sequentially in a for loop to immediate
mode functions. Has some valid applications. Better use index
based drawing for models with a lot of shared vertices. */
glDrawArrays(Gl_TRIANGLE, /* draw triangles */
0, /* start at index 0 */
3, /* process 3 elements (of 3 scalars each) */ );
What I didn't include yet is setting up the transformation and viewport mapping.
The viewport defines how the readily projected and normalized geometry is placed in the window. This state is set using glViewport(pos_left, pos_bottom, width, height).
Transformation today happens in a vertex shader, Essentially a vertex shader is a small program written in a special language (GLSL), that takes the vertex attributes and calculates the clip space position of the resulting vertex. The usual approach for this is emulating the fixed function pipeline, which is a two stage process: First transform the geometry into view space (some calculations, like illumination are easier in this space), then project it into clip space, which is kind of the lens of the renderer. In the fixed function pipeline there are two transformation matrices for this: Modelview and Projection. You set them to whatever is required for the desired outcome. In the case of just a triangle, we leave the modelview identity and use a ortho projection from -1 to 1 in either dimension.
glMatrixMode(GL_PROJECTION);
/* the following function multiplies onto what's already on the stack,
so reset it to identity */
glLoadIdentity();
/* our clip volume is defined by 6 orthogonal planes with normals X,Y,Z
and ditance 1 from origin into each direction */
glOrtho(-1, 1, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
/* now a identity matrix is loaded onto the modelview */
glLoadIdentity();
Having set up the transformation we can now draw the triangle as outlined above:
draw_triangle();
Finally we need to tell OpenGL we're done with sending commands and it should finish it's renderings.
if(singlebuffered)
glFinish();
However most of the time your window is double buffered, so you need to swap it to make things visime. Since swapping makes no sense without finishing the swap implies a finish
else
SwapBuffers();
You're using the API to set and change the OpenGL state machine.
You're not actually programming directly to the GPU, you're using a medium between your application and your GPU to do whatever you're trying to do.
The reason it is like this and doesn't work the same way as a CPU and memory, is because openGL was intended to run on os/system-independent hardware, so that your code can run on any OS and run on any hardware and not just the one your programming to.
Hence, because of this, you need to learn to use their preset code that makes sure that whatever you're trying to do it will be able to be run on all systems/OS/hardware within a reasonable range.
For example if you were to create your application on windows 8.1 with a certain graphics card(say amd's) you still want your application to be able to run on Andoird/iOS/Linux/other Windows systems/other hardware(gpus) such as Nvidia.
Hence why Khronos, when they created the API, they made it as system/hardware independent as possible so that it can run on everything and be a standard for everyone.
This is the price we have to pay for it, we have to learn their API instead of learning how to directly write to gpu memory and directly utilize the GPU to process information/data.
Although with the introduction of Vulkan things might be different when it is released(also from khronos)and we will find out how it will be working.

OpenGL textures: why does order matter?

I am trying to setup a simple function which will make it a lot easier for me to texture map geometry in OpenGL, but for some reason when I'm trying to make a skybox, I am getting a white box instead of the texture mapped geometry. I think that the problemed code lies within the following:
void MapTexture (char *File, int TextNum) {
if (!TextureImage[TextNum]){
TextureImage[TextNum]=auxDIBImageLoad(File);
glGenTextures(1, &texture[TextNum]);
glBindTexture(GL_TEXTURE_2D, texture[TextNum]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[TextNum]->sizeX, TextureImage[TextNum]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[TextNum]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[TextNum]);
//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[TextNum]->sizeX, TextureImage[TextNum]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[TextNum]->data);
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
The big thing I don't understand is for some reason the glBindTexture() must come between glGenTextures() and glTexImage2D. If I place it anywhere else, it screws everything up. What could be causing this problem? Sorry if it's something simple, I'm brand new to openGL.
Below is a screenshot of the whitebox I am talking about:
+++++++++++++++++++++++++++++++
EDIT
+++++++++++++++++++++++++++++++
After playing around with the code a bit more, i realized that if I added glTexImage2D() and glTexParameteri()after the last glBindTexture() then all the textures load. Why is it that without these two lines most textures would load, and yet there are a few that would not, and why do I have to call glTexImage() for every frame, but only for a few textures?
Yes, order is definitely important.
glGenTexture creates a texture name.
glBindTexture takes the texture name generated by glGenTexture, so it can't be run before glGenTexture.
glTexImage2D uploads data to the currently bound texture, so it can't be run before glBindTexture.
The client-side interface to OpenGL is a Big Giant Squggly State Machine. There are an enormous number of parameters and flags that you can change, and you have to be scrupulous to always leave OpenGL in the right state. This usually means popping matrices you push and restoring flags that you modify (at least in OpenGL 1.x).
OpenGL is a state machine, which means that you can pull its levers, turn its knobs, and it will keep those settings, until you change them actively.
However it also manages it's persistent data in objects. Such objects are something abstract, and must not be confused with objects seen on the screen!
Now to the outside OpenGL identifies objects by their so called name, a numerical ID. You create a (list of) name(s) – but not the object(s)! – with glGenTextures for texture objects, which are such a kind of OpenGL object.
To maniupulate such an object, OpenGL must first be put into a state that all the following calls to manipulate such objects of that type happen to one particular object. This is done with glBindTexture. After calling glBindTexture all the following calls that manipulate textures happen to that one texture object you've just bound. If the object didn't exist previously, it is created if a new assigned object name is bound for the first time.
Now OpenGL uses that particular object.
glTexImage2D is just one of several functions to maniuplate the data of the currently bound textures.
Otherwise your function points into the right direction. OpenGL has no real initialization phase, you just do things as you go along. And it makes sense to defer loading of data until you need it. But it also makes sense to have multiple iterations over the lists of objects before you actually draw a frame. One of the preparations should be, that you iterate over all objects (now not OpenGL but your's) to test if the data's already loaded. If a significant amount of data's still missing, draw a loading screen instead, so that the user doesn't get the impression your program hangs. Maybe even carry out lengthy loading operations in a separate thread, but with OpenGL this requires some precautions.

How to use OpenGL and GLSL to change color (C++)?

I am working on an OpenGL project in C++, and I want to learn how to use GLSL shaders. The problem is that, while I can complete my program without using my own shaders, I want to write my own (at this time there are no shaders that I load myself - not sure if OpenGL defaults any).
To draw a bunch of lines on the image (whose vertices are stored in a vector and color values are stored in another vector), I use the following code to run through and render them whenever the frame is updated - I use the GLUT display function for this.
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
vector<point2>::iterator it;
int c_index = 0;
for(it=points.begin(); it<points.end(); it++){
if(c_index % 2 == 0) //set color for every pair of points (each line)
glColor3f(colors[c_index/2][0], colors[c_index/2][1], colors[c_index/2][2]);
c_index++;
glVertex2f(it->x, it->y); //set vertex
}
glEnd();
glFlush();
Now, the problem is when I try to use shaders that I found in another example program, the color is all red (even though the shaders do not explicitly define any colors). It also makes glColor3f do nothing.
My question is, assuming I can use shaders to do this, what do the shaders have to look like, and how would I load them?
Apparently it cannot be done using glColor3f. Instead, I had to make a pre-determined OpenGL buffer, and send the buffer data to the shaders. It can't be done "on the fly" as I hoped.