Lots of small textures or fewer large textures?

I’m going to be writing a program that will be zooming in and out on very large images (10000+x10000+).
I’ve already tiled the image into lots of 1024x1024 tiles at different LODs (essentially doing my on pre-mipmapping).
I’m also writing a texture manager to load the appropriate textures when the image gets panned etc…

I was wondering if rendering smaller textures (256x256 for example) and having more of them is better for performance than rendering fewer larger textures.


Can’t you simply leave the texture size as a parameter and compute the neccessary amount of textures from this? So your program would be flexible and you can find out what’s fastest (although I guess if it’s just about zooming in and out of one image, speed will not be an issue). Also, I would only calculate the highest level textures and would mipmapping automatically take care of the rest.


I don’t think I can use mipmapping because then I would have around 100 base textures (assume 1024x1024 base texture with a 10000x10000 image)…that’s A LOT of texture memory once you throw in the mipmaps.

And yes I can generate tiles that are of smaller sizes, but I was just wondering if there was an obvious up-front answer…

[This message has been edited by jlamanna (edited 01-06-2004).]

There is some performance impact inherent in binding to a texture, because this is state change. So in general, it is better to use one large texture than many small textures.

However, this impact may be much smaller than the impact of thrashing textures out of AGP space, if your texture caching scheme is constantly maxing out VRAM usage.

As with most OpenGL performance questions, the best thing to do is just try it both ways on your target hardware and see which way works better.

It depends on the granularity of the pan etc.

Consider memory useage and what happens at the borders. When you start panning you have an instantaneous load with a tiled approach and that needs to be managed over time where several tiles need to be loaded simultaneously you must anticipate, how much anticipation and the padding required is a matter for experimentation but also affects the total texture space used since your border pad must accomodate all anticipated tiles. The smaller the tiles the less this load, however too many small tiles and you start to lose paging performance at all levels of your system.

The bottom line is there’s no simple answer anyone can give you. It may be best if your system can support several sizes and you can experiment which size works best.

[This message has been edited by dorbie (edited 01-06-2004).]

He already said he has MIP maps, so thrashing the texture cache won’t be a problem.

I think fewer, larger, will always be better.

If you’re doing filtering, you should set the textures up with border, or at least repeat the edge pixel of one texture at the beginning of the next.

regarding the mip mapping issue… I do not really see a difference between mip mapping and computing several LODd textures yourself? I just thought that mip mapping would make it more comfortable.

And like dorbie said, leave the size as a variable parameter and find out what’s best. I guess it also differs between different chipsets.

However I think a problem with tiling the image is that one might see the seams, which would make large textures more suitable. if your image is 10000 x 10000, you might use 3 x 3 textures each 4096 4096, or something.

Why are you doing this with OpenGL anyway? If it’s just for displaying a large image, simply doing everything yourself might be sufficient.


[This message has been edited by JanHH (edited 01-06-2004).]

The problem with conventional hardware based MIP mapping is that the image tile size reduces with resolution. That becomes impractical as you zoom and page. You must apply your own resolution based texture switch as your level of detail changes. There are many ways to implement this. I won’t talk about it in detail because I’ve worked on proprietary solutions to this problem.

[This message has been edited by dorbie (edited 01-06-2004).]

Originally posted by dorbie:
I won’t talk about it in detail because I’ve worked on proprietary solutions to this problem.

Publicly available information:
<a href=“http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL&p=1&u=/netahtml/srchnum.htm&r=1&f=G&l=50&s1=6,618,053.WKU.&OS=PN/6,618,053&RS=PN/6,618,053” target="_blank">

[edit: I edited the link text because it was causing the whole page to get stretched unreadably. You may have to cut/paste the pieces if the embedded link doesn’t work.]

I believe it’s licensable.


[This message has been edited by Cyranose (edited 01-06-2004).]

[This message has been edited by Cyranose (edited 01-07-2004).]

For the record, that’s not the only scheme I’m thinking of Avi. There are alternative approaches and improved solutions.

Originally posted by dorbie:
For the record, that’s not the only scheme I’m thinking of Avi. There are alternative approaches and improved solutions.

Agreed. Just trying to give you something you can talk about, Angus

Why would I need to when there’s an expert around?

Originally posted by dorbie:
Why would I need to when there’s an expert around?

Really? There’s a Pop’n Fresh on the board somewhere, but somehow I don’t think that’s Michael…

Seriously, I know a bit about it, but Chris and Phil did much much work on the texturing than I did. I’m a scenegraph and spatial algorithms kind of guy…

Anyway, to save Angus the trouble of typing this up, the key idea from the Universal Texturing patent is the idea of toroidal scrolling of a texture (one per LOD layer) rather than using adjacent tiles and MIP mapping.

By shifting the effective origin of the texture, one can subtexload the one or two slivers that are needed to complete a scroll, and therefore keep the texture properly windowed while minimizing texture memory footprint.

Do that for multiple LODs, and you have a fixed-size texture cube (not a true 3D texture, but shaped like one) you can scroll over a virtually unlimited source texture size, where you can go up and down the stack to find the right LODs per triangle.

Computing the proper LODs and doing the right per-pixel blending to make up for not using H/W trilinear is trickier.

Doing that for a whole planet of imagery is a bit trickier still, but if anyone wants to do that, I’d suggest talking to the patent holders about licensing or go another route entirely.


Originally posted by Cyranose:
the idea of toroidal scrolling of a texture (one per LOD layer) rather than using adjacent tiles and MIP mapping.

In other words, the 1985 trick.

arekkusu, I’m very interested, what specific prior art do you have in mind?

@cyranose: the images of the link you provided are broken; do they work for someone else?

@dorbie: I think, he means clipmapping specified by SGI as an OpenGL extension.

Limiting the discussion solely to updating edge strips of a 2d bitmap (windowing scroller) and shifting the virtual origin of the unchanged portion, how about this for starters: http://homepage.mac.com/arekkusu/GS/index.html#SMT

I think I still have the Merlin 16+ assembly source, somewhere.

In more recent work (this century) I do the same trick with real OpenGL textures, in the Tilescroller pictured here: http://homepage.mac.com/arekkusu/SW/other.html

I’m not trying to detract from your work, I’m sure there are plenty of novel ideas in the caching scheme. Just saying that “toroidal scrolling” is a new name for an old idea.

[This message has been edited by arekkusu (edited 01-07-2004).]

[This message has been edited by arekkusu (edited 01-07-2004).]

This all looks very similar to the clipmapping extension to me (Toroidal loading, around a region of interest…) I wonder if you could get away with saying you learnt it from clipmapping instead of from the crappy patent
Anyway just wait a year DirectX Next has virtual texture memory coming up


[This message has been edited by Pentagram (edited 01-07-2004).]

A friend of mine turned me on to OpenSceneGraph (http://openscenegraph.sourceforge.net) which does have support for LOD views.

I have quite some extensive experience in this matter. I currently support literally infinite size rasters (capped by the numerical precision), and have tested with rasters over 1M pixels wide. The memory consumption is quite optimial in that I only use about 16Megs video memory or less. I have even tesetd on loading thousands of these large images at the same time (overcoming system os file handle limitations), and the memory consumption has stayed the same (system memory consumption is also low, less than 20megs for over 2000 images). Roaming is also done in realtime with zooming/scaling/panning, no noticeable lag. Oh, its also 3D or 2D, so all pyramid layers can be active at any given time. What it boils down to in my opinion is as follows.

How fast can you load the 1024x1024 blocks of data? Even compressed, thats still a heavy chunk of data to be read in and decompressed on the fly. Threading is a must when dealing with large imagery, so you’re going to have to choose a compressor that is thread friendly (if not using a raw format). Some compressors take up too much cpu time, so unles you have a dual cpu, your second thread will drastically slow down your main thread.

How fast can you upload the data to OpenGL? That is quite a bit of data to upload. Even in a convenient GL data format, using sub loads may be too slow on older cards. It might be faster on newer cards these days, but you tend to get noticeable performance hits when using sizes that large. Even .1 seconds to upload the imagery is a very very big performance hit when the rest of your app runs at 500fps and sudenly drops down to 10 fps.

In general, what I have settled on is to use a selecteable block size for imagery (usually 128 or 256) with a selectable compressor for creating your mip map imagery (similar to TIFF). Alternatively, you can use pre-existing imagery (which I also seamlessly support). There are quite a few, and each have their limitations. Tiled TIFF, MRSID and ECW come to mind. Look into GDAL which wraps these libraries (http://remotesensing.org/gdal/formats_list.html) and provides a nice way to make your program import many other formats besides your native one. Develop your streaming architecture so that the actual GL texture block can be selected regardless of your image block size. That way you can experiment for yourself and choose a good block size. 128 is usually faster for me, but 256 gives a better visual appearance (or in general higher block sizes).

This is quite simply a GIS problem. This is actually the easy part, the hard part would be supporting other features on that raster, and making it dynamic. Hope this helps, lata.