Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

XNA Alpha Textures

0.00/5 (No votes)
5 Jan 2011 1  
This shows how to create and combine transparent sprites in C# XNA
main_print_screen.png

Introduction

Terrain rendering is a very common technique used in 3D and 2D games. There are many approaches from simple vertex coloring to stitching together images, etc.

A realistic looking effect can be achieved by using multiple textures blended in using an alpha factor. Also if you want to obtain high resolution terrain, you can either use high detail textures or simply add the detail afterwards.

This article shows how to create and combine a couple of textures used in 2D sprites in order to obtain a realistic ground effect. It also adds a last ground detail texture which gives the impression of high resolution textures. It’s actually an old technique used in 3D Game Rendering especially when processing height maps. This example only uses 2D images and generates 2D terrain. If you want more advanced techniques, you should check for Height Maps and multi-texturing.

Topics Covered by this Project

  • XNA Sprite rendering
  • Alpha Blending
  • Terrain Rendering (2D) 

Specifications

The application includes the following features:

  • Manipulation of alpha gradient in Images
  • First steps in creating realistic looking terrain
  • Texture processing and manipulation in XNA
  • Resources found in other XNA samples or downloaded directly from Google

Technical Information 

  • Uses XNA Framework for 2D rendering
  • Code written in C#

Requirements

  • Visual C# Express or Visual Studio
  • XNA Game Studio 
  • XNA-compatible hardware  

Using the Application 

The application is just a demo, the only interaction with the user is scrolling around the map. Just hold down the left mouse button in the desired corner of the main screen, and the map will start scrolling.

Using the Code

All you need for this to work is a set of images (same size) and a reference grayscale bitmap (fitting the given images) used to generate the alpha factor and a detail texture (any size).

You start by creating the alpha masks from the reference bitmap:

Bitmap alpha1 = BuildAlphaMap(bmp, 0, 84); 

Then you have the combine the texture image with its alpha map:

groundTextures[1] = FromFileWithAlpha(gd, "Terrain/grass.bmp", alpha1); 

The BuildAlphaMap truncates the result for colors under the minimum and over the maximum interval and creates a smooth alpha transition in-between.  

private Bitmap BuildAlphaMap(Bitmap bmp, int min, int max) {
            Bitmap tmp = new Bitmap(bmp.Width, bmp.Height);
            for (int i = 0; i < bmp.Width; i++) {
                for (int j = 0; j < bmp.Height; j++) {
                    byte col = 0;
                    if (bmp.GetPixel(i, j).B < min) {
                        //
                    } else if (bmp.GetPixel(i, j).B > max) {
                        col = 255;
                    } else {
                        float rez = (float)(bmp.GetPixel(i, j).B - min) / (max - min);
                        col = (byte)(rez * 255);
                    }
                    tmp.SetPixel(i, j, System.Drawing.Color.FromArgb(col, col, col));
                }
            }
            return tmp;
        }

The following code takes a reference bitmap and another image used as the base texture and creates the alpha component given certain parameters.

 public static Texture2D FromFileWithAlpha
	(GraphicsDevice gd, string FileName, Bitmap AlphaMap) {
            try {
                Bitmap source = (Bitmap)Image.FromFile(FileName);
                //resize the alpha map (just in case)
                Bitmap alpha = new Bitmap
			(AlphaMap, new Size(source.Width, source.Height));

                Texture2D tex = new Texture2D
		(gd, source.Width, source.Height, 1, 
			TextureUsage.Linear, SurfaceFormat.Color);
                ColorData[] cd = new ColorData[source.Width * source.Height];
                for (int i = 0; i < source.Height; i++) {
                    for (int j = 0; j < source.Width; j++) {
                        cd[i * source.Width + j].A = alpha.GetPixel(j,i).R;
                        cd[i * source.Width + j].R = source.GetPixel(j, i).R;
                        cd[i * source.Width + j].G = source.GetPixel(j, i).G;
                        cd[i * source.Width + j].B = source.GetPixel(j, i).B;
                    }
                }
                ////Todo: de optimizat
                //int[] tmp = new int[512 * 512];
                //for (int i = 0; i < cd.Length; i++) {
                //}
                tex.SetData(cd);
                return tex;
            } catch (Exception e) {
                throw e;
            }
        }

Finally, all we need is to render all the sprites from the same coordinates, with the same size, then add the detail texture. Note that the first image was not given any alpha component, because there was no need for this.

 public void Render(int x, int y) {
            sdr.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend);
            for (int i = 0; i < 4; i++) {
                sdr.SpriteBatch.Draw(groundTextures[i], 
		new Microsoft.Xna.Framework.Rectangle(-x + 0, -y + 0, width, height), 
		Microsoft.Xna.Framework.Graphics.Color.White);
            }
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {

                    sdr.SpriteBatch.Draw(detailTexture, 
			new Microsoft.Xna.Framework.Vector2(i * 512 - (x % 512), 
			j * 512 - (y % 512)), 
			Microsoft.Xna.Framework.Graphics.Color.White);
                }
            }
            sdr.SpriteBatch.End();
        }

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here