DevIL provides some powerful access to the Open Graphics Library (OpenGL)
API through DevILUT. DevIL is quite particularly suited to OpenGL, as
DevIL was created specifically with OpenGL in mind. Of course, you do not
*have* to use DevILUT at all and can call glTexImage2D with the image data
ilGetData returns and the image
information ilGetInteger reports.
I would consider this an effort at reinventing the wheel, though, just
like writing your own image loading functions. =]
Getting Started
Before you call any ilut functions dealing with OpenGL and after you have
initialized OpenGL, you *must* call
ilutRenderer with the ILUT_OPENGL
parameter.
Required line to initialize DevIL's OpenGL access.
ilutRenderer(ILUT_OPENGL);
How ILUT Handles Textures
DevIL allows the use of arbitrarily-sized images, but OpenGL only works
with images that have dimensions that are powers of 2, for optimization
purposes. If an image has dimensions that are not powers of 2, DevIL
will resize the image before sending it to OpenGL. Alternatively, you
could use glTexSubImage2D after creating a texture, but this is outside
the scope of this tutorial.
DevIL will properly handle paletted images with ease, but OpenGL does
not natively supports these types of images. Ilut could utilize the
paletted texture extension, but I decided against this, as the support
seems shoddy, and nVidia does not even seem to support it on their cards.
So, if an image is paletted, Ilut will convert the image to its truecolour
equivalent before sending it off to OpenGL.
DevIL is only limited in the size of images it can load by the amount
of system memory that is available. OpenGL does not have this luxury
and must fit images in the video card's limited memory. The main reason
you must call ilutRenderer is for ilut to determine just how large an
image the video card can handle. glGetIntegerv reports this information
and is called when you call ilutRenderer. If you try to send an image to
OpenGL that is too large, DevIL will automatically convert the image to
appropriate dimensions. If you do not call ilutRenderer, the largest
dimensions of an image your video card can handle will be assumed to be
256x256.
One last conversion that may take place is if you have the origin set
via ilEnable and
ilOriginFunc. The image will be
flipped if its origin is opposite that which you have set (such as if
you changed the default origin after loading the image). If you wish
to find out exactly what is going behind the scenes in Ilut, look at
MakeGLCompliant in opengl.c. This is where all conversions take place.
ILUT_OPENGL_CONV
Some nVidia cards have this "feature" where they will automatically
convert all images to 16-bit to save memory. This is good and all,
but it introduces dithering effects. To counter this, call
ilutEnable with the
ILUT_OPENGL_CONV parameter. What this does is send a different value
as the internalFormat parameter of glTexImage2D. The new
values are GL_RGB8 and GL_RGBA8 instead of GL_RGB and GL_RGBA,
respectively.
How to disable on-board conversion.
ilutEnable(ILUT_OPENGL_CONV);
Straight-Up Access to OpenGL
ILboolean ilutOglTexImage(GLuint Level);
ilutOglTexImage is the simplest of the ilut GL functions. Basically,
all this function does is call glTexImage2D after performing any
required conversions. The Level parameter allows you to
manually set mipmaps.
GLuint ilutOglBindTexImage(ILvoid);
ilutOglBindTexImage is similar to the aforementioned ilutOglTexImage,
except it generates and binds a texture via glGenTextures and
glBindTexture. When you call ilutOglTexImage, you already have to
have your texture bound, so this function makes it easier for the
developer. Also, this function sets many of the texture environment
settings, so this integrated solution may not be perfect for you.
The return value is the OpenGL texture name. If it is 0, an error
occurred.
Mipmapping With OpenGL
ILboolean ilutOglBuildMipmaps(ILvoid);
ilutOglBuildMipmaps is the mipmapping equivalent of ilutOglTexImage.
Right now, it creates mipmaps via gluBuild2DMipmaps but may use
DevIL's mipmap generation functions in the future.
GLuint ilutGLBindTexImage(ILvoid);
ilutGLBindTexImage is the mipmapping equivalent of ilutOglBindTexImage.
This function is similar to ilutOglBuildMipmaps in that it performs
the same operations, but it generates and binds an OpenGL texture
and sets various texture states before generating mipmaps. The
return value is the OpenGL texture name. If it is 0, an error occurred.
Simple Solutions
GLuint ilutOglLoadImage(char *FileName);
Feel that there is no reason to mess directly with DevIL, as you will
not need a local copy of the DevIL images you load as OpenGL textures?
If so, ilutOglLoadImage is for you. This function bypasses the need
to generate image names, etc. Just call ilutOglLoadImage with the
name of the file you wish to load, and it will load the image directly
into an OpenGL texture, then delete all unnecessary local data. This
function is quick and simple to use if it is all you will need.
Screenshots
Sometimes you want to take a screenshot, such as an in-game shot.
ilutOglScreen can perform this for you.
ILboolean ilutOglScreen(ILvoid);
ilutOglScreen loads the viewport's data into the current bound image,
for you to decide what to do with it. If you want to automate the
process even further and save the viewport's data directly to disk, use:
ILboolean ilutOglScreenie(ILvoid);
ilutOglScreenie does not modify the current bound image at all.
This function is very specialized and saves the image to a Targa
file with the filename format of screen%d.tga, where %d is a number
from 0 to 126. This function will probably not be suited to most
developers' preferences.