自批:读者注意,以下都是肤浅之谈,诚不足作为参考。继续沿袭大片贴源码风格,发一个Managed Direct3D的典型2D渲染实例: ) 采用了Sprite+Texture方式,速度其实也不算慢,代码也还算简洁可靠(除了控制Device Lost异常比较烦琐以外),尤其是在窗口模式下,要考虑的底层细节比DirectDraw要少得多,什么裁剪区域、页切换链等等,如果不想去碰它们,均可交给Direct3D自动管理,当然,如果需要的话也可以自行设置。
不爽的地方在于Direct3D对硬件要求起点比DirectDraw要高,实际2D绘制效率比起DirectDraw还是要慢不少;此外,Direct3D中以纹理绘制方式实现2D渲染决定了其局限性:纹理的形状必须是正方形的,则制作2D Sprite时也不得不将其制作成正方形的,这很不自然;更令人郁闷的是,纹理的象素尺寸必须是2的整数幂,否则在渲染时其尺寸将会被拉伸导致图像模糊、变形;上述两点要求对于传统的2D场景渲染而言都可以说是一些非常不合理的约束,不过我想至今还没有哪款2D Game是纯粹地用Direct3D来做的吧,呵呵,下面这个实例就当见识一下M$向我们所推荐的“未来”的2D渲染编程方式吧。
结论:对于2D的我还是喜欢用DirectDraw — Speed Rules!
//#define FULL_SCREEN

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace MDirect3D


{
public class AppFrm : System.Windows.Forms.Form

{
private Device device;
private Sprite sprite;
private Texture[] texture=new Texture[2];

private Rectangle[] textureSize=new Rectangle[2];
private Vector3 centerPos = new Vector3(0, 0, 0);
private Vector3 position = new Vector3(0,0,1);

private int idx=0; //纹理索引
private PresentParameters PreparePresentParameters()

{
PresentParameters presentParams = new PresentParameters();

初始化设备参数#region 初始化设备参数
#if FULL_SCREEN
presentParams.Windowed = false;
presentParams.BackBufferCount=1;
presentParams.BackBufferWidth=1024;
presentParams.BackBufferHeight=768;
presentParams.BackBufferFormat=Format.X8R8G8B8;
presentParams.SwapEffect = SwapEffect.Flip;
#else
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
#endif
#endregion
return presentParams;
}
private void InitializeGraphics()

{

初始化设备#region 初始化设备
device = new Device(0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, PreparePresentParameters());
#endregion

初始化纹理#region 初始化纹理
//纹理资源创建类型: Pool.Managed - Device Lost之后无需再次创建
texture[0] = TextureLoader.FromFile(device, @"..\..\01.tga");
texture[1] = TextureLoader.FromFile(device, @"..\..\02.tga");

for (int i=0;i<2;i++)
using (Surface s = texture[i].GetSurfaceLevel(0))

{
SurfaceDescription desc = s.Description;
//纹理的尺寸必须是2的整数次幂,否则会拉伸变形
textureSize[i] = new Rectangle(0, 0, desc.Width, desc.Height);
}
#endregion

sprite = new Sprite(device);
}
private void Restore()

{

恢复设备#region 恢复设备
PresentParameters[] ps=new PresentParameters[1];
ps[0]=PreparePresentParameters();
device.Reset(ps);

//由于纹理资源创建类型为Pool.Managed
//所以恢复device的时候无需再次创建
#endregion
}

public void Draw()

{
if (device==null || WindowState == FormWindowState.Minimized)
return;

int result=0;
device.CheckCooperativeLevel(out result);
try

{
switch (result)

{
case (int)ResultCode.Success:

2D绘制过程#region 2D绘制过程

device.BeginScene();
device.Clear(ClearFlags.Target, Color.White , 0.0f, 0);
sprite.Begin(SpriteFlags.None);
sprite.Draw(texture[idx], textureSize[idx], centerPos, position, Color.White);
sprite.End();
device.EndScene();
device.Present();
idx^=1;
#endregion
break;
case (int)ResultCode.DeviceNotReset:

设备恢复过程#region 设备恢复过程
Restore();
#endregion
break;
case (int)ResultCode.DeviceLost:
break;
}
}
catch (Exception e)

{
return;
}
}

乱七八糟#region 乱七八糟

/**//// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;

/**//// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )

{
if( disposing )

{
if (components != null)

{
components.Dispose();
}
}
base.Dispose( disposing );
}


Windows 窗体设计器生成的代码#region Windows 窗体设计器生成的代码

/**//// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()

{
//
// AppFrm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "AppFrm";
this.Text = "Managed Direct 3D";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AppFrm_KeyDown);

}
#endregion
#endregion

public AppFrm()

{
InitializeComponent();

#if FULL_SCREEN
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
#endif

InitializeGraphics();
}
private void AppFrm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{
if (e.KeyCode==Keys.Escape) Close();
}
[STAThread]
static void Main()

{
AppFrm frm=new AppFrm();
frm.Show();


消息循环#region 消息循环
while (frm.Created)

{
frm.Draw();
Thread.Sleep(1000/60);
try

{
Application.DoEvents();
}
catch (Exception e)

{
continue;
}
}
#endregion
}

}
}