Skip to main content
GameDev.net gamedev.net
🔒 Locked

texture not binding / texture Manager

Started by Effron Feb 23, 2008 at 11:30 PM 7 replies 1.1k views
Original Post
Effron
Effron
OPTIONAL READING: So I wrote a bitmap (loading) class and thoroughly tested it. Everything working fine texturing with the bitmaps. So I decided to make a whole texture manager to basically do the main ideas: 1- Load all kinds of textures 2- modify texture parameters 3- "setup" a given texture for use -basically just enble textures and bind a given texName 4- remove textures The plan is basically to have texture ID's visible externally, these are actually just the index of the texture names array internally. QUESTION (problem) #1 I load a bitmap with my tested and true Bitmap class I generate a texture name, I bind the texture, create the texImage2d blabla... *snippet* glGenTextures(1, &texName[id]); glBindTexture(GL_TEXTURE_2D, texName[id]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmp.width, bmp.height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp.pData); //set some more general parameters after... The texture I am using was one tested on my bitmap class prior and worked fine. It's a simple 128x128 24bit bmp. But it no longer shows up ??? So I add glIsTexture(&texName[id]) right after this code and it is returning false. I step through the code, check the bitmap, it is loading, all the data is correct and it's there... where is the texture dissapearing to ? QUESTION #2 Is this an ok idea / model for a texture manager ?
MARS_999
MARS_999
Are you sure the texture object name that is returned from OpenGL is valid, and is it stored in your manager correctly? I don't know how you designed your resource manager, but I am assuming you are using C++, I would use std::map and save the texture filename with the texture id returned from glGenTextures(), and then you can reference that id value from the std::map, based of the filename.
JotDot
JotDot
glIsTexture needs the texture ID - not the address of it.

ie: "So I add glIsTexture(&texName[id]) right after this code..."
should be glIsTexture(texName[id])

source: opengl.org: http://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml
Effron
Effron
Re: reply #2
Sorry, copied that from a different part of my code, im passing the correct value in the class.

Reply #1:
Using map is a good idea, thanks.
I don't think thats the issue though. The way im doing it is a static array of size
const static int MAX_TEXTURES = 100;

and this is my manager BMP loader function which uses the bitmap class I was talking about

GLuint TexManager::loadBMP(char * file)
{
//load the bmp image
Bitmap bmp; //********** this is the tested bitmap class I wrote prior
if (!bmp.loadBMP(file)) //couldn't open
return 0; //0 reserved for errors

//get a free texIndex
GLuint id = getFreeID();
usedID[id] = true; //flag ID as in-use


glEnable(GL_TEXTURE_2D);

//allocate a openGL texture name
glGenTextures(1, &texName[id]);

//Bind the texture
glBindTexture(GL_TEXTURE_2D, texName[id]);

//test is the image size is a power of 2
if (isPow2(bmp.width) && isPow2(bmp.height))
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmp.width, bmp.height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp.pData);
else //not power of 2, need to load a mipmap
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, bmp.width, bmp.height, GL_RGB, GL_UNSIGNED_BYTE, bmp.pData);

//set some default parameters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

//*********** there is where I tried glIsTexture()

return id; //return the id of the texture
}


So in my test application, initGL() function
I use a global int texture
texture = texMan->loadBMP("test.bmp");

then in the displayFunc I do texMan->useTex[texture];

bool TexManager::useTex(GLuint ID)
{
if (!glIsTexture(texName[ID]))
return false;

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName[ID]);

return true;
}

And nothing works, but the thing is, If I take all the code from these functions and copy paste it all directly into the display function then it works :(






dmatter
dmatter
Quote:
Original post by Effron
The plan is basically to have texture ID's visible externally, these are actually just the index of the texture names array internally.

What is an ID? An integer?
Also, why are you mapping (integer?) ID's to texture names? Is a texture name a string or another (GL) integer?

It'd be helpful if you elaborate a bit more.

Quote:
QUESTION (problem) #1

I load a bitmap with my tested and true Bitmap class
I generate a texture name, I bind the texture, create the texImage2d blabla...

*snippet*
glGenTextures(1, &texName[id]);
glBindTexture(GL_TEXTURE_2D, texName[id]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmp.width, bmp.height, 0, GL_RGB, GL_UNSIGNED_BYTE, bmp.pData);

//set some more general parameters after...

So I'm guessing that id is an integer and texName is an array of GLINTS.
Has this array been allocated correctly?
Where does the id come from?

Quote:
I step through the code, check the bitmap, it is loading, all the data is correct and it's there... where is the texture dissapearing to ?

Check the OpenGL error state and see if there's anything there.

Quote:
QUESTION #2

Is this an ok idea / model for a texture manager ?

Well it's a 'manager', it can pretty much do or be anything you want.
The term manager is really generic and doesn't portray what the class is actually responsible for (unlike those 4 bullet points at the top of your original post).
Roughly speaking there are two reasons to use managers at all:
A way to subvert fixing a flawed design,
A way to obfuscate the actual purpose of the class in question.

If you find yourself using a manager it's an indication that it's time to pause and think about why you're using one, are you:
A) Cramming several responsibilities into one class, or
B) Is this manager really a façade, factory or pool?

Point A is a cause for concern, every class in your framework should have it's own, well defined and singular responsibility.
Point B is less problematic, fixable by either changing the name of the class to something more descriptive or by simply adding a note saying "this class is a façade for the texturing subsystem".

So where does this leave you?
Well it's easy enough to extract what classes you need from those 4 bullet points you gave:

Quote:
1- Load all kinds of textures
2- modify texture parameters
3- "setup" a given texture for use -basically just enble textures and bind a given texName
4- remove textures

Rather than have a single class bogged down with all that responsibility, split it up, here's one way:

An Image - a raw image, perhaps stored in a native bitmap format.
An ImageLoader - loads bmps, jpgs, etc into Images.
A Texture - perhaps simply maintains a texture handle, width, height etc.
A TextureFactory - a factory for creating Textures from images.
A TexturePool - facilitates adding/removing from a collection of textures.
A TextureSystemFacade - encapsulates the interaction of the above classes

Notice how each class has a simple, short 'n' sweet, easily understood and well-defined responsibility.
As a user of the texture subsystem all you do is interact with the TextureSystemFacade and perhaps the Texture class.
MARS_999
MARS_999
BTW GL uses unsigned int or GLuint, not GLint or int, for texture objects. You should use the data type that GL wants to avoid any issues.

[Edited by - MARS_999 on February 24, 2008 12:54:15 PM]
Effron
Effron
Sorry I always have issues balancing the "flood" of information and code, or not providing enough information.

Let me kind of summarize a bit.

Basically I just recently started working with openGL and I thought a nice way to learn would be to make a game (a car racing game in my case) So I started to write functions for all kinds of scenery models etc... Now im starting to texture everything and its getting confusing to keep track of everything.

So I wanted to make a (singleton) texture manager that just simplified everything for me. Project-wide
I wanted to just just load() a whole bunch of textures with default parameters, since most of the textures in my game use the same ones. Then useTex() whenever I wanted to use one.


* The idea behind ID:
ID is the texture name visible to the user (of the manager)
the textureName openGL sees is texName[ID]
So texName is an array of GLUINT, ID I am also using as a GLuint, but its basically just the index of the texNames array.

The documentation on genTexexture says that it will ensure a unique number if available, however, it doesn't specify any kind of order, or pattern or whatever u want to call it. So I thought hey, ill make things easier for myself and the outside world, by giving my own "ID" to the user, and let them call functions with this ID, and I will keep the names internally. For debugging this also (I was thinking) would help.


Sooo.... that said,

The following does NOT work: Using manager
-----------
inside initGL()
load a texture and get the ID //function shown in previous post


inside DisplayFunc()
glEnable(GL_TEXTURE_2D);
call useTex(ID) //function shown in previous post
draw random quad
-----------

The following does NOT work: Withought manager
-----------
inside initGL()
genTexture //and save textureName
bindTexture
glTexImage2D
glTexParameteri...


inside DisplayFunc()
glEnable(GL_TEXTURE_2D);
Bind saved textureName
draw random quad
-----------

The following DOES work: Withought manager
-----------
inside DisplayFunc()

glEnable(GL_TEXTURE_2D);
load bitmap
genTexture //and save textureName
bindTexture
glTexImage2D
glTexParameteri...
draw random quad
-----------


At first I thought it was that I needed to keep the image data (buffer) in mem.
As you can see from my load function in previous post, the mem is toast as soon as the load is finished.

But #1 I've read many many posts where they say no, it sends to video memory, no need to keep it at all. (by the way my test.bmp is very small)

and #2 when I do glIsTexture after I did genTexture, bind, glTexImage2D, parameters... it still returns false.

So if its not the image data being lost, then im really stumped. Basically all im doing is moving code around, not adding / removing anything.

I hope might be enough for someone to see the error of my ways :) Thats for the help so far guys
snoutmate
snoutmate
Well i don't see anything wrong with the particular code. You mentioned InitGL function, so just be sure that you initialize the OpenGL context before calling any OpenGL function. You may also want to chceck what value you're getting from glGenTextures, and check for errors with glGetError() after each of the functions to see if anything gone wrong.
Effron
Effron
arg...


int main(int argc, char argv[])
{
initGL();

dooohhh


thanks snoutmate for the reminder.
A day of headaches for such a silly mistake

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.