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!
sir,
your program does not gives the actual color of images………… please let me know how we get the original imag color
i cant see any output. just only a white box
You must delete the blank spaces in teh method init(). When I load the code in my IDE it was like this:
texture[0] = LoadTexture(“textures / 1.raw”, 256, 256);
and after correct it:
texture[0] = LoadTexture(“textures/1.raw”, 256, 256);
See you!
hey can u pls help me out , i m not able to see the output of this code , I m using codeblocks to run this code and i have placed the texture file in bin directory of the project.
and i can see only the white cube in the output . I guess the raw files are not getting read.
Hello Swiftless,
First let me say great tutorials and thanks for making the effort to create them. I had a question about the texture memory thing above because in my project I am using a sprite sheet method. Is there anyway to check how large of a texture a card will support in my code and then maybe use an alternate method? I know it would be easier to just do either or, but I was just wondering. Thanks!
where to save the texture file so that we can link with program??
Hi Pankaj,
You can save the texture file wherever you like, as long as the source code is pointing to that file. In this example, I have them in a folder called “textures” which is in the same directory as the application.
Cheers,
Swiftless
Hum.. Why not use a single texture file and then change the texture uv coordinates of each vertex? Usually an animated image goes to a cardboard which has only 4 vertexes. There won’t be much impact of changing those coords on the fly. Better then having 100s of images on disk…
Hi Limanima,
You could do that, and it is perfectly valid if you have a small 2D game and already have the sprite maps.
The problem with doing this in a larger game is that if you have a large file you will run out of texture memory extremely quickly. A lot of graphics cards don’t support textures with a size greater than 2048×2048.
Also, if you look at files such as movie files, or gifs, then you have no choice usually but to load it in frame by frame as that is how the file format is stored.
Cheers,
Swiftless