• Advertisement
Sign in to follow this  

Copy regions of a texture

This topic is 3626 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have an Image class for my 2D game, it uses SOIL to load an image from file and create a texture. I store the texture id in my Image object. My plan is to texture map a quad when i want to draw the image, this is so that i can easily change the colour by setting the vertex colours. So i can use a greyscale image and colour it. Now, what i want to do is split one image (texture) up into smaller ones. I give the function an array of structs that have the x, y, width and height of each small image. I want to use something like glCopyPixels or something. It would be good to create textures straight from it but if i end up with raw pixel data i can use SOIL to create a texture from it. thanks

Share this post


Link to post
Share on other sites
Advertisement
Oh, yes. I think i have used that before. But doesn't that copy the screen buffer to a texture? I want to copy a texture to another texture.
I was just thinking that i may store the image data in the object and draw the pixel data to the screen instead of texture mapping a quad. But i remembered that i need to either tile or stretch the image. Using a texture i can use GL_REPEAT or GL_CLAMP when i create it, that way i don't have to do it myself. But can you do that by drawing pixels (glDrawPixels is it?) I guess i could tile the image myself but can it stretch the image?

EDIT: Mmmm, i just realised that i can use glPixelZoom to stretch along x and/or y axis but now i have another problem. How to rotate!? I am planning on rotating images, i.e. if the player shoots their gun. They can aim up/down so i would draw the weapon fire (say, for a laser gun) as a quad rotated by the aim angle. But i can't easily (if at all) rotate pixel data. I think i will make another class called Sprite which has the image as a texture, and Image will contain pixel data. Does that sound good? (i've never made a game before so i am acomplete n00b at this)

Share this post


Link to post
Share on other sites
Hi Xtal256.

You could use render-to-texture functionality. The splitting can be done by rendering parts of the large images to a framebuffer attached texture. You probably want to look at the FBO extension (see http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt) if it's supported.

Else you would have to render it to your regular framebuffer first (see OpenGL Programming Guide, chapter 10), then copy back the subimages with glCopyTexImage.

Share this post


Link to post
Share on other sites
Mmmm, i think i used a framebuffer once before but i couldn't get it to work. I don't think it's supported by my crappy video card.

I have just made another class, Sprite, like i described above. But i need to split Sprites as well as Images. I could easily create a texture from raw data so i think i will do it the second way ndhb said.
I have done this stuff once before where i copied the screen to a texture for a Windows Media Player visualization but it was a while ago, i will have to go back and look at it.

Share this post


Link to post
Share on other sites
Why do you need to split your texture up? If you were thinking of using spritesheets or something similar, generally all you need to do is assign different texture-coordinates to your quads. Same thing for rotating and scaling images, just rotate and scale the quad.

[Edited by - Luctus on March 15, 2008 8:11:43 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Luctus
...Same thing for rotating and scaling images, just rotate and scale the quad.

Yes, that's what i'm doing. But i can't rotate pixel data, which is the problem i had. I fixed that problem by deciding to use textures for rotating, etc and just an array of GLubyte pixel data for images that don't need to be rotated (the 'map', GUI buttons, etc).

Ok, i am really confused. I don't know whether to store images as raw pixel data (GLubyte*) or as OpenGL textures and store the texture id as a GLuint. Is there a best way or not, 'cos i want to use the second method but i don't know if it will work for everything i want to do. For example, my map will be deformable so the player can blow a hole in the wall, etc (like Worms). So i will need to manipulate individual pixels which means i will need to use raw pixel data.

Share this post


Link to post
Share on other sites
Rotate pixel data.......uh what? What are you trying to accomplish?

If you rotate the quad then you have the pixels rotated..

Share this post


Link to post
Share on other sites
You don't seem to understand me. If i understand correctly, OpenGL allows you to work with images in two ways:
1. Create a texture from an image then draw a quad with that texture,
2. Use the raw pixel data, a pointer to GLubyte, and use glDrawPixels.
Using the second way, you cannot rotate the image. That is, you cannot call glDrawPixels with an angle, it just draws a rectangle. I don't want to use that method since i want to rotate, but i also need to manipulate individual pixels which i don't think you can do with a texture since it stores the data internally and only gives you an id. I think i have figured out what i need to do.

Share this post


Link to post
Share on other sites
Quote:
Original post by XTAL256
You don't seem to understand me.
No, I'm afraid not.
Quote:

If i understand correctly, OpenGL allows you to work with images in two ways:
1. Create a texture from an image then draw a quad with that texture,
2. Use the raw pixel data, a pointer to GLubyte, and use glDrawPixels.
Basicly, yes.
Quote:

Using the second way, you cannot rotate the image. That is, you cannot call glDrawPixels with an angle, it just draws a rectangle. I don't want to use that method since i want to rotate[...]
I really can't think of a case where you'd want to use glDrawPixels, no.
Quote:

[...] but i also need to manipulate individual pixels which i don't think you can do with a texture since it stores the data internally and only gives you an id.
If you really can't pre-generate all the picture data you need and have to modify it dynamicly, then you're in a whole different ballbark and would probably be best off using some kind of two-pass rendering method using pbuffers or something similar as have already been hinted at.

Anyway, I'd first recommend you to read through the OpenGL Red Book (newer editions are avaliable in print), especially the chapter on texturing.

Finally, to give you a hint of what I was talking about, this is almost verbatim (at least conceptually) what I'm using in my sprite engine:

typedef Texture GLuint; // introduce a new name for opengl textures

struct Rect
{
float x, y;
float width, height;
};

struct Frame
{
Rect tc; // The texture coordiantes of the sprite frame
Texture t; // The texture of the sprite-sheet
};

struct Sprite
{
hashmap<String, vector<Frame&> > animations; // mapping from animation to sequence of frames
Rect r; // the size of the sprite on screen
};

struct Actor
{
Sprite &sprite;
Matrix transform; // Any transformation to the sprite, including scaling, translation or rotation.

String current_animation;
int current_frame;
};

/* ... */

void render( Actor a )
{
glPushMatrix( a.transform );

Frame f = a.sprite[a.current_antmation][a.current_frame];

// I don't really use glBegin/glEnd, rather a vertex buffer, but for the sake of illustration...
glBindTexture( GL_TEXTURE_2D, f.t );
glBegin( glQuads );
glTexCoord2f( f.tc.x, f.tc.y ); glVertex2f( a.sprite.r.x, a.sprite.r.y );
glTexCoord2f( f.tc.x, f.tc.y + f.tc.height ); glVertex2f( a.sprite.r.x. a.sprite.r.y + a.sprite.r.height );
glTexCoord2f( f.tc.x + f.tc. width, f.tc.y + f.tc.height ); glVertex2f( a.sprite.r.x + a.sprite.r.width, a.sprite.r.y + a.sprite.r.height );
glTexCoord2f( f.tc.x + f.tc.width. f.tc.y ); glVertex2f( a.sprite.r.x + a.sprite.r.width, a.sprite.r.y );
glEnd();

glPopMatrix();
}


Pardon for any syntactical or logical errors, I don't generally code in C++ and also aren't quite awake at the moment.

Hope that helps.

Share this post


Link to post
Share on other sites
Yes, i think i will read chapters 9 and 10 of the red book. I have glanced at it before but never really read it.
I seem to have it figured out, i am going to use two different ways. I will use a texture for most images but my map will use the second method. See, the main feature of my game will be that the terrain is deformable. Like Worms, the player can destroy bits of the terrain with their gun, but i will also have dirt that can fall down. I will use a system similar to this game, but a lot similar. The point is that i need to work on individual pixels. I have come up with the following classes:

class MetaImage { // Defines info about image, doesn't specify how image data is stored
public:
int width, height; // Width and height (in pixels).
int repeatMode; // Stretch or tile

inline int size() { return width * height; }
...
};

class Image : public MetaImage { // Store image as OpenGL texture
public:
GLuint id; // Texture id

Image(String filename, int mode = IMG_STRETCH, int w = 0, int h = 0);
...
};

class Bitmap : public MetaImage { // Store image as byte array
public:
GLubyte* data; // Pointer to image data

Bitmap();
...
/* Retrieve individual pixel */
inline int pixel(int x, int y) { return data[y*width + x]; }
...
};

drawImage(...); // Draw texture on quad, rotated, scaled, etc
drawBitmap(...); // Use glDrawPixels


I think that is sufficient for what i need and not too complex.

btw, why are you using a hashmap for your frames, why not just an array?

Share this post


Link to post
Share on other sites
Quote:
Original post by XTAL256
I will use a texture for most images but my map will use the second method. See, the main feature of my game will be that the terrain is deformable. Like Worms, the player can destroy bits of the terrain with their gun, but i will also have dirt that can fall down.
Ah, I understand then. You might want to profile glDrawPixels against re-uploading a modified texture each frame as I'm not entirly sure which one is most effecient. Also, you might want to look into wheter using the stencil buffer would be possible.
Quote:

btw, why are you using a hashmap for your frames, why not just an array?
No specific reason really. I had a lot of sprites with few animations in common between them and identifying them using strings proved to be quite easy to use. But any associative container could have been used without there being much difference.

Share this post


Link to post
Share on other sites
I would say glDrawPixels would be better that creating a texture each frame (although that's what i did with my WMP visualization). I might read up on stencil buffers and all that, just to get an idea of how to do it. It's just the map that will require pixel manipulation, everything else i can just use a texture which is pretty easy.
thanks

Share this post


Link to post
Share on other sites
Updating a texture and rendering it as a quad should always be faster than drawing pixels. Just make sure you're not updating the texture in some stupidly inefficient way like actually deleting/creating textures each frame, or building mipmaps. Try glTexSubImage2D, and only update the part of the texture that you modify each frame.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fingers_
Updating a texture and rendering it as a quad should always be faster than drawing pixels.

Wow, really. Why is that?
Remember, i need to manipulate pixels so it would be inefficient to use a texture because and as far as i know creating an OpenGL texture actually copies the pixel data:

texture = LoadTexture(); // Load texture
glGenTextures(1, id);
glBindTexture(GL_TEXTURE_2D, *id); // Create texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
free(texture); // Delete image data



So like you said, deleting/creating textures each frame. But i still could only draw the updated parts of the image.

Share this post


Link to post
Share on other sites
Quote:
Original post by XTAL256
Quote:
Original post by Fingers_
Updating a texture and rendering it as a quad should always be faster than drawing pixels.

Wow, really. Why is that?


First, because drawing texture-mapped polygons is generally what modern GPU's and their drivers are designed to do so these functions are guaranteed to be hardware accelerated. Secondly, because this means transferring less data to the GPU (only the part of the texture that changes and only when it does, not the whole thing every frame).

Quote:

Remember, i need to manipulate pixels so it would be inefficient to use a texture because and as far as i know creating an OpenGL texture actually copies the pixel data:
*** Source Snippet Removed ***
So like you said, deleting/creating textures each frame. But i still could only draw the updated parts of the image.


You don't need to delete/create the texture each frame to manipulate its contents. You only need to create the texture once with glGenTextures and glTexImage2D, and then do partial updates whenever something changes. As I said, glTexSubImage2D is the most straightforward way to do this.

This does mean keeping a copy of the texture in RAM, but you also need that in order to do per-pixel collision tests against the terrain so it doesn't really add any overhead.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fingers_
You don't need to delete/create the texture each frame to manipulate its contents. You only need to create the texture once with glGenTextures and glTexImage2D, and then do partial updates whenever something changes. As I said, glTexSubImage2D is the most straightforward way to do this.

This does mean keeping a copy of the texture in RAM, but you also need that in order to do per-pixel collision tests against the terrain so it doesn't really add any overhead.

Oh, ok. That will be a lot of RAM if my map is, say 1024x512, but since that will probably be the biggest object in that game it won't be too bad. And i guess OpenGL needs to keep a copy of the texture (when you do glTexImage2D(GL_TEXTURE_2D, ..., texture)) so it can store it in video RAM (even though my laptop doesn't have video RAM, it's 128Mb shared).
Also, i will need to keep an array of terrain types. I am going to have different terrain like dirt and rock. Rock will be solid whereas dirt will fall down like in the link i posted. So each pixel will need a corresponding terrain type. My point is that i will need to keep an array of (width x height) just for terrain, so keeping a copy of the texture won't be any different.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement