trouble with material/textures

Started by
23 comments, last by python_regious 18 years, 9 months ago
I have put on the materials as read from the mtl file, and the models look alright (some of them, at least..). The thing is that the last material gets smeared over my textures somehow. After drawing the car, I should draw the road, and it has a texture. When I use the materials, the road gets the color of the car wheels - probably the last material used. why is that? should I disable the material somehow?
Advertisement
You just replied to your own question :)

A simple way of handling with these kind of problems is making a 'clear' function that calls the proper glDisable(...) calls for each of the glEnable(...) calls you use in your program and call that before setting up the state for a new object. This my not be the best option from a performance point of view, but it does make state cleaning easy. More efficient ways of state management require you to track the states yourself.

Tom
yeah, well...
what do I have to disable then? I never did an glEnable(GL_MATERIAL) or anything like that, and my textures are set to GL_DECAL, so how come the materials cover them?
If you don't want any colors or lighting effects on the road and only want to see the texture, make sure you use:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
This ensures that any color values are overwritten.
If you do want lighting effects, use:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
and specify proper material values for the road as well.

Tom
I must be doing something wrong...
I just changed the GL_DECAL to GL_REPLACE, and I still get an all black road.
It's probably not it.. I edited the mtl file so that the last used material will be bright yellow.. the model gets it, but the road gets all black.
and when I just comment out the line that causes the four glMaterialf calls (ambient, diffuse, specular, shininess), the road gets the texture alright.
what am I missing here?
Try to disable lighting for the road. Then you know for sure that blackness is not just lack of light.

Tom
I disabled lighting for the engite scene, and nothing changed (excpet that the model now looks like a 2d blob).
This texture thing is weird - the sideways of the road are getting the proper texture alright. just not the middle polygon.
Maybe post some code, I'm running out of ideas :)

Tom
First I load and bind the texture:

void Road::GetTexture(const char *texFileName)
{
texImage = NULL;

FREE_IMAGE_FORMAT format = FreeImage_GetFileType(texFileName);
if (format == FIF_UNKNOWN)
{
format = FreeImage_GetFIFFromFilename(texFileName);
if ((format == FIF_UNKNOWN) || (!FreeImage_FIFSupportsReading(format)))
return;
}

texImage = FreeImage_Load(format, texFileName, NULL);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

BYTE *pixels = FreeImage_GetBits(texImage);
int texWidth = FreeImage_GetWidth(texImage);
int texHeight = FreeImage_GetHeight(texImage);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
}

loading the image, and reading it's pixel array.

here is the method that draws the road

void Road::Draw()
{
GLfloat wall_diffuse[] = {1, 0.3, 0.5, 1.0};

glPushAttrib(GL_CURRENT_BIT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glBegin(GL_QUADS);
{
glTexCoord2f(0.0, time); glVertex3f(-shoulderWidth, 0, length);
glTexCoord2f(1.0, time); glVertex3f(shoulderWidth, 0, length);
glTexCoord2f(1.0, time + ratio); glVertex3f(shoulderWidth, 0, -length);
glTexCoord2f(0.0, time + ratio); glVertex3f(-shoulderWidth, 0, -length);
}

glEnd();

glBindTexture(GL_TEXTURE_2D, 0);
glPopAttrib();
time += speed;
if (time == 1024)
time = 0;

for(unsigned int i = 0; i < models.size(); ++i)
models->Draw();
}

the shoulderWidth and length just define the road, a simple quad polygon around (0,0,0) on the XZ plane.
After the road is done with, I draw all the models (one, at the moment...) on it.
The models are drawn using display lists, which are being compiled when they are loaded from files.
here is the creation of the display list:

displayList = glGenLists(1);
glNewList(displayList, GL_COMPILE);
glPushMatrix();
boundingBox.Normalize();
glBegin(GL_TRIANGLES);
{
for (unsigned int i = 0; i < triangles.size(); ++i)
{
if (currentMaterial != triangles.material)
{
currentMaterial = triangles.material;
currentMaterial->Set();
}

for (unsigned int j = 0; j < 3; ++j)
{
normal = normals[triangles.normal[j]].v;
vertex = vertices[triangles.vertex[j]].v;
glNormal3fv(normal);
glVertex3fv(vertex);
}
}
}

glEnd();
glPopMatrix();
glEndList();

just a simple loop. whenever the triangles array calls for a change of material, I change it, and set it (just a call to the 4 material mehotds). The rest is just going over all the vertex of each triangle, creating it's normal and vertex.
if I comment the line with currentMaterial->Set(); I get the road texture working fine.

Another newbie question, while I am at it - in order to create a decent interactive frame rate, what should I do? right now I am just using my display function as the glutIdleFunc, so it keeps refreshing the screen whenever it can. is that the way to do it, or is there another way?
And about creating the movement - should I just get the Draw method of every Model I've got to run the display list, and then update some local variable to change the current location? or should I seperate the drawing from the moving ( - before each call do a glTranslatef call, but updating the local x,y,z values at a different location)?
Allthough this will probably not solve your problem, I'm missing a glEnable(GL_TEXTURE_2D); at the start of your road::Draw() and a glDisable(GL_TEXTURE_2D); at the end of that same function.

I don't understand why currentMaterial->Set() had an effect on the road, because you did not add the code for the Set() function. However, if it contains a glDisable(GL_TEXTURE_2D); that would explain your problem.

On the other issues; my glutIdle() always looks like this:
void idle(void)
{
glutPostRedisplay();
}
You could do some variable upkeep here, but as a rule I only use glut* calls and no gl* calls in idle. gl* calls should be in your glutDisplay function. This only to get nicer code, it will not make much of a performance difference compared to your approach. Performance is normally determined by whatever you do in the rendering loop (and by your program logics if you perform complex calculations such as object culling, game a.i., etc.).

About the movement; as it's just a matter of design, this is all up to you. I use my own Scene Graph API where each object has Translation, Rotation and Scaling functions that togeter form the TRS-transform matrix for a particular object. Then I load the TRS matrix before drawing the object. This might be overkill for a smaller program. I would definately store the position and orientation inside the object, because they are properties of that object.

Tom

This topic is closed to new replies.

Advertisement