working with super-big textures

greetings,

i’m working on a panoramic image viewer. the images that i’m using are fairly large, but not outrageously so – typically around 5000 x 2000 pixels.

at first i tried loading the pixels into the app and then copying a subarea of the pixels (around HD rez) to the a texture each frame, but that proved to be rather slow.

my next approach involved loading the image as a big texture and then using texture coorinates to draw a smaller subsection of the panoramic image. this worked incredibly well, but when i switched from one panoramic image to another, i opengl froze for a few seconds, presumably to activate the texture. can anybody recommend any ways to avoid this stuttering? dividing the image into smaller strips didn’t seem to do the trick.

thanks for any advice,

jeremy

but when i switched from one panoramic image to another,

what exactly do you do when you switch from one panoramic to the other? Is that when you load the image? or are they all loaded at startup? How many images do you have? and what hardware are you running on?

I am pretty sure that sending more than one texture of that size to the GPU is propably causing the freeze. I would try to make tiles of the panaomorama images at startup and draw them as extra rectangles. Then you can use some kind of frustum culling or something simpler for your use propably since it’s 2D and test what tiles you have to draw, so you only send the data to the GPU that is needed.

right, this is on a mac book pro 2.4 GHz with a GeForce 8600M GT card (258 MB VRAM). i also had the same problems with a new mac mini – which is the machine that this installation will be running on.

images are loaded at startup. and the transition is a slow fade from one panoramic image to another. sometimes the stutter happens for the duration of the 5-second fade.

i tried cutting the texture up into 36 slices and just using a few of them, which seemed to mostly alleviate the stuttering (it still happens intermittently). i’m thinking that there might be other memory problems with my app.

this kinda proves to me that my grasp of how gl works is a little rough. what happens when i run out of memory on the card (i’m using about 14 images)? should i be clearing the textures when they’re not being used and then sending the data again?

thanks, as always, for the useful advice,

jeremy

well at 5000x2000 each image will come in at about 30MB (if they don’t have alpha). So you can only fit about 6 of these in your VRAM. When you try to upload a new texture and your VRAM is full, your opengl driver will swap out an old texture to ram and swap in the new texture, then swap back in the old texture if and when it’s needed. (actually i think this depends on opengl implementation, some may just give an error - but I think thats rare).

The logical thing that comes to mind is to:

  • upload textures 1-4
  • fade from 1->2 and in the background upload texture5
  • when 2 is fullly visible, unload texture1, start fading to texture3, and in the background start uploading texture6
  • etc.

of course the tricky thing is the background upload, since multithreading and opengl don’t mix very well. you have a couple options here:

  • Zach posted some code on the forum about how he background trickle uploaded textures for a project a while ago.
  • chop the textures into little bits and upload a new one every now and again
  • I think right now the best way to do it is using PBOs. The data transfer is asynchronous, so when you issue the ‘upload’ command (glTexImage2D), control returns to your app immediately and opengl takes care of the data transfer in the background - as opposed to doing it the normal way, when you issue glTexImage2D your app waits until the upload is over and then control returns.
    http://www.songho.ca/opengl/gl-pbo.html

of course before doing all of this I"d recommend just trying your current app with just 2-3 textures to make sure there are no other bottlenecks with textures at that size (e.g. drawing).

well at 5000x2000 each image will come in at about 30MB (if they don’t have alpha). So you can only fit about 6 of these in your VRAM. When you try to upload a new texture and your VRAM is full, your opengl driver will swap out an old texture to ram and swap in the new texture, then swap back in the old texture if and when it’s needed. (actually i think this depends on opengl implementation, some may just give an error - but I think thats rare).

The logical thing that comes to mind is to:

  • upload textures 1-4
  • fade from 1->2 and in the background upload texture5
  • when 2 is fullly visible, unload texture1, start fading to texture3, and in the background start uploading texture6
  • etc.

of course the tricky thing is the background upload, since multithreading and opengl don’t mix very well. you have a couple options here:

  • Zach posted some code on the forum about how he background trickle uploaded textures for a project a while ago.
  • chop the textures into little bits and upload a new one every now and again
  • I think right now the best way to do it is using PBOs. The data transfer is asynchronous, so when you issue the ‘upload’ command (glTexImage2D), control returns to your app immediately and opengl takes care of the data transfer in the background - as opposed to doing it the normal way, when you issue glTexImage2D your app waits until the upload is over and then control returns.
    http://www.songho.ca/opengl/gl-pbo.html

of course before doing all of this I"d recommend just trying your current app with just 2-3 textures to make sure there are no other bottlenecks with textures at that size (e.g. drawing).

P.S. sorry for the double post, forum 404’ed on me on first submit :confused:

hey memo -

the project requires that users select which panorama they’re viewing, so adding and removing textures in a given order won’t help to alleviate the problem.

i ended up building a transition to alleviate the problem of drawing 2 large textures simultaneously, which also looks nice because the images are fairly tightly aligned: swap 1 panel at a time (from left to right, or vice-versa).

thanks for the explanation about filling up the vram. i’ve been meaning to look into PBOs.

take care,

jeremy