This article will discuss the need for, and creation of, a Singleton Texture Manager in OpenGL. By using a Singleton, we ensure that the Texture Manager class has only one instance, which we can use to handle all texture loading/deleting operations. If implemented properly, this tool could be a great benefit to game programmers, as it gives a viable and simple means for managing a large number of textures at once. For some beginning programmers, this may be their first glimpse of the Singleton pattern.
The graphics of today's games have often defined the difference between success and failure. Developers are often questioning themselves how much, how fast, how detailed their graphics should be. Oftentimes, the textures of a game can determine how realistic the game looks and feels. Luckily, programmers have access to API's like DirectX and OpenGL that aid in optimizing texture rendering in complex scenes. The problem that we run into, however, is that we need a way to keep track of all of the textures in the game scenes. In a simple game with a wall, a floor, and a player skin, you shouldn't have many problems, but when changing levels, loading a WAD file, or applying skins to every new model that enters the scene, you need some way to keep track of the textures that are being used or you run into problems. In this article, we will discuss how we can combat these problems through a Singleton Texture Manager with the OpenGL API.
OpenGL and Textures Overview
Every texture in OpenGL is referenced through a unique ID through the glBindTexture() function. Now, you can either specify this unique ID by yourself and have the responsibility of handling all new texture ID's, or you can let OpenGL find a currently unassigned ID with a call to the glGenTextures() function. With the latter approach, you only need to keep track of every ID the function returns.
Whichever method of texture ID generation you choose, you're still left with a seemingly random list of numbers coming and going as quickly as you can say 'jibs'. Even worse, when you're finished using a texture with a given map/object/effect, you need to find the texture's ID again and call the glDeleteTextures() function, which will recover the video memory that was allocated by the texture for re-use.
Although keeping track of a list of numbers may not seem like a real problem, if you have ever had code like this:
glDeleteTextures (1, &m_Player->GetProjectiles ().rocket [nDeadRocket].GetTexture ().nID);
then you might change your mind about how to handle a list of numbers.
What we need is a class or object, which will sit in memory and manage every texture going in or out of our program. It will keep a list of all texture ID's, provide the functionality to delete textures, and also the functionality to give us a list of the number of textures loaded and their unique ID's. If the application sticks to a strict texture ID naming convention, such as:
Map/World Textures > 256
then we could easily look up and delete every texture of a specific type automatically.
This seems simple enough, but what if we load a texture in some remote function in the nether-regions of our code? We simply cannot create an instance of this class as a member variable for one of the main systems of our game and hope we put it in a place where it will have the most effectiveness. Even worse would be a series of texture managers keeping their own list of texture ID's.