PDA

View Full Version : Best way to manipulate textures



force
09-20-2010, 03:08 AM
Hello.

I'm new to this, I can't figure out which is the best way I could achieve.
I've been using SDL so far and I find it slow, so I'm moving my graphic part to OpenGL. The game is completely 2D and I've disabled depth buffer and I'm using glOrtho().
I've loaded my images (textures) successfully into OpenGL and draw them on the screen. using GL_Quads and vertexes.

I'm a pixel-freak, I used to get pixels from my SDL_Surfaces and replace them AND I used to draw primitives (circles, boxes or any polygon) onto these surfaces.

Which way is faster and more standard:
1. After loading my SDL_Surface into OpenGL texture, I keep the SDL_Surface, when a pixel-replacement/draw-shapes is needed, I do it on the SDL_Surface, then I replace the OpenGL texture with the new SDL_Surface?

2. I do all the changes directly on the OpenGL texture? (Delete SDL_Surface after it is loaded in the OpenGL texture)

If it is the second, could you please show me how to pixel-manipulate/draw-shapes on OpenGL texture?

I load SDL_Surface onto OpenGL like this:


GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, SDLImage->format->BytesPerPixel, SDLImage->w,
SDLImage->h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
SDLImage->pixels);

BionicBytes
09-20-2010, 04:21 PM
Can't you just draw everything with OpenGL and forget sdl?
You may find you won't need to draw to a texture and your performance should increase as a result

force
09-20-2010, 10:12 PM
I'd love to forget about SDL :)
I have events happening in the game which alters the game textures. That's kinda my whole game concept. I can't skip that.

Is it really that expensive modifying a texture in OpenGL? If it is, then I guess I HAVE TO have a copy of the texture in SDL so that I alter the SDL version and update the OpenGL one with the result.

ugluk
09-21-2010, 02:17 AM
Both are optimal performance-wise, but you probably want 1.

basically, an OpenGL texture is just a bitmap without SDL's header crap (i.e. just the ->pixels). So, if you need to modify your textures you need to keep the ->pixels somewhere, if the texture is not modified anywhere, then you can delete your surface(s) after uploading the texture. There is no way I know of to draw on your texture after it is uploaded onto the GPU, you can only sample it; that is you can only download it back to the system memory again, modify, then reupload (maybe some more experienced reader can chime in on this). This would hit your perf though, so do this only if you're short on system memory.

As Bionic probably wanted to imply, sometimes you can combine textures on quads 1 on top of the other in multipass rendering, and/or you can multitexture, combining 2 textures, thereby avoiding modifications.

force
09-21-2010, 03:24 AM
Thanks for your reply. I got a better image of the whole thing now :)

It has been a while since I was looking for the answer, but I only came to this (http://www.devmaster.net/forums/showthread.php?t=4892), in the last post it says modifying the texture on OpenGL will be incredibly slow since graphic cards are not designed for that.


This would hit your perf though, so do this only if you're short on system memory.

You meant if I have "enough" system memory to do this?

hmm on more thing.
Say I have a texture, a very big rectangle. (10000 x 10000) then I wanna draw a small circle some place on it. Should I "download" only that part of rectangle for the circle into system memory and then upload it? Or it won't make much difference if download/upload the whole rectangle? (edit: 10000 x 10000 x 4 = ~380 MB, I assume I gotta download partially, how do I transfer from GL to SDL_Surface?)

and lastly,


glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, ModifiedSDLImage->format->BytesPerPixel, ModifiedSDLImage->w,
ModifiedSDLImage->h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
ModifiedSDLImage->pixels);


That will be my "upload/update" way?

ZbuffeR
09-21-2010, 04:26 AM
To update a small part of a texture, you can use glTexSubImage2D.
However for best results, you should pass a pointer to a small part of the ModifiedSDLImage, meaning you have to work on small tiles on the CPU side.

For better performance, try to update a texture only when it is not used, ie. keep a "double buffer" for each texture. It will introduce one frame lag, but should allow much better performance.

As a side note, you may be able to perform the texture modification all on the GPU with render to texture (FBO).
Then it depends if the modifications can easily be done on the GPU ... lines ? triangles ? something else ?

ugluk
09-21-2010, 05:38 AM
Yeah, if you don't filter your textures, you have a perfect setting for texture atlas use. This will hopefully limit the amount of texture binds you do.

And sorry for not being clear in my post; you need to download only if you free the SDL surface you create your texture from.

Don't think that because you use OpenGL, performance will automatically increase. It probably will on newer cards, but on older ones, this is not 100%, if you aren't careful.