33. OpenGL Animating Textures (Version 2.0)

Introduction

Some of you might be wondering about animating your textures in OpenGL. Unfortunately, OpenGL does not natively support texture animation. You cannot directly load GIFs or movie files and render them on shapes. However, there are workarounds, and this tutorial will guide you through one of the simplest methods.

In this method, we create a series of image files representing each frame of the animation. These frames are loaded as individual textures and displayed sequentially to simulate animation. Let’s dive in!

Setting Up the Animation Frames

We start by loading each frame of the animation into a texture array. Here’s how it’s done:

GLuint texture[9]; // Array to hold textures
texture[0] = LoadTexture("textures/1.raw", 256, 256);
texture[1] = LoadTexture("textures/2.raw", 256, 256);
texture[2] = LoadTexture("textures/3.raw", 256, 256);
texture[3] = LoadTexture("textures/4.raw", 256, 256);
texture[4] = LoadTexture("textures/5.raw", 256, 256);
texture[5] = LoadTexture("textures/6.raw", 256, 256);
texture[6] = LoadTexture("textures/7.raw", 256, 256);
texture[7] = LoadTexture("textures/8.raw", 256, 256);
texture[8] = LoadTexture("textures/9.raw", 256, 256);

Each frame is loaded as a unique texture using the `LoadTexture` function, which takes the file path, width, and height of the texture as arguments.

Displaying the Animation

To display the animation, we bind the texture corresponding to the current frame and draw it on a quad. Here’s the key section of the rendering code:

glBindTexture(GL_TEXTURE_2D, texture[(int)frame]); // Bind the current frame
glBegin(GL_QUADS);
glTexCoord2d(0, 0); glVertex3f(-1, 1, 0);
glTexCoord2d(1, 0); glVertex3f(1, 1, 0);
glTexCoord2d(1, 1); glVertex3f(1, -1, 0);
glTexCoord2d(0, 1); glVertex3f(-1, -1, 0);
glEnd();

Here, `frame` is a variable that determines which frame of the animation to display. Each texture is mapped onto a quad using texture coordinates.

Animating the Frames

To simulate animation, we increment the `frame` variable each time the display function is called. When `frame` exceeds the maximum frame number, it is reset to the first frame, creating a seamless loop.

frame += 0.2; // Advance the frame
if (frame > 8) {
    frame = 0; // Loop back to the first frame
}

The increment value `0.2` determines the animation speed. Smaller values slow down the animation, while larger values speed it up.

Tutorial Code

Here’s the complete program for animating textures in OpenGL:

#include 
#include 
#include  // For malloc and free

GLuint texture[9]; // Array to hold texture frames
double frame = 0;  // Current animation frame

// Function to load textures
GLuint LoadTexture(const char *filename, int width, int height) {
    GLuint texture;
    unsigned char *data;
    FILE *file;

    file = fopen(filename, "rb");
    if (file == NULL) return 0;

    data = (unsigned char *)malloc(width * height * 3);
    fread(data, width * height * 3, 1, file);
    fclose(file);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
    free(data);

    return texture;
}

// Render a textured quad
void cube(void) {
    glBindTexture(GL_TEXTURE_2D, texture[(int)frame]);
    glBegin(GL_QUADS);
    glTexCoord2d(0, 0); glVertex3f(-1, 1, 0);
    glTexCoord2d(1, 0); glVertex3f(1, 1, 0);
    glTexCoord2d(1, 1); glVertex3f(1, -1, 0);
    glTexCoord2d(0, 1); glVertex3f(-1, -1, 0);
    glEnd();
}

// Display function
void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glEnable(GL_TEXTURE_2D);
    glTranslatef(0, 0, -5);

    cube();

    glutSwapBuffers();

    frame += 0.2;
    if (frame > 8) {
        frame = 0;
    }
}

// Initialize textures and settings
void init(void) {
    texture[0] = LoadTexture("textures/1.raw", 256, 256);
    texture[1] = LoadTexture("textures/2.raw", 256, 256);
    texture[2] = LoadTexture("textures/3.raw", 256, 256);
    texture[3] = LoadTexture("textures/4.raw", 256, 256);
    texture[4] = LoadTexture("textures/5.raw", 256, 256);
    texture[5] = LoadTexture("textures/6.raw", 256, 256);
    texture[6] = LoadTexture("textures/7.raw", 256, 256);
    texture[7] = LoadTexture("textures/8.raw", 256, 256);
    texture[8] = LoadTexture("textures/9.raw", 256, 256);
}

// Reshape function
void reshape(int w, int h) {
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
}

// Main function
int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Texture Animation");

    init();

    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();

    return 0;
}

If you have any questions, feel free to email me at swiftless@gmail.com. Happy coding!

Download Textures(.RAW files in a Zip file)

Download Textures(.BMP files in a Zip file)

  • March 25, 2010
  • 9