Search code examples
c++opengltextures

In openGL. How do you copy part of a texture to another texture


I am trying to create a blank (white with no alpha) texture where I can load other textures and write part of them. I tried just having to get a portion of the texture, and using glTexSubImage2D to put it there it doesn't seem to work right. Anyone have any idea how to do this? What am i doing wrong?

int sourceTextWidth;
int sourceTextHeight;
int sourceFormat;
int formatOffset = 0;

//bind the texture
glBindTexture( GL_TEXTURE_2D, textureID );

//get its params
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &sourceFormat);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sourceTextWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &sourceTextHeight);
switch (sourceFormat)
{
    case GL_RGB:
    {
        formatOffset = 3;
    }
    break;
    case GL_RGBA:
    {
        formatOffset = 4;
    }
    break;
}
if (formatOffset == 0)
{
    return false;
}


unsigned char * sourceData = (unsigned char *)malloc(sourceTextWidth * sourceTextHeight * formatOffset);

glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, sourceData);

glBindTexture( GL_TEXTURE_2D, m_currentTextureId );

unsigned char * destData = (unsigned char *)malloc(width * height * 3);



glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, sourceData);

for (int i = 0; i < height; ++i)
{       
memcpy(&destData[(i * width * 3) ], &sourceData[((i + y) * sourceTextWidth * 3) + (x * 3)], width * 3);
}
//glDeleteTextures (1, m_currentTextureId);
glBindTexture( GL_TEXTURE_2D, m_currentTextureId );

glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB,GL_UNSIGNED_BYTE, destData );
free(destData);
free(sourceData);

Solution

  • If you have access to OpenGL 4.3 or the ARB_copy_image extension (or its older cousin, NV_copy_image), then you can use glCopyImageSubData.

    Otherwise, you could use FBO blitting. You attach the source texture to an FBO, attach the destination texture to an FBO (possibly the same one, but if so, then obviously not to the same attachment point), set the read buffers and draw buffers for the FBOs to read from the source attachment and draw to the destination attachment, and then blit from one framebuffer to the other.

    The trick you're trying to do doesn't work, BTW, because you never allocated storage for your new texture. glTexSubImage cannot be called for an image in a texture unless storage for that image has been allocated. This can be by a call to glTexImage or one of a number of other functions. The "SubImage" functions are all for uploading to existing storage, not for creating new storage.