Additive Blending with Sprites
Xna4.png

Introduction

In this tutorial, we will look at how to do additive blending with sprites. We will start off by looking at what additive blending is, and how it works. Then, we will set up a simple XNA game that does additive blending. If you haven't looked over the tutorials about sprite batches in XNA, you should take a look at that first to get going.

Blending and Additive Blending

In computer graphics, the term blending comes up frequently. Blending is when we combine two or more colors to produce a resulting color. One very common use of blending is transparency. The most common way to do transparency is called alpha blending, where in addition to a red, green, and blue value for a color, we also give it an alpha value, which indicates how transparent the color is. With the methods we have been using so far, alpha blending happens by default.

In this tutorial, we will introduce a new blending technique called additive blending. Additive blending does not require an alpha value for a color. Instead, to combine two colors, we add up their red, green, and blue components to get the resulting color. An example is shown below, where we have Cornflower Blue (r=100 g=149, b=237) and Saddle Brown (r=139, g=69, b=19). Both of these colors are defined in the Color class in XNA. When we combine or "blend" the colors, we get a combination of the two, where r=239, g=218, and b=256. (Since 256 is more than the upper limit of 255, it gets set to 255 instead.)

ColorAddition.png

While it may take a person a little bit of time to do this kind of addition, XNA does it very efficiently. We will see that it can do this for lots and lots of overlapping sprites very quickly, and produce some very nice looking results.

Performing Additive Blending

The actual work required to do additive blending is very simple. We will see that it is only one line of code different from our normal sprite batch drawing. But to illustrate what it can do, we are going to need to do a little bit of work.

Acquiring Content

Our first step will be to get some textures that will be good for additive blending. You can download the files below and use them in your project.

red.png
green.png
blue.png

They are shown here:

red.png green.png blue.png

Download these three textures and import them into your project like we have done in earlier tutorials.

Loading the Textures In

We are now ready to import our textures into our game. To start, let's make a place to store our textures. Let's add the following three variables as instance variables to our game class:

private Texture2D blue;
private Texture2D green;
private Texture2D red;

Now go to the LoadContent() method and load the textures in with the following code:

blue = Content.Load<Texture2D>("blue");
green = Content.Load<Texture2D>("green");
red = Content.Load<Texture2D>("red");

We are now ready to use our textures in our game.

Some Math for Movement

This next little bit might get a little confusing. We are going to do some math to keep track of locations for our sprites. We will want them to move around. This math might get a little confusing. If it does, feel free to just copy and paste the whole section into your code and don't worry too much about what it actually does. We're trying to learn how to do additive blending here, not math.

Go back up and add these seven variables as instance variables to your class, once again:

        private float blueAngle = 0;
        private float greenAngle = 0;
        private float redAngle = 0;
 
        private float blueSpeed = 0.025f;
        private float greenSpeed = 0.017f;
        private float redSpeed = 0.022f;
 
        private float distance = 100;

These variables will allow us to move our sprites around in circles. The first three, the angles, are going to store what angle each of the sprites are located at around the circle. The next three, the speeds, are going to store how fast the sprites are moving in the circle. They are each different values, so you can see them as they overlap. The last one, the distance, is the radius of the circle that our sprites will travel around.

Next, we need to update their angles. So in the Update() method, add the following code:

            blueAngle += blueSpeed;
            greenAngle += greenSpeed;
            redAngle += redSpeed;

Now, as one last step, we will calculate the actual locations of the sprites from their angles (basically converting from polar to cartesian coordinates) just before we draw them. So in the Draw() method, add the following code:

Vector2 bluePosition = new Vector2(
                (float)Math.Cos(blueAngle) * distance,
                (float)Math.Sin(blueAngle) * distance);
Vector2 greenPosition = new Vector2(
                (float)Math.Cos(greenAngle) * distance,
                (float)Math.Sin(greenAngle) * distance);
Vector2 redPosition = new Vector2(
                (float)Math.Cos(redAngle) * distance,
                (float)Math.Sin(redAngle) * distance);
 
Vector2 center = new Vector2(300, 140);

In this code, we calculate a location for each of the sprites as a Vector2. We will use this in a minute to do the actual drawing. The last line is a variable to store where we want our sprites centered. I've moved it to (300, 140) so they don't go in circles around the top corner, but rather, in the middle of the screen.

Drawing our Sprites

We are now ready to draw our sprites. The first thing that I want to do is to change the background color from the default cornflower blue to black. Do this by changing the line at the top of the Draw() method that says:

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

to say:

graphics.GraphicsDevice.Clear(Color.Black);

Finally, we will draw our sprites with additive blending. The following code will do this. Add it to the bottom of your Draw() method.

spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive);
 
spriteBatch.Draw(blue, center + bluePosition, Color.White);
spriteBatch.Draw(green, center + greenPosition, Color.White);
spriteBatch.Draw(red, center + redPosition, Color.White);
 
spriteBatch.End();

Notice that the only real difference from what we have done before is in the SpriteBatch.Begin() call. Normally, we call the version of this method that is SpriteBatch.Begin(), but here, we are calling the one that uses a SpriteBlendMode. We call spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive), which says that we want to do additive blending. The default is BlendState.AlphaBlend, and also notice that there is an option to do BlendState.Opaque, which ignores the alpha channel altogether.

I've included below a couple of screen shots of what your program should look like. Notice how the colors change when two colors are over each other. For example, when the red and green are on the same spot, they look yellow. That is because in additive blending, red + green = yellow.

ScreenShot1.png
ScreenShot2.png

What's Next?

You might want to take a look at the 2D Particle Engines tutorial. It covers an interesting topic in games, and you can combine it with the stuff here to do some really cool looking things!


Troubleshooting.png Having problems with this tutorial? Try the troubleshooting page!