The Ultimate DirectX Tutorial
Lesson 10: Blending Colors for Special Effects
Lesson Overview

In this lesson I am going to cover a special technique that you may or may not always use. This technique is called color blending.

What is color blending?

Simply put, color blending is a way to mix two color together to produce a third color. For example, if you blend blue and red together, you get purple.

There are other effects that can also be produced, such as semi-transparency. If you take an object you wish to draw, and blend each pixel with the one behind it, you can make the object look somewhat invisible. This particular effect will be covered in this lesson, although there are hundreds more that can be achieved.

Blend Operations

Because of the flexibility of color blending, DirectX requires that you specify exactly how you want your blending to be done. To do this, DirectX uses what is called a blend operation. A blend operation is simply an equation with two unknown values which, when filled, produce a third value. If you fill the two values with color, the third color is some combination of the two you provided.

As you can see, each red, green and blue value from both colors were run through the equation, blended, and a new set of primary colors was produced. This is the basis of all color blending. Now let's look at this in detail.

A blend operation (or blend equation) has five parts: the source color, the source factor, the operation, the destination color and the destination factor. Let's take a look at the whole equation, then go into each of the parts in detail.

Final Color = (Source Color x Source Factor) Operation (Dest Color x Dest Factor)

Source Color and Dest Color

Color blending takes place when you draw on object onto the back buffer. This equation is run for each pixel drawn. The source color is the color of the pixel that is being drawn, while the destination color is the color of the pixel that was behind the one drawn, like this:

Source Color and Destination Color

The values of these colors are automatically set based on what you are drawing, and nothing need be done for Direct3D to set these values.

Source Factor and Dest Factor

In color blending, each primary color is multiplied by some pre-determined factor. While this can get quite complex, building a simple color blend is quite simple. Before you begin rendering, you tell Direct3D what it should use for these factors. Usually, you will use an object's Alpha channel. We'll go over how this is done in a moment.

When you select what factor is to be used, Direct3D always translates that value into a FLOAT between 0.0 and 1.0.

In color blending, each primary color is multiplied by some other number between 0.0 and 1.0. Where that number comes from, you will determine (we'll go over how in the next section).

For example, if you were to create a semi-transparency effect, you might use a model's alpha channel. The alpha channel (which is a value between 0 and 255) gets translated into a value between 0.0 (fully transparent) and 1.0 (fully opaque). The color is then multiplied by new number. If the alpha were 192 (or .75 once translated), then the color would show at 75 of its usual brightness. All you would then have to do is add 25 of whatever was behind that (we'll go over this in a bit as well)

Operation

In addition to the source factor and the destination factor, you are also able to set the overall operation used between the source and the destination. Available settings for this are addition, subtraction, minimum (the darker of the two colors) and maximum (the brighter of the two colors).

Enough! Let's get on with the code. section Using Color Blending

Blending colors is quite simple in practice, and only takes a few lines of code. This lesson happens to be oriented around semi-transparency, and these are the steps taken to achieve this effect:

1. Turn on Blending
2. Set the Operation for the Blend Equation
3. Set the Source and Destination Factors
4. Set the Alpha Values in the 3D Model

1. Turn on Blending

Before any color blending can be done, Direct3D must be informed. This is a simple call to the ever-useful SetRenderState() function, like so:

d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

Setting the parameters to D3DRS_ALPHABLENDENABLE and TRUE turns on color blending.

2. Set the Operation for the Blend Equation

This step is also simple, and requires another call to SetRenderState(). This time, the parameters are a little more flexible.

d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

The first parameter is D3DRS_BLENDOP, which indicates that we are going to set the operation. The second parameter tells what operation we are setting it to. The various values you can put into this parameter are listed here:

ValueDescription
D3DBLENDOP_ADDThis is the one we'll use in this lesson. This indicates that the destination color will be added to the source color.
D3DBLENDOP_SUBTRACTThis indicates that the destination will be subtracted from the source.
D3DBLENDOP_REVSUBTRACTThis indicates the reverse of regular subtraction, that the source will be subtracted from the destination.
D3DBLENDOP_MINThis indicates that the darker of the two colors will be used. Note that this is done to each primary color separately, not to the whole color.
D3DBLENDOP_MAXThis indicates that the brighter of the two colors will be used.

3. Set the Source and Destination Factors

Here, we have to make two calls to SetRenderState(), once for each factor. To set the source factor, we use the flag D3DRS_SRCBLEND in parameter 1. Next, we set the destination factor with D3DRS_DESTBLEND in parameter 1, as shown here:

d3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
d3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
d3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

Just as with the operation, each factor is flexible, and there are fifteen different options to choose from. Not all of them are listed in this tutorial, as most of them you will never need. However, the most commonly-used values are given here:

ValueDescription
D3DBLEND_SRCALPHAThe factor used is the alpha value of the object being drawn.
D3DBLEND_INVSRCALPHAThe factor used is the inverse of the alpha value of the object being drawn. In other words, because the value is between 0.0 and 1.0, this would be equal to 1 - alpha.
D3DBLEND_SRCCOLORThe factor used is the source color.
D3DBLEND_INVSRCCOLORThe factor used is the inverse of the source color.
D3DBLEND_DESTCOLORThe factor used is the destination color.
D3DBLEND_INVDESTCOLORThe factor used is the inverse of the destination color.
D3DBLEND_ZEROThe factor used is zero, meaning the color is treated as if it were black.
D3DBLEND_ONEThe factor used is one, meaning the color is not changed at all.

When reviewing the table, note that all the values mentioned there (such as the color and the alpha) start as a value between 0x00 and 0xFF (0 to 255) and get translated to a value between 0.0 and 1.0.

4. Set the Alpha Values in the 3D Model

This is the easy step. All we need to do is change the alpha values of each color in whatever object we're going to use. For this lesson, we'll use two squares, one somewhat transparent and the other fully opaque. Also, for simplicity we'll not use index buffers.

Here are the coded vertices:

// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX t_vert[] =
{
// square 1
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_ARGB(255, 0, 0, 255), },
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_ARGB(255, 0, 255, 0), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_ARGB(255, 255, 0, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_ARGB(255, 0, 255, 255), },

// square 2
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_ARGB(191, 0, 0, 255), },
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_ARGB(191, 0, 245, 0), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_ARGB(191, 255, 0, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_ARGB(191, 0, 255, 255), },
};

Notice that instead of using the D3DCOLOR_XRGB macro, we're switching to the D3DCOLOR_ARGB macro instead. This one takes four parameters, the first being alpha, and the other three being red, green and blue.

In this example, I've set the alpha for the first square as 191 (3/4 opaque), and for the second square as 255 (full opaque).

The Finished Program

And now let's look at the whole program. There are several parts taken out such as lighting and textures, while the transparency code was put in.

Note: I haven't bolded every change in this example, as most of the changes from the last lesson are quite irrelevant here, and are simply there to clean up all the stuff we're getting rid of.

[Main.cpp]

This code is quite straightforward, without all the additional lighting and texture code included. If you run this, you should get something like this:

Alpha Squares in Action
Summary

That isn't all there is to color blending. There are fifteen different flags that you can plug into the source factor and the destination factor, not to mention the five different operations. This leaves you with 1125 different combinations of color blending. Of course, many do the same as other combinations, but there is still quite a bit to play around with.

Therefore, before going on, try doing these for exercises:

1. Make the front square have 25% transparency.
2. Study the tables above and concoct your very own alpha blend. See if it does what you expected!
3. Try making both objects transparent, and switching their positions and see what happens.

Congratulations! You now know the basics of Direct3D programming! But in case this worried you, never fear, for the adventure has only just begun!