PDA

View Full Version : Texture not showing on animated model



EvanV
10-04-2011, 11:05 AM
Good morning everyone,

So I've been working on a project using OpenGL the last few weeks. It's nearly complete except for the fact that the texture on the model I'm animating isn't showing up. However, the texture for the font loads up and I can see that when rendered. The texture manager I made for a previous project and worked, it uses DevIL library to load in the images. I'm just not sure if I'm forgetting to enable/disable something that maybe causing my issue. It would be very helpful if anyone could shed some light on this. Thank you.

InitGL()


CLight::Initialize();
CTextureManager::GetInstance()->Initialize();
establishProjectionMatrix(width, height);
//glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_PERSPECTIVE_CORRECTION_HINT);
glEnableClientState( GL_VERTEX_ARRAY );
//glEnableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );

mainCLight = new CLight(LSPOT);
mainCLight->setDiffuse(1.0f, 1.0f, 1.0f, 1.0f);
mainCLight->setPosition(0, 50, 0);


CModel Render()


glVertexPointer( 3, GL_FLOAT, 0, &m_vMeshes[i]->GetVertices()[0] );
glTexCoordPointer(2, GL_FLOAT, 0, &m_vMeshes[i]->GetTexCoords()[0]);
glDisable(GL_LIGHTING);

glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texHandle);

glDrawElements( GL_TRIANGLES, (GLsizei)m_vMeshes[i]->GetIndices().size(), GL_UNSIGNED_INT, &m_vMeshes[i]->GetIndices()[0] );

NOTE: Already tried enabling vertex and tex coord states before calling glDrawElements and disabling the states after the call. Still doesn't work.

EvanV
10-07-2011, 10:00 AM
Been a while since I've worked on this but I still have the same problem. I bind the texture I'm trying to use to a simple quad. The texture showed up fine on the quad so I know it's being loaded in correctly. I've disabled lighting so I know it can't be that. The texture coordinates in the vector look right and even if they were wrong I should get something other than black. If anyone could at least point me in the right direction that would help a lot.

BionicBytes
10-07-2011, 11:04 AM
What filtering have you used on your textures. I wonder if you have set a filter mode using mipmapping but you have not generated any mip maps.

Dan Bartlett
10-07-2011, 11:24 AM
Do you adjust the client active texture anywhere in the program using glClientActiveTexture (http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml)? This would affect the glTexCoordPointer/glEnableClientState( GL_TEXTURE_COORD_ARRAY) calls.

If you are switching the active texture elsewhere, you also might want to switch to texture unit 0 before enabling GL_TEXTURE_2D. Since enabling/disabling GL_TEXTURE_2D is per texture unit.



glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);

Do you any other buffer object/ VAO switches etc that you haven't shown?

EvanV
10-07-2011, 11:27 AM
This is what I'm using.
minFilter = GL_LINEAR_MIPMAP_LINEAR
magFilter = GL_LINEAR
wrapMode = GL_REPEAT


//Define how to scale the texture.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);

//Define your texture edge handling
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);

//Generate the mipmap
if(minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT),
GL_UNSIGNED_BYTE, ilGetData()); /* Texture specification */

EvanV
10-07-2011, 11:30 AM
I have not used glClientActiveTexture anywhere in the program and I have tried glActiveTexture(GL_TEXTURE0) before enabling GL_TEXTURE_2D. This is pretty much all my draw code, everything else is drawing points for vertices and joints.



//Setup Scene
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
establishProjectionMatrix(windowWidth, windowHeight);

//TODO: remove
GLuint err = glGetError();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glEnable(GL_LIGHTING);
glDisable(GL_BLEND);

//Update the scene from mouse control
glTranslatef(translate.x, translate.y, zoom);
glRotatef(rotateX, 1.0f, 0.0f, 0.0f);
glRotatef(rotateY, 0.0f, 1.0f, 0.0f);

//Draw all lights in the scene
for(int i = 0; i < (int)CLight::lights.size(); i++)
{
CLight* test = CLight::lights[i];
CLight::lights[i]->updateLight();
}

//Draw grid with no texture
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
drawGrid();

//Draw the model we're animating
glDisable(GL_BLEND);
model.DrawModel(bRenderSkin, bRenderPoints, bRenderJoints);

//Draw Controls
glColor3f(1.0f, 1.0f, 1.0f);
glDisable(GL_LIGHTING);
setOrtho(windowWidth, windowHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
displayFPS();
drawControls();

//Clean
glFlush();
SDL_GL_SwapBuffers();


NOTE: I noticed that the glActiveTexture is called after glEnable but I switched it recently calling glActiveTexture first. Still there has been no change.

BionicBytes
10-07-2011, 01:23 PM
When rendering with vertex arrays you need to specify glClientActiveTexture and not glActiveTexture. This needs to be issued before the texture pointer function call.

EvanV
10-07-2011, 03:04 PM
Okay so I've tried using glClientActiveTexture in place of glActiveTexture. Here is what CModel's DrawModel() is now. But the model is still showing up as black.


glEnable(GL_TEXTURE_2D);
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, 0, &amp;m_vMeshes[i]->GetTexCoords()[0]);
glVertexPointer( 3, GL_FLOAT, 0, &amp;m_vMeshes[i]->GetVertices()[0] ); //NOTE: Remember the [0] at the end when using vectors

glBindTexture(GL_TEXTURE_2D, texHandle);

glDisable(GL_LIGHTING);

glDrawElements( GL_TRIANGLES, (GLsizei)m_vMeshes[i]->GetIndices().size(), GL_UNSIGNED_INT, &amp;m_vMeshes[i]->GetIndices()[0] );

EvanV
10-07-2011, 05:53 PM
I have cut down my main render code so this is everything I'm doing.



//Setup Scene
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
establishProjectionMatrix(windowWidth, windowHeight);

//TODO: remove
GLuint err = glGetError();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glDisable(GL_LIGHTING);
glDisable(GL_BLEND);

//Update the scene from mouse control
glTranslatef(translate.x, translate.y, zoom);
glRotatef(rotateX, 1.0f, 0.0f, 0.0f);
glRotatef(rotateY, 0.0f, 1.0f, 0.0f);

//Draw Model
std::string szTex;
GLuint texHandle;
szTex = "data/Textures/" + model.m_vMeshes[0]->m_vTextureNames[0];
texHandle = CTextureManager::GetInstance()->GetTextureHandle(szTex.c_str()/*"data/font.tga"*/);

glVertexPointer( 3, GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetVertices()[0] );
glNormalPointer(GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetNormals()[0]);
glEnable(GL_TEXTURE_2D);
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glClientActiveTexture(GL_TEXTURE0);
vector<UV> testuv = model.m_vMeshes[0]->GetTexCoords();
glTexCoordPointer(2, GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetTexCoords()[0]);
glBindTexture(GL_TEXTURE_2D, texHandle);
glDrawElements( GL_TRIANGLES, (GLsizei)model.m_vMeshes[0]->GetIndices().size(), GL_UNSIGNED_INT, &amp;model.m_vMeshes[0]->GetIndices()[0] );

//Clean
glFlush();
SDL_GL_SwapBuffers();

Dan Bartlett
10-08-2011, 03:28 AM
If you replace the glDrawElements call with something like:


glBegin(GL_TRIANGLES);
for (int i = 0; i < model.m_vMeshes[0]->GetIndices().size(); i++)
{
int index = model.m_vMeshes[0]->GetIndices()[i];
glTexCoord2fv(&amp;model.m_vMeshes[0]->GetTexCoords()[index]);
glNormal3fv(&amp;model.m_vMeshes[0]->GetNormals()[index]);
glVertex3fv(&amp;model.m_vMeshes[0]->GetVertices()[index]);
}
glEnd();

does it display correctly? Is the model currently displaying correctly apart from being untextured?

If your model has more problems than just being untextured, do you have the right types of tightly packed data in your arrays?
Indices = unsigned int (not e.g. unsigned short)
TexCoords = 2x float
Normals = 3 x float
Vertices = 3 x float

If you use multitexturing, then both glClientActiveTexture + glActiveTexture are both used, they have different purposes. If you aren't using multitexturing, then the glClientActiveTexture/glActiveTexture calls aren't necessary, since you'll always be using texture unit 0.



glVertexPointer( 3, GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetVertices()[0] );
glNormalPointer(GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetNormals()[0]);

// client active texture unit = 0
glClientActiveTexture(GL_TEXTURE0);
// enable gl_MultiTexCoord[0]
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
// gl_MultiTexCoord[0] will be retrieved from here
glTexCoordPointer(2, GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetTexCoords()[0]);

// active texture unit = 0
glActiveTexture(GL_TEXTURE0);
// enable texturing with GL_TEXTURE_2D on tex unit 0
glEnable(GL_TEXTURE_2D);
// bind texHandle to GL_TEXTURE_2D on tex unit 0
glBindTexture(GL_TEXTURE_2D, texHandle);

vector<UV> testuv = model.m_vMeshes[0]->GetTexCoords();

glDrawElements( GL_TRIANGLES, (GLsizei)model.m_vMeshes[0]->GetIndices().size(), GL_UNSIGNED_INT, &amp;model.m_vMeshes[0]->GetIndices()[0] );

EvanV
10-08-2011, 07:54 AM
Yes, the model displays correctly and animates correctly the only problem being that the texture is black. I am not using any multitexturing just trying to render using one texture at the moment. My texture coordinates are 2f and normal/position are 3f within my arrays.

_arts_
10-08-2011, 08:42 AM
Try this:



glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );

glVertexPointer( 3, GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetVertices()[0] );
glNormalPointer(GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetNormals()[0]);
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, 0, &amp;model.m_vMeshes[0]->GetTexCoords()[0]);

glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texHandle);
glDrawElements( GL_TRIANGLES, (GLsizei)model.m_vMeshes[0]->GetIndices().size(), GL_UNSIGNED_INT, &amp;model.m_vMeshes[0]->GetIndices()[0] );

//disable all arrays and textures

EvanV
10-08-2011, 09:25 AM
Found the problem. The function that returns the vector of tex coordinates wasn't returning the address of that vector. Made that return the address and the tex coordinates are wrong but I see the texture at least.

Edit: Actually the tex coordinates are right too. Switched the texture to what it was originally (png) within the output file and now it shows up perfectly.

Thank you all for your help.

BionicBytes
10-08-2011, 01:18 PM
[quote]glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, 0, &amp;m_vM
[\quote]
you definitely need to switch the order of the enableclientstate and clientactivetexture commands because you have to select which if the 8 fixed function texture units you are sending the cordinate array to.

Are you using shaders to render the model?

EvanV
10-08-2011, 06:17 PM
I am not using any custom shaders at the moment.