Jump to content
  • Advertisement
Sign in to follow this  
arasmussen

Multiple (separate) textures in one VBO

This topic is 2837 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

Hi,

I have a cube (for simplicity's sake), and I'd like to render a different texture on each surface. I've searched all over for this, and all of the results are either a little over my head (hence why I'm here, for explanation), or don't seem to work, or really are not what I'm looking for.

Right now, my init function looks like this:


GLint InitGL(GLvoid)
{
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

gltext = new GLText(hDC);
framerate = new Framerate();

LoadGLTextures("Data/texture0.bmp", &texture[0]); LoadGLTextures("Data/texture1.bmp", &texture[1]);
LoadGLTextures("Data/texture2.bmp", &texture[2]);
LoadGLTextures("Data/texture3.bmp", &texture[3]);
LoadGLTextures("Data/texture4.bmp", &texture[4]);
LoadGLTextures("Data/texture5.bmp", &texture[5]);


return true;
}


and my draw function looks like this:


int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(-2.0f, -2.0f, -6.0f);

glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);

glBindTexture (GL_TEXTURE_2D, texture[0]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, (GLvoid*)(24*sizeof(GLfloat)));

glBindTexture (GL_TEXTURE_2D, texture[1]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, (GLvoid*)(32*sizeof(GLfloat)));

GLubyte indices[] = {0,1,3,2,
0,2,6,4,
0,1,5,4,
2,3,7,6,
5,1,3,7,
4,5,7,6};

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, indices);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);

return true;
}


I realize that this isn't quite right. If someone could explain to me what the "glEnable(GL_TEXTURE_2D", "glActiveTexture(GL_TEXTURE0)", and "glClientActiveTexture(GL_TEXTURE0)" stuff actually do in the background, that might get me somewhere.

Share this post


Link to post
Share on other sites
Advertisement
glActiveTexture sets the active texture unit. Each 'texture unit' can hold one texture, and has its own set of states. Subsequent calls to glBindTexture, glEnable, etc affect the active texture unit.

glEnable turns on or off the active texturing unit for the fixed function pipeline only. If enabled, the fixed pipeline will sample the active texture to get the fragment color.

glClientActiveTexture affects subsequent calls to glTexCoordPointer. In cases where you are doing multitexturing, this will set which texcoord pointer goes with which texture.

For what you're trying to do, I would recommend one of two things:

1) Build a texture atlas, and then set the UVs for each side to sample the correct texture from the atlas
2) Draw one side, switch textures, repeat.

In neither of these cases do you need to do anything with glActiveTexture or glClientActiveTexture.

There's no easy way to set different vertices to sample from different textures in the same draw call.

Share this post


Link to post
Share on other sites
What are you trying to achieve; to put multiple textures on the same face, or a single texture on each face but different textures for different faces? You are mixing those goals, but they are entirely different things. glActiveTexture is for multitexturing (putting several textures on one face), but your six textures and six quads suggest a single texture per face (not multitexturing, just bind the correct texture and draw each quad individually).

Share this post


Link to post
Share on other sites
I would like a separate texture for each face, and no multitexturing. Sorry for not being clear. Also, I'd like to do this with just a single glDrawElements call. Is that possible, or will I have to make a separate draw call for each texture?

Share this post


Link to post
Share on other sites
It might be possible with some funky shaders, but you shouldn't do it anyway, as it would require some terrible branching logic that would just be bad performance hit.

For all practical purposes, you should assume that you should have one draw call per material. Different textures means different materials (unless you atlas them).

Share this post


Link to post
Share on other sites
So could I do something like this? Also, would this be the fastest way?


int DrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

glTranslatef(-2.0f, -2.0f, -6.0f);

glBindBuffer(GL_ARRAY_BUFFER, vbuffer);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);

glBindTexture (GL_TEXTURE_2D, texture[0]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, (GLvoid*)(24*sizeof(GLfloat)));

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, indices[0]);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);


glBindTexture (GL_TEXTURE_2D, texture[1]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, (GLvoid*)(32*sizeof(GLfloat)));

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, indices[1]);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);

return true;
}

Share this post


Link to post
Share on other sites

I would like a separate texture for each face, and no multitexturing. Sorry for not being clear. Also, I'd like to do this with just a single glDrawElements call. Is that possible, or will I have to make a separate draw call for each texture?


As already someone said, make a Texture Atlas aka Spritesheet. You put multiple Textures onto one big image. Then you only need to bind one texture to opengl, because you only load that big image. And then you just calculate different u/v to match that subpicture.
Formula for this is:

subimage_position / spritesheet_size.
Should give you something like 0.xx, thats your subimage.

Tools for this:
http://spritesheetpacker.codeplex.com/

Sample of Implementation for the File generated from this Tool:
http://code.google.c...SpriteSheet.cpp

Hope it helps.

edit:
You need to set those Texture-Coords before uploading or you modify them afterwards. I suggest to modify them before uploading.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!