XNA Alpha 纹理






4.71/5 (5投票s)
这展示了如何在 C# XNA 中创建和组合透明精灵。

引言
地形渲染是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();
}