自批:读者注意,以下都是肤浅之谈,诚不足作为参考。
继续沿袭大片贴源码风格,发一个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;
![None.gif](/Images/OutliningIndicators/None.gif)
using
Microsoft.DirectX;
using
Microsoft.DirectX.Direct3D;
![None.gif](/Images/OutliningIndicators/None.gif)
namespace
MDirect3D
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public class AppFrm : System.Windows.Forms.Form
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private Device device;
private Sprite sprite;
private Texture[] texture=new Texture[2];
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
private Rectangle[] textureSize=new Rectangle[2];
private Vector3 centerPos = new Vector3(0, 0, 0);
private Vector3 position = new Vector3(0,0,1);
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
private int idx=0; //纹理索引
private PresentParameters PreparePresentParameters()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
PresentParameters presentParams = new PresentParameters();
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
初始化设备参数#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()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
初始化设备#region 初始化设备
device = new Device(0, DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing, PreparePresentParameters());
#endregion
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
初始化纹理#region 初始化纹理
//纹理资源创建类型: Pool.Managed - Device Lost之后无需再次创建
texture[0] = TextureLoader.FromFile(device, @"..\..\01.tga");
texture[1] = TextureLoader.FromFile(device, @"..\..\02.tga");
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
for (int i=0;i<2;i++)
using (Surface s = texture[i].GetSurfaceLevel(0))
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
SurfaceDescription desc = s.Description;
//纹理的尺寸必须是2的整数次幂,否则会拉伸变形
textureSize[i] = new Rectangle(0, 0, desc.Width, desc.Height);
}
#endregion
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
sprite = new Sprite(device);
}
private void Restore()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
恢复设备#region 恢复设备
PresentParameters[] ps=new PresentParameters[1];
ps[0]=PreparePresentParameters();
device.Reset(ps);
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//由于纹理资源创建类型为Pool.Managed
//所以恢复device的时候无需再次创建
#endregion
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public void Draw()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (device==null || WindowState == FormWindowState.Minimized)
return;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
int result=0;
device.CheckCooperativeLevel(out result);
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
switch (result)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case (int)ResultCode.Success:
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
2D绘制过程#region 2D绘制过程
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
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:
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
设备恢复过程#region 设备恢复过程
Restore();
#endregion
break;
case (int)ResultCode.DeviceLost:
break;
}
}
catch (Exception e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return;
}
}
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
乱七八糟#region 乱七八糟
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if( disposing )
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (components != null)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
Windows 窗体设计器生成的代码#region Windows 窗体设计器生成的代码
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//
// 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);
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
#endregion
#endregion
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public AppFrm()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InitializeComponent();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
#if FULL_SCREEN
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
#endif
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
InitializeGraphics();
}
private void AppFrm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (e.KeyCode==Keys.Escape) Close();
}
[STAThread]
static void Main()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
AppFrm frm=new AppFrm();
frm.Show();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
消息循环#region 消息循环
while (frm.Created)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
frm.Draw();
Thread.Sleep(1000/60);
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Application.DoEvents();
}
catch (Exception e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
continue;
}
}
#endregion
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
}