views:

51

answers:

2

Hello,

I'm writing a simple 3D engine based on OpenGL (I know there are plenty of them out there but for some reasons I want to learn how to do this myself). I am pretty happy with my current approach of a scene graph and stuff like that but I'm very unhappy with texture handling. So I wonder how to do this properly.

When I look at example code on the internet then they never speak about how to manage textures. They just load some textures on application startup, show their demo stuff and then the program exits. But what if I change stuff in the scene pretty often? What if I want to display a scene with 10 textures and then I remove a node in the scene so 2 textures are no longer needed and then I add a new node with 4 new textures. So the 2 old textures must be removed from the Video RAM and I have to add 4 new textures. Then I completely replace the whole scene so again all unused textures must be removed and new textures must be loaded while textures that were used before and are also used in the new scene must be re-used. This sounds pretty complicated.

How are textures managed in professional 3D engines? Is it a global singleton texture manager which tracks texture usage with reference counters and cleans up the video memory from time to time? Or is there a more genius method to do it?

+2  A: 

If you're implementing it in C++, the "easiest" way would just to have a Texture class that can load and unload itself. Whenever an object loads, it also loads up the textures it needs. When that object goes away, it destroys the textures that it loaded, thereby unloading them.

A solution in C would be similar; you have a struct that contains enough data to "unload" that texture when it's time to take it out of vram and free its resources.

This is basically what we do on "professional games," although on the series I'm currently working on each world area pulls in all of the textures that it needs, so every object in that area that has the same texture shares the same texture data. Adjoining areas may have objects with the same source textures, but in that case we just let there be two copies in memory as the management is much easier.

You could get tricky with reference counting and a global manager, but then you'll also need to come up with a scheme for defragmenting memory and so on and so forth that is a fun academic exercise but which ends up causing too much trouble as the project nears completion.

dash-tom-bang
A global manager with reference tracking and memory defragmenting is the only thing I've used professionally, so I would certainly say its a workable solution.
BigSandwich
Certainly, I just feel that the costs are very high and the value only starts becoming apparent when you have a lot of people throwing a lot of assets at the game.
dash-tom-bang
+2  A: 

I think something you need to realize here is that the problem you are trying to solve is not unique to textures but to all of your game resources. I think the best solution is an automated method of dependency tracking combined with ref counting. For each "thing" you want in your game, you should have some sort of root file that references every other asset (sounds, textures, models, particle effects) that that "thing" uses. You should have some sort of tool or build script that will package up all of the assets for each item. Before you create any of your "things" you load the appropriate package. Every thing you load addrefs the package, and in turn the package addrefs all of the resources that are loaded. You know its safe to remove resoures or whole pacakges once the ref count goes to 0.

Another good thing about this approach is that you can give yourself memory budgets, and check them at build time rather than run time because you know how big each package is. Also, packages can share resources, so you can make sure not to load them more than once if another package has already addrefed it.

BigSandwich