It's free to join Gamasutra!|Have a question? Want to know who runs this site? Here you go.|Targeting the game development market with your product or service? Get info on advertising here.||For altering your contact information or changing email subscription preferences.
Registered members can log in here.Back to the home page.

Search articles, jobs, buyers guide, and more.

By Richard Wright
Gamasutra
July 23, 1999

Letters to the Editor:
Write a letter
View all letters


Features

Contents

Introduction

A First Try at Texturing

An Intuitive Improvement

Where's the Beef?

Using Texture Objects

Texture Management

Texture Priorities

Texture Management

So, now we know that texture objects are the way to go for managing our textures. We load each texture into a texture object, and then bind to the appropriate texture whenever needed. Piece of cake, right? Well, there are still a few things that we need to keep in mind. In our example program, once we loaded and bound all seven textures, we switched textures thirteen times during the rendering of the two cubes and marble floor.

Some consumer OpenGL hardware (such as the i740) handle this texture switching very quickly and efficiently. Deep down in the driver, texture switching amounts to little more than changing a single pointer value. Unfortunately, we can't make this assumption for most hardware. One of the reasons that the i740 is so good at this is because it textures directly from AGP memory. An i740-based AGP graphics card has no local texture memory, so all textures are accessed at roughly equivalent efficiency.

Most other modern AGP and PCI graphics cards usually have some memory on board the card for texture storage. These boards can cache a considerable amount of texture directly on board. Accessing these local textures is very efficient when using texture objects. Although still phenomenally faster than reloading the textures with glTexImage2D(), switching between texture objects can still have some performance overhead. This is especially true if you're using different texture filtering parameters, or perhaps different sized or nonsquare textures. Just how much overhead texture switching introduces will vary depending on which vendor’'s card you're using.

The example program REFLECT_SORTED.EXE rearranges the cube drawing code to draw faces of the two cubes with the same texture together. I won't reprint the code here, but it is horrid to look at. The code performs a great number of transformations and pops them off of the transformation stack as we swap back and forth between the upper cube and the reflected and scaled down cube below the marble floor. While a more elegant solution to texture sorting is desirable, just what this will look like will depend greatly on your own rendering engine. The code shown in the REFLECT_SORTED.CPP source file is meant to demonstrate the concept, not necessarily show the best possible way to do this for a general situation. The difference in frame rate with the ATI AGP graphics card was interesting — we dropped one frame per second. You should benchmark your own code. Texture sorting may not always pay off. I think the difference might be more positive in a real application, with many more textures being swapped to and fro. The amount of texture memory available can also have an influence on the effectiveness of this technique.

While binding textures saves the driver from having to reload and reformat texture data each time it's accessed, it is possible that texture data may still need to be shuffled back and forth between local memory (resident) and either AGP or system memory (not resident on the graphics card). Again, some drivers might consider AGP memory to be resident. Don't pay any attention to what the Intel documentation tells you regarding resident memory. Hardware manufacturers are not all handling resident memory in the same way. Their marketing literature calls it whatever they want, and you're left to fend for yourselves (that's the hard reality of being a developer).

The REFLECT_SORTED.EXE program might actually show a substantial performance increase on some hardware. If, for example, we were running on a board with a very small amount of texture memory available (say, one of the older 4MB boards), then the extra processing headache may pay off because it would still be far less time consuming than reading entire textures multiple times over the PCI bus. A related topic that is beyond the scope of this article is state sorting. Texture sorting is a simplified case of state sorting. When state sorting, you render all geometry of like state together (lit objects, unlit objects, textured objects, nontextured objects, and so on). State sorting is still a tremendous performance optimization technique and should not be ignored. You might be surprised by how much of a performance hit you take from a single glEnable()and glDisable() call. As we've seen, within the textured state, sorting again by texture object can still provide further optimization opportunities.


Texture Priorities


join | contact us | advertise | write | my profile
news | features | companies | jobs | resumes | education | product guide | projects | store



Copyright © 2003 CMP Media LLC

privacy policy
| terms of service