Sign in to follow this  
yahn

glCopyTexImage2D

Recommended Posts

How exactly do you copy a texture to another texture with this function? It doesn't take any textures in its parameters. I want to copy pixels from one texture to another and this seems like the function to do it. I understand all the arguments of the function, but I don't get what you do with the textures. I figure you have to have one bound, but I don't know what you do with the other. Also I wouldn't know if I should bind the one I want to copy to or from. I searched around but all I could really find was a description of what the arguments do. I figured I'd ask here since someone could probably answer this in a second. Thank you.

Share this post


Link to post
Share on other sites
There is no function for doing that. glCopyTexImage2D is for copying the framebuffer to a texture which you can use for texture to texture copy if you code it right.

Share this post


Link to post
Share on other sites
If you want to copy a texture to another then you will need to use glGetTexImage() and copy that to a temp pointer and then use that pointer with glTexSubImage*()

Share this post


Link to post
Share on other sites
Ok, I'm going to use glTexSubImage2D(), but what is wrong with this code?


glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);



I know I have the pixel information in pixels. I have x set to the left part of the image I want to copy y set to the top of the image I want to copy and width and height set to the width and height. I'm not sure if you need to bind a texture because I saw an example that was using glTexSubImage2D and I didn't see a texture being bound anywhere. Can anyone help me out?

Thank you.

Share this post


Link to post
Share on other sites
You need to create a texture first the usual way except if you don't want to define the texels, put NULL for the pixels in glTexImage2D

glTexImage2D(..........., NULL);


then this will work

glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);


and use glGetError to see if errors are reported.


Share this post


Link to post
Share on other sites
I'm still confused.

I have the pixels for the entire image. Can I use those pixels and load a 4 textures each representing a quarter of the image? I would figure I could, but I just want to make sure.

Do I have to make a texture with the entire image first? I've tried doing it making a texture first and not making one and neither way works.

Right now I am creating a texture and then binding it and then calling glTexImage2D(..., NULL) making it large enough for the quarter image to fit in and putting in all the right arguments for the format and what not. Then I bind it again and call glTexSubImage2D().

So my code would look something like this:
// load texture and pixels

glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glBindTexture(GL_TEXTURE_2D, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);



What am I doing wrong? It's just loading a white texture. And when I check for errors, it is not returning an error.

Share this post


Link to post
Share on other sites
white generally means there is something wrong with the filtering modes set. As I guess you aren't creating any mipmap levels try setting both the min and max filters to GL_LINEAR and see if that helps.

Share this post


Link to post
Share on other sites
You don't have to bind the created texture twice, so the second glBindTexture call is redundand. If a texture is bound it will stay this way until you bind another one.

glTexSubImage2D is used to change a part of an already existing texture to new data. If you want to create a whole new texture you can just use glTexImage2D and specify the pixel data there. Apart from that both functions work the same way.
Depending on how the pixel data is laid out in the memory area pointed to by pixels you may need to use the glPixelStore function.

Edit: And set the min and max filter as phantom pointed out.

Share this post


Link to post
Share on other sites
I figured I wouldn't need to bound them twice.

Anyways, how do I create a whole new texture from the pixel data and load it into four textures when I can only change the width and the height? I'd need to change the x and the y.

Do I need to create the texture four times and then call glTexSubImage2D() four times to get the right sub images? Or can I just call glTexImage2D() with the pixel data that I have?

Also, I am setting the min and max filters. I am just trying to make this as easy to look at as possible.

Thank you.

Share this post


Link to post
Share on other sites
I figured I wouldn't need to bound them twice.

Anyways, how do I create a whole new texture from the pixel data and load it into four textures when I can only change the width and the height? I'd need to change the x and the y.

Do I need to create the texture four times and then call glTexSubImage2D() four times to get the right sub images? Or can I just call glTexImage2D() with the pixel data that I have?

Also, I am setting the min and max filters. I am just trying to make this as easy to look at as possible.

Thank you.

edit:

I don't know how I posted this twice. -- Sorry

[Edited by - yahn on August 13, 2007 1:23:11 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by yahn
I know I have the pixel information in pixels. I have x set to the left part of the image I want to copy y set to the top of the image I want to copy and width and height set to the width and height.

I'm fairly sure this should be the bottom of the image you want to copy.

Share this post


Link to post
Share on other sites
Yes I changed that. That was from when I was using a different function.

Right now I'm just trying to use glTexImage2D().

this code should be pretty self explanatory:

GLubyte *frame_pixels = new GLubyte[4*width*height];

int h = 0, w = 0;
while (h < height)
{
while (w < width)
{
frame_pixels[w*h + w*4] = image_pixels[(w + x)*(h + y) + w*4];
frame_pixels[w*h + w*4 + 1] = image_pixels[(w + x)*(h + y) + w*4 + 1];
frame_pixels[w*h + w*4 + 2] = image_pixels[(w + x)*(h + y) + w*4 + 2];
frame_pixels[w*h + w*4 + 3] = image_pixels[(w + x)*(h + y) + w*4 + 3];
w++;
}
h++;
}

glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame_pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

if (glGetError() != GL_NO_ERROR)
{
return false;
}

return true;


I thought RGBA was 4 bytes per pixel. So, I thought this code should work, but it doesn't.

x and y are the offsets of the frame
width and height are the width and height of the frame
texture is the texture I have created to use for this
frame_pixels is the array storing the pixel data for the frame I want to create
image_pixels is the array storing the pixel data for the image I want to create the frame from.

This isn't returning any errors. The code is always loading a white line for some reason. And I know for a fact that image_pixels has the pixels that I want. I'm rendering both textures to the screen and image_pixels has what I want, it just isn't being copied into frame_pixels.

Thank you for the help so far.

Share this post


Link to post
Share on other sites
This is really weird, but when I change the code a little it still isn't working. So, I'm really at a loss now.

when I change the loop to get the pixels to this:

GLubyte *frame_pixels = new GLubyte[sizeof(image_pixels)];
int w = 0;
while (w < sizeof(image_pixels))
{
frame_pixels[w] = image_pixels[w];
w++;
}

I would expect that frame_pixels is the same thing as image_pixels. But when I render the texture using frame_pixels the image is screwed up. When I render it using image_pixels it still works fine. I really can't explain that. Does anyone see what I'm doing wrong?

Thank you.

Share this post


Link to post
Share on other sites
Don't use 4

glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame_pixels);

try

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame_pixels);

Share this post


Link to post
Share on other sites
It still does the same thing. I'm really confused how I am copying the array into another array exactly and it doesn't work on the copied one but it does work on the original one.

Is there something about unsigned char pointer arrays that I don't know about?

If it is any simpler to do than figuring out what is wrong with this, can anyone tell me how I can take the pixels I would use to create a texture for one image and use those to create 4 textures each representing a quarter of the image. That is basically what I'm trying to do, but for some reason anything I do with the copied pixels doesn't work.

Share this post


Link to post
Share on other sites
Sigh,

please try glGetTexImage() and send the bound texture object into an array and then do what you want with that data and see if you get what you are looking for, and if you want you can just send that array back into the bound texture object with glTexSubImage and just select the whole image...

Share this post


Link to post
Share on other sites
This is one of the first things that I tried doing and it didn't work. I don't really understand how to work with more than one texture at once. Could you explain?

Thank you.

Share this post


Link to post
Share on other sites
C SPECIFICATION
void glGetTexImage( GLenum target,
GLint level,
GLenum format,
GLenum type,
GLvoid *pixels )


void glTexSubImage2D( GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid *pixels )


so


//get texture data
unsigned int temp1 = 0;
unsigned char *temp = new unsigned char[512*512*4];
//or call glGetTexLevelParameter() to find the texture size!!!

glBindTexture(GL_TEXTURE_2D, textureObject[0]);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);

//setup new texture object to take old data
//also if you want to edit the data do so here before you upload it to glTexImage2D()

glGenTextures(1, &temp1);
glBindTexture(GL_TEXTURE_2D, temp1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);

//save out the data to see it with your texture library
delete []temp;//clean up after ourselves




[Edited by - MARS_999 on August 17, 2007 8:28:00 PM]

Share this post


Link to post
Share on other sites
That is doing the exact same thing as glTexSubImage2D() was doing before. The example code you gave looks as if it should be to create a duplicate texture. I need to create one that is part of the image. glTexSubImage2D() seems like it should work, but it doesn't.

Maybe I'm not being clear. I want to be able to load parts of an image. I used the example of being able to create 4 textures that each represent a quarter of the image.

I have tried manipulating the pixel data myself and using glTexImage2D() and that does not work. I've tried using glTexSubImage2D() and that does not work. OpenGL has to be able to do this. This is not a very complicated task. However, I can't seem to get the functions right to be able to do this.

I've tried binding the texture, using glTexImage2D() to load the entire image and then calling glTexSubImage2D() to get the part of the image that I want. That seems to be the order of functions I should be using to accomplish this, but it is not working.

I've tried manipulating the pixels that glTexSubImage2D() takes and I've tried leaving them the same, but both ways leave me with the exact same image that is the same thing as if I would call glTexImage2D() with too large of an array of pixels for the dimensions in the arguments.

What am I doing wrong?

Share this post


Link to post
Share on other sites
So let me see if I have this correct, you want to take a texture say 1024x1024 and take out a 512x512 section and do something to that chunk? and then upload it back into the original texture?

Share this post


Link to post
Share on other sites
Yes, except I don't really want to do anything to that chunk. I just wanted to load parts of an image.

Share this post


Link to post
Share on other sites

void updateTexture(void)
{
glBindTexture(GL_TEXTURE_2D, textureObject[MAP]);
unsigned char temp[256*256*4] = {0};

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, temp);
}




I can tell you that code works for me to update a texture. Are you trying to update mipmaps? NPOT textures? Check your pixel alignment?

[Edited by - MARS_999 on August 18, 2007 8:24:31 PM]

Share this post


Link to post
Share on other sites
I may have gotten it completely wrong, but if you've got a large texture, and you just want to have 4 quads displaying different quarters of it. Why not just draw 4 quads, alll bound with the same texture and just change the texture coordinates?

glBindTexture (glTexture2d, texture)
glBegin GL_Quads
glTexCoord3f 0,0
...
glTexCoord3f 0,0.5
...
glTexCoord3f 0.5,0.5
...
glTexCoord3f 0.5,0
glend

glBegin GL_Quads
glTexCoord3f 0.5,0
...
glTexCoord3f 0.5,0.5
...
glTexCoord3f 1,0.5
...
glTexCoord3f 1,0
glend

glBegin GL_Quads
glTexCoord3f 0.5,0.5
...
glTexCoord3f 0.5,1
...
glTexCoord3f 1,1
...
glTexCoord3f 1,0.5
glend

glBegin GL_Quads
glTexCoord3f 0,0.5
...
glTexCoord3f 0,1
...
glTexCoord3f 0.5,1
...
glTexCoord3f 0.5,0.5
glend

This will draw 4 quads, each showing a quarter of the Texture. Obviously this code can be optimised, and you need to replace ... with the relevant Vertex and Normal codes.

Sorry if I'm being really dumb.

Share this post


Link to post
Share on other sites
Mars that is still doing the exact same thing. It is like it is taking the entire image and trying to fit it into the reduced sized image. I want to just take a piece of that image and display it as it would normally look.

I'm loading the texture like I would normally and then I'm calling glTesSubImage2D() just like you said but it's doing the same thing it has been doing every time I try to do anything with glTexSubImage2D().

Is there something I'm missing?

load the pixels, bind the texture, call glTexImage2D(), and then call glTexSubImage2D()? That is what I'm doing. From what I read everywhere I can find any information about this, that seems like it is exactly what I should be doing, but it just isn't working at all.

I'm sorry I've drawn this out for almost 2 weeks, but it is one of the last things I need to finish and I've been trying everything and I cannot get it to work at all.

Thank you.

Share this post


Link to post
Share on other sites
"It is like it is taking the entire image and trying to fit it into the reduced sized image. I want to just take a piece of that image and display it as it would normally look."

So do you actually see something on the screen right now?

So let me get my dense head around this statement.

These sizes are fictious. Are you saying you have texture object 0 and its say 1024x1024 in size and you have the subimage you want to update texture object 0 with and its 512x512 in size. So with your call to
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

x,y could be 511,511 so it updates one quarter of the texture image.

Now you want to see the whole texture object as 1024x1024 or you just want to see the 511,511 section you just updated? Cause if you want to see that portion you need to use new texture coordinates to offset to that location.

e.g.
glTexCoord2f(.5f, .5f);
glTexCoord2f(.5f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glTexCoord2f(1.0f, .5f);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this