Appendix A: Multiple Textures on the Cube

The way the EDCubeDemo projects stands, it uses one texture for everything. This works out pretty well because it allows us to be efficient with our draw logic, but what if we wanted to put different textures on the different sides?

The easiest way to accomplish this is to simply add more textures and bind them as we draw.

The first change to the project is in the EDCubeDemoViewController.h file, where we create new variables to hold our six textures for the cube faces.

    GLuint textureName0, textureName1, textureName2, textureName3, textureName4, textureName5;

Then, in the EDCubeDemoViewController.m file, in the awakeFromNib method, we load all six textures by calling the loadTexture:fromFile: method six times.

    [self loadTexture:&textureName0 fromFile:@"apple_logo0.png"];
    [self loadTexture:&textureName1 fromFile:@"apple_logo1.png"];
    [self loadTexture:&textureName2 fromFile:@"apple_logo2.png"];
    [self loadTexture:&textureName3 fromFile:@"apple_logo3.png"];
    [self loadTexture:&textureName4 fromFile:@"apple_logo4.png"];
    [self loadTexture:&textureName5 fromFile:@"apple_logo5.png"];

You can substitute other graphics files for these, or you can download the project code and just use those.

The only other change to the file is in the drawFrame method, where instead of calling glDrawArrays() once for the entire vertex array, we break up the calls to draw one face at a time, binding the texture that we want drawn on that face before each call.

    glBindTexture(GL_TEXTURE_2D, textureName0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindTexture(GL_TEXTURE_2D, textureName1);
    glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
    glBindTexture(GL_TEXTURE_2D, textureName2);
    glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
    glBindTexture(GL_TEXTURE_2D, textureName3);
    glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
    glBindTexture(GL_TEXTURE_2D, textureName4);
    glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
    glBindTexture(GL_TEXTURE_2D, textureName5);
    glDrawArrays(GL_TRIANGLE_STRIP, 22, 4);

Note that the final call to glDrawArrays() jumps over the two vertices that we had created to make the degenerate triangles to move cleanly from the bottom face to the top face. Since we’re no longer drawing the cube as one strip, they’re unnecessary.

Now when we build and run the code, behold.



The different textures are being rendered on the different faces.

There’s another method that can be used to draw (or, more accurately, project) textures onto cubes called cube mapping. Instead of using a target of GL_TEXTURE_2D, we use a target of GL_TEXTURE_CUBE_MAP.

Unlike what we’ve just done here with multi-texturing, however, cube maps are generally most useful for environmental mapping, with the viewpoint of the user being inside the cube, not outside.

Part Seventeen | Index | Appendix B