Render scene to texture: FBO and glCopyTexImage2D

It is sort of tricky to explain what I’m trying to do here. But basically, I want to render my entire scene to a texture (as efficiently as possible) so that I can apply some post-processing effects.

Just to give you an idea of where I’m at, I can render my scene directly to the screen, and that all works great. I’m currently working on rendering it to a texture.

My initial attempt at rendering to texture was by using an FBO. I ran into a hiccup with this though. My scene uses an FBO for rendering a reflection and refraction to a texture, so I ended up switching from my entire scene FBO to my reflection FBO, so my entire scene was not rendered to my scene FBO as intended. I did not forsee this being a problem, but in retrospect it is obvious.

My current attempt just uses glCopyTexImage2D, which works fine. It sidesteps the issues I had with nesting FBOs - but, it is very slow.

Given my situation, are there any other methods of rendering to texture that is more performance-friendly than glCopyTexImage2D or is that the best solution?

Best,
Brick

edit: forgot to mention, I’m working with GLES 2.0

This seems more like a code-structure problem to me. Your render scene function looks, conceptually, like this:


renderScene()
  bindReflectionFBO()
  renderReflections()
  bindDefaultFramebuffer()
  renderNonreflected()

The problem is “bindDefaultFramebuffer”. What you really want is “restorePreviousFramebuffer”. You could use glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING) to get the currently bound framebuffer. You would get this before changing the framebuffer, then restore it afterwards.

Or, you can just have a little framebuffer manager class that allows you to change a framebuffer, then restore it to the old one. All your framebuffer binding would go through that class.

Good point, I had a suspicion that it would be more of design problem… Second question, will using the FBO instead of glCopyTexImage2D be at least somewhat faster?

Yes, it will.

Also worth looking at glCopyTexSubImage2D. You’ll need to create the texture object in advance (via Gen/Bind/TexImage) and destroy/recreate it if your resolution changes, but it will do the job considerably faster than glCopyTexImage2D.

An FBO is the more correct modern approach of course, but CopyTexSubImage will work on downlevel hardware or in cases where your driver’s FBO support is ropey.

Ok, I tried restructuring my code. It looks more like this.


renderScene()
  bindDefaultFBO()
  renderSomeNonReflectiveStuff()

  bindReflectionFBO()
  renderReflection()

  bindRefractionFBO()
  renderRefraction()

  bindDefaultFBO()
  renderRemainingNonReflectiveStuf() // uses reflection and refraction textures

Now, I am having a strange issue with this. Using a profiler, I can see that my reflection/refraction textures are correct. However, when I attempt to use the reflection/refraction textures (which happens after I switch back from the reflection and refracion FBOs to the default FBO), the reflection/refraction textures appear to be just the clear color… But besides that, everything is rendered correctly. Again, I don’t understand why, because in the profiler I am seeing the textures I expect.

Is this just ropey FBO support? Or is there some caveat I am not aware of in switching between FBOs?