Copy Texture contents to new texture

Hello,

I’m trying to create an FBO based object that can keep a history of its contents on every frame via textures. Accessing the FBO’s color texture returns TextureRef and oddly enough there’s no copy constructor or gl::Texture::create(...) method to copy the contents of an existing texture. Ideally I’d like to avoid any CPU-GPU bottlenecks that would come from a Texture > Surface > new Texture copy.

From my research it seems the easiest way to do it is rendering the texture into a temporary FBO, retrieving the color texture (or by attaching a fresh texture to the FBO at GL_COLOR_ATTACHMENT0), then destroying the FBO, but this creation/destruction would be impossible to do every frame.

It looks like there’s a native gl method for doing exactly this : glCopyImageSubData

And even a previous suggested implementation that didn’t make it into the fold: https://forum.libcinder.org/topic/copying-a-texture-to-another-implementation

I’m trying to use raw gl calls but can’t quite get it to work.

TextureRef existingTex = mFbo->getColorTexture();
TextureRef storageTex = gl::Texture::create(w, h);

glCopyImageSubData(existingTex, existingTex->getTarget(), 0,0,0,0,
    				storageTex , storageTex->getTarget(), 0,0,0,0,
    				w, h, 1);

:point_up: That doesn’t work because existingTex and storageTex are not the GLuint srcName types the method is expecting, but I’m not sure what to give it.

Can someone help correct my OpenGl syntax or point me to another method?

You can get thet texture id with tex->getId().

That worked. Thanks @gabor_papp. So srcName is the texture Id. Thanks OpenGl, very intuitive :roll_eyes: haha

For anyone interested, the working code is below (don’t forget to set the internal format of the new texture the same as the existing one):

TextureRef existingTex = mFbo->getColorTexture();

int w = existingTex->getWidth();
int h = existingTex->getHeight();
gl::Texture2d::Format format;
format.setInternalFormat( existingTex->getInternalFormat() );

TextureRef storageTex = gl::Texture::create(w, h, format);

glCopyImageSubData(existingTex, existingTex->getTarget(), 0,0,0,0,
    				storageTex, storageTex->getTarget(), 0,0,0,0,
    				w, h, 1);

Hey @adielfernandez , I needed to clone a TextureRef in a vector for a Boomerang style sequence I needed to make from the camera and your code snippet did it for me. Thanks :slight_smile: Just wanted to point out that you forgot to correct the last line and use getId() based on Gabor’s suggestion. It should look like:

TextureRef existingTex = mFbo->getColorTexture();

int w = existingTex->getWidth();
int h = existingTex->getHeight();
gl::Texture2d::Format format;
format.setInternalFormat( existingTex->getInternalFormat() );

TextureRef storageTex = gl::Texture::create(w, h, format);

glCopyImageSubData(existingTex->getId(), existingTex->getTarget(), 0,0,0,0,
    				storageTex->getId(), storageTex->getTarget(), 0,0,0,0,
    				w, h, 1);

Cheers!