65.9K
CodeProject 正在变化。 阅读更多。
Home

XNA Alpha 纹理

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (5投票s)

2011年1月5日

CPOL

2分钟阅读

viewsIcon

32370

downloadIcon

1126

这展示了如何在 C# XNA 中创建和组合透明精灵。

main_print_screen.png

引言

地形渲染是3D和2D游戏中一种非常常见的技术。有很多方法,从简单的顶点着色到拼接图像等等。

通过使用alpha值混合多张纹理,可以实现逼真的效果。另外,如果你想获得高分辨率的地形,你可以使用高细节纹理,或者简单地在之后添加细节。

本文展示了如何创建和组合用于2D精灵的纹理,以获得逼真的地面效果。它还添加了一张最后的地面细节纹理,给人一种高分辨率纹理的印象。这实际上是一种在3D游戏渲染中使用的旧技术,尤其是在处理高度图时。这个例子只使用2D图像并生成2D地形。如果你想要更高级的技术,你应该查看高度图和多纹理。

项目涵盖的主题

  • XNA 精灵渲染
  • Alpha 混合
  • 地形渲染 (2D) 

规格

该应用程序包含以下功能

  • 图像中alpha渐变的操纵
  • 创建逼真地形的第一步
  • XNA 中的纹理处理和操纵
  • 在其他 XNA 示例中找到或直接从 Google 下载的资源

技术信息 

  • 使用 XNA Framework 进行 2D 渲染
  • 代码用 C# 编写

要求

  • Visual C# Express 或 Visual Studio
  • XNA Game Studio 
  • 兼容 XNA 的硬件 

使用应用程序 

该应用程序只是一个演示,与用户的唯一交互是滚动地图。只需按住主屏幕所需角落的鼠标左键,地图就会开始滚动。

Using the Code

使其工作所需的全部内容是一组图像(大小相同)和一个参考灰度位图(适合给定的图像),用于生成alpha值,以及一张细节纹理(任何大小)。

你首先从参考位图创建alpha蒙版

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

然后将纹理图像与其alpha图组合

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

BuildAlphaMap 截断低于最小值和高于最大间隔的颜色结果,并在两者之间创建平滑的alpha过渡。  

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;
        }

以下代码获取一个参考位图和另一个用作基本纹理的图像,并根据某些参数创建alpha组件。

 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;
            }
        }

最后,我们只需要从相同的坐标渲染所有精灵,使用相同的大小,然后添加细节纹理。请注意,第一张图像没有赋予任何alpha组件,因为不需要这样做。

 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();
        }
© . All rights reserved.