Shader blend modes - glCopyTexSubImage or FBO bind?

I’m currently looking at implementing some of the additional blend modes in Praxis LIVE within the OpenGL pipeline - ones like DIFFERENCE which need to be implemented in a shader using multiple textures. I’m hoping to get some advice on the best way to achieve this.

All surfaces within the pipeline use texture-backed FBO’s, which are cached and reused - so doing this on a full image should be quite easy - render two surfaces on to a third. However, I’m not sure what to do in the case the user wants to render into a sub-region of a surface. Now I probably need to get a part of the destination surface into one of the source surfaces, and I’m not sure of the best approach -

  • Bind first source texture FBO, draw destination region into it, bind destination FBO and blend textures.
  • Bind destination FBO and first source texture, use glCopyTexSubImage to get destination region into source texture, then blend textures.
  • Bind new destination FBO (like full-screen), draw areas of original destination around sub-region, then blend sub-region.
  • AN other suggestion??

I’m inclined away from option 3 as it seems to involve a lot of unnecessary rendering. So, what’s likely to be the best performing way of getting the destination FBO into another texture - option 1 involving two FBO binds, or option 2 using glCopyTexSubImage? Or am I missing an obvious alternative?

Hope that makes sense, and thanks in advance, Neil

hmm … surely someone on here has had to do this!? :persecutioncomplex:

TL;DR - Which way of getting the current framebuffer into a texture is likely to work faster across different machines - using glCopyTexSubImage or using render-to-texture (bind texture FBO, draw quad, re-bind previous FBO)?

i think blitting into a fbo is fastestest.

it’s something like :

glTexSubImage < RTT < blit

if you want to access the default-frame-buffer, just use id 0.

  • create a new FBO with same dimensions and 0 samples
  • create a fitting Texture for that FBO, attach
  • blit
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0); // <- 0 is the default framebuffer.
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, target_fbo_id);  // <- the one just created
GL30.glBlitFramebuffer(0,0,width,height,0,0,width,height,GL11.GL_COLOR_BUFFER_BIT,GL11.GL_NEAREST);
  • use texture

you can grab the other buffers like that too if you like. [icode]GL_DEPTH_BUFFER_BIT[/icode] [icode]GL_STENCIL_BUFFER_BIT[/icode]

@basil_ thanks for the input :slight_smile:

OK, option 3! Or 2.5. I thought blit should be faster, but had discounted it because I then read some things online that suggested it wasn’t faster than RTT and sometimes slower, depending on the hardware / driver. I think this was down to RTT being more common and therefore more optimised. Confused! :clue:

I assumed glCopyTexSubImage would be a slower operation in itself, but aren’t FBO binds also slow? Using the former would allow to keep the same FBO bound throughout. Taking the need to bind an FBO twice, will RTT or blit still be faster?

In my particular case, this will be always be working with texture-backed FBO’s. Not sure if that will make a difference to the “right” answer.

it will be faster then copyTexImage, but if you’re better with a single FBO or multiple, i don’t know.

depends on how often you change the render target per frame. if you have something like 2-5 FBO’s, don’t bother to optimise them.

o/

Thanks @basil_ My inclination was to try the FBO re-bind option first, as it’s the easiest to implement given what I’ve already got. You’ve put my mind at rest a bit that this should be the right approach.

I’ll be using multiple FBOs because v2 of Praxis LIVE is built on top of the Processing OpenGL renderer. I’ve hacked it enough already - trying to get it to use a single FBO is probably a step further than I want to go. My switch (from v1) is to attempt to reduce the amount of low-level GL code I have to manage! :wink:

That’s all going to be user dependant - could be 2, could be 20, could be 200 - when their machine judders to a halt they’ll know they’ve gone too far! ;D