1
votes

I have an OpenGL program in which I am doing some augmented reality work. It works in 2 passes.

First, it renders a frame using standard OpenGL calls. Next, it compares a frame from the camera to the rendered frame using a shader.

In the first pass, I render to a texture bound to my framebuffer objects, and I also upload camera frames to other textures bound to that object.

In my second pass, my shader has no trouble accessing the uploaded textures (that is, the camera frames) however it cannot access the texture rendered to by the first pass.

If I make a debug shader that simply sets the vertex colours to be the colour of the texture at that point, then when I use the texture uploaded from the camera I see this:

Successfully accessing texture

However, if I change the shader to instead use the texture rendered to in the first pass, I see this:

Not accessing texture successfully

I'll try to give enough background below to make this clear, but any help is greatly appreciated!


Background

I know it was rendering properly in the first pass, as I have a debug window showing me the rendering results, and in addition am using Apple's OpenGL Profiler, and can see all of the textures.

I'm basically doing the rendering to textures like this site does

http://www.songho.ca/opengl/gl_fbo.html#example

a difference is that I never switch framebuffer objects. That is, I never call

// switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

Do I need to use different FBOs when I do my initial rendering, and when I use my shader to compare them?


The one other hint I have towards what might be going on is that if in the OpenGL profiler I look at my State, it only claims that GL_TEXTURE0 and GL_TEXTURE4 have changed from their default state. Those are both textures that I explicitly load pixel data into. The other 3 textures are rendered to in my first pass. Screenshot of OpenGL state


Relevant code

// First I create the textures
glGenTextures(1, &renderTexture);
glGenTextures(1, &cameraTexture);
glGenTextures(1, &correlationTexture);

gllActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, cameraTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->width, img->height, 0,GL_BGR, GL_UNSIGNED_BYTE, img->imageData); 

glActiveTexture(GL_TEXTURE0+1);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);

glActiveTexture(GL_TEXTURE0+2);
glBindTexture(GL_TEXTURE_2D, correlationTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, correlationTexture, 0);

// Now I render to the renderTexture. This works fine, I can verify
// it using glReadPixels.

// However, later on when I'm ready to do the shader, I do this
// First I switch the bound texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,      GL_TEXTURE_2D,correlationTexture, 0); // (this has been set up earlier)
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(theProgram);
glUniform1i(renderTexLoc, 1); // This should tell it to look at the rendered texture from earlier, it does not.
2

2 Answers

2
votes

Ah, looks like I solved it. I had to bind the first-pass rendered texture before I rendered with the shader thus:

  glActiveTexture(GL_TEXTURE0+1);
  glBindTexture(GL_TEXTURE_2D,renderTexture);

I guess I'm still a bit fuzzy on what exactly the difference between bound textures vs. active textures is, but for now this works.

0
votes

You're not allowed to both read from and write to the same image at the same time. Doing so leads to undefined behavior.

You can write to different images in the same texture (different mipmaps, or layers of an array/cube/3D texture). But you cannot write to and read from the same image within a texture.

I'm guessing you called glClear(GL_COLOR_BUFFER_BIT) before you tried to render on your second pass, which overwrote the texture you were expecting to read from.

In general, if a texture is attached to the FBO, it should not be bound to the context. And vice-versa. Perhaps you should ping-pong between two textures. One is the current destination while the other is the previous destination. After you finish the second pass, you switch. This is a pretty common technique.