DirectXTutorial.com
The Ultimate DirectX Tutorial
Lesson 12:  Using Color-Keys
Log In
Lesson Overview

Now we are going to return once more to the subject of textures.  As I mentioned in Lesson 8, there is enough you can do with textures to create an entire tutorial about them.  I won't, but I will tell you quite a bit about them.

In this lesson, we're going to look into a new way to load textures. To add a practical use for this new way, we're going to learn about color-keys, which allow you to have part of an image transparent and part of it drawn.  First we're going to learn what exactly color-leys are, and then we'll go into the new function.

About Color-Keys

And why would we want to draw part of an image?  Let's take an example:

Let's say we wanted to draw a simple blue circle on our screen.  We could create a square, and place a texture of a blue circle on it.  Let's say we use this 256x256 texture:

Image 12.1 - A Blue-Circle Texture

Image 12.1 - A Blue-Circle Texture

Now let's take this textured square and draw it onto a gray background (for whatever reason).

Image 12.2 - The Blue Circle As Displayed

Image 12.2 - The Blue Circle As Displayed

Well, this certainly won't do.  What we want to do here is draw only the blue and hide all the black.  Direct3D fortunately has a way of doing this.  It is called a color-key.

And so what is a color-key?  A color-key is a specified color in a texture that is not drawn when rendering occurs.  For example, if we had specified black as our color key in this image, here is what we would have gotten:

Image 12.3 - The Blue Circle Using a Color Key

Image 12.3 - The Blue Circle Using a Color Key

Now that is, I'm sure, what was originally intended when that texture was made.

When making textures intended to be "color-keyed", it is usually not wise to select black for the transparent color, as black is too often used in the texture itself.  Instead use some arbitrary color that you would never use in your game, such as pink (unless you're thinking of competing with The Sims).  As I can't imagine you using 255, 0, 255 (hot pink) in your game, it's probably safe to use as a color-key.

D3DXCreateTextureFromFileEx()

What a function name!  Not only is it a long name, but it has more parameters than any function we have covered so far!

But don't get discouraged.  This lesson and the next few will be devoted to explaining it in detail, in addition to the many different techniques it supports.

However, let's start with a simple function prototype, examine the parameters, and find out how we can use color-keys.  Then we'll worry about the rest.  So here we go:

HRESULT D3DXCreateTextureFromFileEx(LPDIRECT3DDEVICE9 pDevice,
                                    LPCTSTR pSrcFile,
                                    UINT Width,
                                    UINT Height,
                                    UINT MipLevels,
                                    DWORD Usage,
                                    D3DFORMAT Format,
                                    D3DPOOL Pool,
                                    DWORD Filter,
                                    DWORD MipFilter,
                                    D3DCOLOR ColorKey,
                                    D3DXIMAGE_INFO* pSrcInfo,
                                    PALETTEENTRY* pPalette,
                                    LPDIRECT3DTEXTURE9* ppTexture);

Breathe!

All right, let's dive in!

LPDIRECT3DDEVICE9 pDevice,

Well, it's a good start.  We know this one already.  d3ddev.  Easy.

LPCTSTR pSrcFile,

We know this one too.  It's the filename of the texture we wish to load.  L"Whatever.bmp" is what we need here.  (or no L if you're into that kind of thing).

UINT Width, UINT Height,

These two are not as straightforward as they seem.  You would at first think they were the width and height of the texture, but they are not.  What they do is tell Direct3D to stretch the texture to the size given.  You can stretch it to any size (or give the image's actual size if you don't want Direct3D to stretch the width or the height to a power of 2).

Note that this is unwise for performance reasons, and also because not all video devices support this feature.  To work with everyone, extend the borders of your texture to a power of two and use a color key to make the extra space invisible.  Then, use D3DX_DEFAULT to have the image be stretched to powers of 2 (hopefully it is already this way) or use D3DX_DEFAULT_NONPOW2 to use the texture's original size.

I will be using D3DX_DEFAULT throughout this tutorial, and providing textures of an appropriate size so that we don't have ugly, stretched textures.

UINT MipLevels,

This parameter indicates the number of mip levels the texture will have.

Mip levels are basically copies of textures that intentionally have less detail than the original.  The purpose of having mip levels is so that Direct3D can display textures that are far away with correct accuracy.  Drawing textures that are far away during runtime makes the textures look incorrect.

To correct this, Direct3D, while loading a texture, can make several copies of the texture in memory, each having less quality, but still being accurate.  This process is called mip mapping.  As doing this takes a little time, Direct3D can do it beforehand and have the images ready to draw during runtime.

But back to the beginning, this parameter indicates the number of mip levels the texture will have.  We won't be using it in this lesson, so we'll set it to D3DX_DEFAULT.

DWORD Usage,

This is a parameter which we can use to set advanced details regarding how the texture will be used.  The only way that we intend to use it is to draw it, so we don't need to do anything with this.  We'll just set it to NULL.

D3DFORMAT Format,

Here we have the format of the pixels in the texture.  Because we are planning to use transparency (for the color-key), we'll need to have 8 bits of alpha in the texture, so we'll set this to D3DFMT_A8R8G8B8.

D3DPOOL Pool,

We have gone over this parameter before, although it has been some time.  What it does is tell Direct3D where to create the texture and how.  For the length of this tutorial, we will only be using D3DPOOL_MANAGED, which tells Direct3D to save the texture in video RAM.

I've copied the table we used before up to here so you can have a look at it again.

[Table 12.1 - D3DPOOL Values]

DWORD Filter,

A filter is a technique that can be used to create special results with textures to make them look better under particular circumstances.  We'll be going into this in more detail in future lessons.  For now, we'll set this to D3DX_DEFAULT to get the most efficient filters.

DWORD MipFilter,

This parameter is very similar to DWORD Filter, only it applies to mip maps, rather than the base texture.  We'll also set this one to D3DX_DEFAULT.

D3DCOLOR ColorKey,

This one is easy, and even relevant!  This parameter is the color-key that is to be used for the transparent parts of the image.  Use a D3DCOLOR_XRGB() macro here to indicate which color.

D3DXIMAGE_INFO* pSrcInfo,

This parameter is a pointer to a D3DXIMAGE_INFO struct, in which will be stored all the information about the image loaded.

A D3DXIMAGE_INFO struct is a very useful tool in obtaining information about an image.  The following table lets you in on some of the information it provides:

[Table 12.2 - D3DXIMAGE_INFO Values]

If using this struct is not needed, we can just set it to NULL.

PALETTEENTRY* pPalette

This parameter is only used when programming with 256 colors (quite obsolete for 3D gaming) and so we will not get into it here.  Just set it to NULL.

LPDIRECT3DTEXTURE9* ppTexture

The last parameter!  This is simply a pointer to the texture we are loading to.  It is exactly the same as it was in the smaller version of the function.

And that's it!  Let's take a look at the function as we'll use it in this next sample program:

D3DXCreateTextureFromFileEx(d3ddev,    // the device pointer
                            L"BlueCircle.png",    // the file name
                            D3DX_DEFAULT,    // default width
                            D3DX_DEFAULT,    // default height
                            D3DX_DEFAULT,    // no mip mapping
                            NULL,    // regular usage
                            D3DFMT_A8R8G8B8,    // 32-bit pixels with alpha
                            D3DPOOL_MANAGED,    // typical memory handling
                            D3DX_DEFAULT,    // no filtering
                            D3DX_DEFAULT,    // no mip filtering
                            D3DCOLOR_XRGB(255, 0, 255),    // the hot-pink color key
                            NULL,    // no image info struct
                            NULL,    // not using 256 colors
                            &texture_1);    // load to texture_1

When using this function, it is always a relief to me that almost none of the parameters are actually used. :)

The Finished Program

And without further ado, let's build the program.  This one uses the exact same matrices as the last program, and produces a similar result.  Only this time, we're using color-key transparency instead of alpha transparency.

Note however, that the alpha channels are still required.  Taking these out would put the pink border around the two circles, which isn't very good looking.  I've bolded the lines needed from the last lesson, as well as the new lines added here.

Also, before your run the program, you should download and include this texture: BlueCircle.png

[Show Code]

If you run this code, here is what you will get:

Image 12.4 - Blue Circles in Action

Image 12.4 - Blue Circles in Action

Well, it doesn't look quite as exciting as it is...

Summary

This is just the beginning of the power of textures.  There are many many other things that can be done comming up in the next couple of lessons.

For now, however, try doing these for exercises:

1.  Experiment with image stretching, and figure out when Direct3D will or will not stretch your image.
2.  Make one of the circles red.
3.  Try to get the two circles to rotate through various colors during runtime.
4.  Design your own texture that requires a color-key and use it in the program.

For now, that's all there is in the Direct3D Basics tutorial.  However, do go on and do the Direct3D Meshes tutorial.  If thought you could do a lot with 3D now, you'll do much more by the time you are through with it.

Next Tutorial:  Direct3D Meshes

GO! GO! GO!