Sign in to follow this  

Texture Manager

This topic is 4372 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Anyone have a recommendation on how to write a descent texture manager class for an engine? So far I'm looking at the Singleton, but for some reason I'm scowling at the idea thinking that there has to be a better way (not that anything is wrong with a Singleton, something just feels wrong about it... I'm sure you understand.) Simple question, that is all :) Thanks guys.

Share this post


Link to post
Share on other sites
I have to disagree with everyone else here, and say that I think a singleton is a bad idea. There are a few cases where multiple texture managers could be a good idea, lets say we have a Renderer class, and a texture manager singleton class. The texture manager needs a pointer to some internal data in the Renderer class because some of the textures should be stored in VidMem and D3D or OGL is needed to do this, there is no problem when we have a single renderer, but imagine we have two renderers. The first renderer renders to a 1600x1200 computer monitor and the other renders to another computer monitor, which is 340x280, both monitors have there own seperate graphic cards so we don't know what internal data to pass to the texture manager. In this case it would be a good idea for each graphic card to have their own texture manager, and each renderer could just have the texture manager as a private or protected member (assuming C++ or C#).

You might say that such a situation is very unlikely, but lets say you are testing a GameBoy game on the 340x280 monitor and you figured out you needed a tool to see what is happening in the AI of you creatures, this would require is to have two renderers pointing at two screens, which might have different graphic cards and one is fullscreen(the game) while the other is windowed(AI tool).

Share this post


Link to post
Share on other sites
Quote:
Original post by Red_falcon
lets stay on the carpet

yes its unlikely, normally we need one renderer. show me a hobby programmer who uses two screens for programming


I dont see why that is unlikely, I'm still very new to game programming and haven't completed anything, but when I will write the AI part of my engine I expect to provide a way to see the state of FSM, Fuzzy Logic, Networks etc. I will most likely give the user an option to start a new window which show all this information. Such a tool would be pretty hard to use on a single screen since the game will most likely require most of the screen space.

I plan to buy a 17" screen after christmas and use that when programming.

EDIT: Also, OT:
I would create a TextureManager class, it should be able to give you an ID (handle) which you could pass around when refering to a texture, when someone who have a handle need to actually get some data it sends the ID to a function in the texture manager. This would be the basic idea of how I would design a texture manager, of course there is lots of things I have left out.

Share this post


Link to post
Share on other sites
Quote:
Original post by Red_falcon
and for such a thing you need to use second renderer?

i saw some reports of idustry developers and they use for that command line output or normal windows window with text output or/and gdi for drawings to represent diagrams


Depending on what you are going to do in your tools, you might, you can in most cases create the application with standard Win32 controls and GDI, so it might not have been a very good example. Then imagine we have a FPS and we want to have two cameras, one mounted on the player (the standard camera) and one mounted on the AI player, or following the AI player. In this case you could use split-screen, but it would probably be a better idea with a monitor for each camera since if you have split-screen you will see less and you might not notice that the AI ignores players until they are 30 % into the screen.

If you are just doing a simple game and don't need a lot of functionality a singleton is probably fine, but the I have mainly chosen a non-singleton approach because of two things I can see lots of ways it can help me balance the game, observe what is happening and debugging, also I might later on figure out I need another screen for something which I haven't thought about and then I need to change a lot of code and if some people using my engine had already written code they would have to re-write it. Also I'm writing an engine I'm planning on making available online (open source) and I can never know what the users will need.

I think you should use a singleton, when you see NO cases where you might need multiple instances. You might say I will never NEED two instances, it is possible, but I will never need it, then when you have been working on the game (engine) for a year you find out that you do need two instances, or some other person using your code might need two instances.

Share this post


Link to post
Share on other sites
I'm working on my engine since a couple of months. I had tried many times before and used also multiple instances of whatever(renderer, window, texture manager), but nowaday i stick to singletons. For second cam i will use PIP(picture in picture). But that only my 2 cent opinion.

Share this post


Link to post
Share on other sites
A singleton is unnecessary in this situation, if not for a practical reason, than for a theoretical one. There is no reason why the engine should be limited to a single texture manager. Moreover, and perhaps more importanty, there is certainly no reason that the texture manager should be globally visible. This latter reason alone tells me that the singleton pattern is not the preferable one for this situation.

This same reasoning can easily be applied to the renderer, the sound system, etc. Hence, no components in an engine should be singletons, at least not in my opinion.

I'd say to just go along with the traditional composition methods, that is, store a pointer to a texture manager in the renderer, and let all classes using the renderer have a pointer thereto. Further, provide access to the texture manager through the renderer interface.

Of course, this isn't as easy as just going with the singleton, because you must pass the pointers around, but architecturally and theoretically, it is a better design because it helps enforce decoupling between disparate engine components.

Share this post


Link to post
Share on other sites
I would recomend using global variables. It seems similar to the singleton patern, but has some differences, and thus - advantages.

A global variable is a variable, that everyone knows how to get to. It does not have to be always the same variable. It could be a pointer to an instance of your texture manager, that, depending on context would point to one of two (or as many as you have) instances of texture manager class.
While processing different classes, you could be doing a tactical context switch once in a while, for another instaces of global variables. Other classes wouldn't even notice - they could be thinking they're using singleton pattern.

Extremely simple sample:

struct MYGLOBALS
{
MyDevice *m_pDevice;
MyTexManager *m_pTexMan;
MyEffectManager *m_pEffMan;
};
extern MYGLOBALS g_myglobals;

#define DevPtr (myglobals.pDevice)
#define TexMan (*(myglobals.pTexMan))
#define EffMan (*(myglobals.pEffMan))



For example, suppose you got two renderers. You're creating instances of, say, device, texture manager, effect manager, and what-more-you-want.
1. Create instances for the first device.
2. Place them somewhere locally in the main function, before you run your main-loop.
3. Assign them to global pointers (your semi-singletons).
4. Run initialization of all objects depending on those instances. They would think they are global, that realy simplifies things.
5. Create instances for second device.
-- Repeat 2,3,4.

You could do this tactical-swapping the same way during main-loop.


But I guess that having multiple devices or texture managers isn't too convincing (it is not to me[grin]), so here's a different, real-life example:

I'm currently working with creating graphical interfaces for some interactive content. There's a main module, that acts as an admin-interface, and as a controller for network and database connection. There are many interactive sub-modules, that can be turned on/off, loaded and unloaded during run-time, so we decided to put each one in its own dll.

Now imagine what would happen, if there was a singleton texture manager in each of those dlls. If you have a common button-texture for GUI, it would be loaded several times. What we would want, is:
- the ability to create "semi-singletons" on request only, and use already created instances when given
- reference counting on all resources - if one part is being closed, there is no need to get rid of global variables, but we would want to remove all resources used by the part being removed. I used intrusive_ptr<Tex*> as texture instance being passed around the program.


If you have a game with a few modules, like a 2D GUI, 3D levels, and a map editor, you might want to pack them into a separate modules, and load/unload when needed, especially on a not so high-end system.
Of course, it is not a thing to consider when writing small games, but it's good to know what your engine is capable of, and what it is not.


And in the end, all this I wrote to show that singleton pattern is not dead yet, although it may needs some modifications.

Cheers.
~def

Share this post


Link to post
Share on other sites
Multiple texture managers are also useful to logically seperate groups of textures, such as differing quality/resolution.

Either way, focus on making a texture manager. No reason to needlessly complicate matters. [imo]

Share this post


Link to post
Share on other sites
Well, my dilemma is whenever I try to create multiple instances of the texture manager, or, whenever I pass a pointer, or, whenever I create a singleton, no matter what texture I try to bind to - it always claims that all my textures are in use, and that it is drawing them, however, it is showing only the last loaded texture from memory.

In my texture class, I have information like:

GLuint textureID; // duh
string filename; // duh

When I make a call like so:

texture_manager->bind(filename);

It goes through an array of texture objects trying to match filename to the texture objects filename, then calls the bind() function. Calling bind it prints out:

cout << textureID << ": Binding " << filename << endl;

then calls
glBind(GL_TEXTURE_2D, textureID);

all goes well.

So I inserted a

if(glIsTexture(tTexture) == GL_TRUE)
cout << "Texture is in use." << endl;

and EVERYFRAME, even the first one, it claims they are in use. What gives?

Forgive lack of source code, its a semi-large project to just post on the web.
Also, for the record, GL is not producing any errors. And calling bind functions from the original instance created does work - however it doesnt functionally work out very well, as you can imagine.

Share this post


Link to post
Share on other sites
Naymind to all above. I am a fool.

Turns out I was trying to call a bind() from within a glBegin() and that's just no good according to the handy dandy reference guide.

Anyways, I've decided to go along with the idea of passing a pointer of the texture object around to where I need it. It may not be the cleanest code... but I find it so much more friendly (odd) then using a Singleton. Just seems more proper. Go figure.

Thanks for all the help guys.

Share this post


Link to post
Share on other sites
Quote:
Original post by deffer
I would recomend using global variables.

Whoa, global variables? I learned back in my C days to avoid global variables. They only get bigger, uglier, and they force an over exposure to header files. I'm against having the same headers visible everywhere, because once you edit one then everything has to recompile even if it wasn't affected by the changes. Header files (or at least user defined header files) should only be included where they are applied.

Anyway, I had a plan for my own texture manager. Here are few ideas for things to consider:
1) File types should be transparent to the user. - This is obvious, but you shouldn't need a different interface for loading each kind of file.
2) Some method for batch loading should be provided.
3) Be sure to destroy all the textures you create from OpenGL or D3D. I made the mistake of only deleting the texture data buffers. Also, once the texture is in video memory there is no reason to keep the pixel data for the texture unless you need to immediately use it. Otherwise, you can request it back from the video card later if needed.
4) Storing names for your textures can prevent multiple instances of the same texture from having to be loaded. My first implementation of this idea was done poorly. Now I believe that the best way to achieve this is to use an STL hash map (or equivalent) and use the file name as the name for the texture. That way, if multiple requests for the same texture is made then a quick check to the hash map can find if it has been loaded already. Futhermore, you don't have to think up a name for the texture as it is the file which you need anyway to load the texture. Two birds, one stone.
5) The texture objects themselves should have most of the methods that need to be performed on your textures. The texture manager for the most part only deals with adding and removing textures from its list of available textures. The texture objects should handle file loading.
6) Textures do not have to be static. Adding support for combining textures to make new ones is not too hard, and OpenGL has methods to aid in that process.
7) Allowing the user to create a texture outside of the manager and insert it may be useful. Say you whish to do some graphics processing on the texture before hand. For example the texture for a characters clothes may need to be changed with a custom inscription added to it.
8) Use a link list (STL list) to store the texture objects and allow the user to destroy textures that are no longer in use.
9) USING SMART POINTERS (boost shared_ptr) can greatly reduce headaches when having to deal with multiple systems that need the same texture. Texture objects should be stored in a referrence counted smart pointer so they can be shared without worry of one deleting the object before all systems are done with it.

Also, avoid singeltons and globals please. Just place the pointer where you need it. Chances are you won't need the texture manager in too many other places. Not everything that can have an affect on a texture needs the texture manager's interface. For example entities (NPC's and monsters) within your game should have a different inteface for things like changing clothes or switching to a texture that shows damage. You could simply use another class that keeps a list of smart pointers to those textures (you should not even need a pointer to the texture manager).

[Edited by - T1Oracle on December 19, 2005 3:40:38 PM]

Share this post


Link to post
Share on other sites
I disagree with the statement to avoid global variables

if you need multiple instance of an object this doesn t necessarily mean you have to avoid singletons

just use a multiton

I use singletons as template classes and pass the actual class I want to use as a template parameter

this allows you to create a template class that holds more then one instance at a time *multiton* and you can still use your objects the old way with pointers

where I need to state that the usage of pointers should be avoided as well as global variables

no global variables because you give other modules access to a module dependent object

also if you use the templated singleton approach as I do you can fairly easy replace it with another access alternative

One thing I want to add after reading oracles post:
Don t overuse singletons everywhere in your code, work with texture indices instead of directly calling the singleton everytime you only use the singleton where you really need to access it that is:
- at load time
- if you need a texture index
- in the end to release memory
- only in your graphics code and nowhere in your gameplay code, therefore you have accessor functions ...

Share this post


Link to post
Share on other sites
Quote:
Original post by dave_
Quote:
Original post by Basiror
just use a multiton


You've just made that up? Its certainly not a GoF pattern.


I had never heard of it either, but Wikipedia actually has an article on it here:

Quote:
From Wikipedia:
Multiton is a (disputed) term often used to describe a Singleton-like pattern that allows more than a just one instance to be created. While there is no official Gang of Four Design Pattern called Multiton, and the actual definition is disputed, at least one pattern that the term is used to describe is quite useful in software development.

The Multiton pattern takes the concept of the Singleton pattern and expands it into object pool. Instead of having a single instance per application (classloader in Java programming language) the Multiton pattern ensures a single instance per key.

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
Quote:
Original post by dave_
Quote:
Original post by Basiror
just use a multiton


You've just made that up? Its certainly not a GoF pattern.


I had never heard of it either, but Wikipedia actually has an article on it here:

Quote:
From Wikipedia:
Multiton is a (disputed) term often used to describe a Singleton-like pattern that allows more than a just one instance to be created. While there is no official Gang of Four Design Pattern called Multiton, and the actual definition is disputed, at least one pattern that the term is used to describe is quite useful in software development.

The Multiton pattern takes the concept of the Singleton pattern and expands it into object pool. Instead of having a single instance per application (classloader in Java programming language) the Multiton pattern ensures a single instance per key.


Fair enough but, even wikipedia says its disputed.

yesterdays news

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
I'd say to just go along with the traditional composition methods, that is, store a pointer to a texture manager in the renderer, and let all classes using the renderer have a pointer thereto. Further, provide access to the texture manager through the renderer interface.

And this, people, is the correct answer.

Share this post


Link to post
Share on other sites
Quote:
Original post by T1Oracle
Quote:
Original post by deffer
I would recomend using global variables.

Whoa, global variables? I learned back in my C days to avoid global variables. They only get bigger, uglier, and they force an over exposure to header files. I'm against having the same headers visible everywhere, because once you edit one then everything has to recompile even if it wasn't affected by the changes. Header files (or at least user defined header files) should only be included where they are applied.
[...]
Also, avoid singeltons and globals please. Just place the pointer where you need it. Chances are you won't need the texture manager in too many other places. Not everything that can have an affect on a texture needs the texture manager's interface.[...]


If you don't need a definition of texture manager in a particular translation unit, you clearly don't need any knowledge about global instance of texture manager. Why, oh why, introducing global variables would force you to include more headers?

Just using a texture don't force you to know about the texture manager/loader. The texture needs to.

Quote:
Original post by Promit
Quote:
Original post by nilkn
I'd say to just go along with the traditional composition methods, that is, store a pointer to a texture manager in the renderer, and let all classes using the renderer have a pointer thereto. Further, provide access to the texture manager through the renderer interface.

And this, people, is the correct a correct answer in a particular situation.


Fixed.
Clearly, that would be the ideal solution. But that's not always desirable. There's such thing as overdesign, and everyday we got to make a tradeoff between ideals and our precious time, which could be saved by using simpler things.

Share this post


Link to post
Share on other sites
Quote:
Original post by nilkn
Quote:
Original post by dave_
Quote:
Original post by Basiror
just use a multiton


You've just made that up? Its certainly not a GoF pattern.


I had never heard of it either, but Wikipedia actually has an article on it here:

Quote:
From Wikipedia:
Multiton is a (disputed) term often used to describe a Singleton-like pattern that allows more than a just one instance to be created. While there is no official Gang of Four Design Pattern called Multiton, and the actual definition is disputed, at least one pattern that the term is used to describe is quite useful in software development.

The Multiton pattern takes the concept of the Singleton pattern and expands it into object pool. Instead of having a single instance per application (classloader in Java programming language) the Multiton pattern ensures a single instance per key.




exactly what I consider a multiton ^^^

Share this post


Link to post
Share on other sites
Yeah I agree, a singlton is not needed in this case. I'm also writing a texture manager/tool at the moment, I'm actually thinking of allowing for two instances of it, one for the game, and the other (possibly), tied to the gui. The idea of this is that mostly gui textures might not be the same as in game textures, this would enable working with gui textures etc without needing to worry about in game textures. Of course theres always the ingame gui, so I don't know. But anyway I've still never had the need for singletons yet.
I think possibly some people think more of them than they need too. Perhaps they come under "optimising too early"?

Anyway, as to your question about how to make one, what I'm doing is firstly getting a list of all the textures, these will be got out of the folder where the game is, then making a second part which allows for more than one image on a bitmap. Eventually what you would have is something where all you have to do is pass a texture id/name and the texture manager will know where it is.

I think I possiblty avoided a bad idea somewhere because I used to think a texture manager just loaded any file anywhere, but I don't think it does, look at game editors, they always have texture paks you load and then assign textures from. In other words textures arn't just open ended they are defined somewhere, (when building the texture pak).

Instead of making a complete texture pak, I'm hoping to just do a text version, this will have the names of the textures, (rather than the textures themselves), then any subtextures in the file sort of like this;

  

//file starts with the number of bitmap chunks

int numbitmapdata;

infile >>numbitmaps;

infile >>bitmappaksize;

//read to a buffer, you will need to put the info into the
//structures where it will be used. As its only a text file it
//might even be better to read it in all at once and just parse
//directly to the texture manager on the fly.., this should then be
//all the info the texture manager needs to load the actual bitmap
//files etc.

infile.read(buffer, bitmappaksize);


//data for an area on a bitmap (sub image).
struct subimagedata{
int subimagedatabytesize;
int stringnamelength;
int imageID;
RECT areaonparent;
string stringnameID;
};

//For one bitmap, but allows for sub images on the bitmap

struct BitmapPak{
int bitmappaksize;
string bitmapname;
int BitmapID;
int bitmapnamelength;
int bitmaptype;
bool loaded;
int numsubimages;
subimagedata subarray;
};


//file parser here..
//Use binary mode for the files, its much easier in the long run,
//once you get used to it.



//load into a vector
vector<BitmapPak> bitmaps;










anyway thats how I'm hoping to do it, one thing is though, you need to get the info into the file in the first place, you could do this manually in a console app and then write it to file.

edit; a few typos.

[Edited by - Stevieboy on December 21, 2005 8:03:31 PM]

Share this post


Link to post
Share on other sites

This topic is 4372 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this