Hardware Texture Rendering

This is an easy way to render changes to a texture in OpenGL. If you are using a double-buffered system, you can actually render the texture to the back buffer and copy it directly into texture memory with glCopyTexImage2D, bypassing the memory transfer as long as you can produce the desired changes using OpenGL. You can use this for for many different purposes, including feedback effects like the fractals in my Dragon Demo, dynamic environment maps, and various blurs.

If you have access to later OpenGL extensions, you may want to use the more efficient and versatile frame buffer object extension instead, but this works with OpenGL 1.1, is fairly simple, and can be reasonably efficient.

In your display code, before rendering the scene, set the viewport to the size of your texture.

glViewport(0,0,256,256);

At this point, draw the desired image. For blur effects or environment mapping, often you would draw the entire scene here in miniature to be used as part of the effect. Once this is done it is as simple as binding the texture you want to replace, and making a single function call; glTexImage2D takes a rectangular portion from a chosen source (the default is the back buffer) and places it directly into the current texture. (For some purposes GL_RGBA, or GL_INTENSITY may be preferred to the GL_RGB used in this example.)

glBindTexture(GL_TEXTURE_2D,my_texture);
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGB,0,0,256,256,0);

Now that the texture is ready, it is time to continue with your regular drawing code. Restore the viewport to its original dimensions, and draw your scene.

glViewport(0,0,width,height);

In some cases, you may wish to use glCopyTexSubImage2D instead, which replaces only a rectangular portion of your texture. Definitions for these two functions follow:

void glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
                       GLint x, GLint y, GLsizei width, GLsizei height, GLint border);

void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset,
                          GLint x, GLint y, GLsizei width, GLsizei height);

That's the basic outline of the technique. There is an application of this to a "radial blur" described at the NeHe tutorial Lesson 36, and Nutty's OpenGL Site has a good environment mapping demonstration that uses this technique on its OpenGL Extensions page. E-mail me if you have any comments or questions.


Return to my Dragon Demo, or main page.
brad @ rainwarrior.ca
4/10/2010