Click here to Skip to main content
Click here to Skip to main content

XNA Alpha Textures

, 5 Jan 2011
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Tiberiu Boros
Other Research Institute For Artificial Intelligence, Ro
Romania Romania
No Biography provided

Comments and Discussions

 
GeneralMy vote of 4 PinmemberSlacker0075-Jan-11 23:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140821.2 | Last Updated 6 Jan 2011
Article Copyright 2011 by Tiberiu Boros
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid