1.安装XNA环境
包括DirectX SDK(August 2006),Microsoft Visual C# 2005 Express Edition,XNA Game Studio Express
http://fishton520.spaces.live.com/blog/cns!9a6a10ea32a0412b!187.entry
2.Managed DirectX(MDX)是DirectX托管版本,用类重新封装DirectX函数库,支持C#和VB.NET语言开发DirectX程序.
3.XNA是微软开发游戏的最新集成开发环境简化版,仅支持C#语言.第一目的使游戏开发简化,第二目的编写跨平台游戏(兼容Windows和Xbox 360).
XNA与MDX不兼容.
4.MDX采用左手笛卡尔坐标系统,XNA采用右手笛卡尔坐标系统.使用Vector3(float x,float y,float z),Vector4(float x,float y,float z,float Rhw)存储坐标.
问:3D空间采用3维来记录坐标,为什么会使用Vector4来存储?
答:MDX采用仿射矩阵来计算点坐标,(仿射矩阵描述了一个点到另一个点的位置变化,包含旋转角度及各轴的偏移量.),为了便于使用矩阵计算.
举例如下:
在二维中,矩阵表示一个点[2 1],点逆时针旋转90度,x轴方向平移3,y轴方向平移4,点坐标应为[2 6].
旋转90度矩阵变换公式为
得到结果是[-1 2],向x轴平移3,向y轴平移4,变换公式为[-1 2]+[3 4]=[2 6].
为了简化矩阵运算,可用矩阵[2 1 1]代表点[2 1],使用一个3*3变换矩阵代表这个复合变换,用一个矩阵乘法代替以上两个矩阵运算.如下:
[2 1 1]中增加一列1为了满足矩阵能够相乘(矩阵AB相乘要求
矩阵A的列数必须等于矩阵B的行数,矩阵A矩阵B才能相乘)变换矩阵第三列0 0 1是固定的,
结果[2 6 1]中最后一列1没有意义.
把2D仿射矩阵推广到3D仿射矩阵,任何一个3D坐标系统中的点用(x,y,z,1)表示,用一个4*4的3D仿射矩阵来记录各种3D复合变换操作.在Direct3D和XNA中,
点坐标(x,y,z,1)用vector4结构表示,而4*4仿射矩阵用Matrix结构表示.
5.一些常用词汇
Matrix:矩阵 Translation:平移 Rotation:旋转 Yaw:Y旋转 Pitch:X旋转 Roll:Z旋转 Primitive:图元
6.Device理解为显卡.GPU为显卡内置的处理器.
深度测试是针对点投影到平面的测试,投影到同一平面坐标相同的点,只有坐标Z值最小的点才被投影.简单点讲就是只绘制前面的,后面挡住部分不处理.
7.3D程序基本框架
引用Microsoft.DirectX.Direct3D和Microsoft.DirectX .net的DLL.
Program.cs
Code
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DirectX3DTest
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
using (frmBaseFramework frm = new frmBaseFramework())
{
if (!frm.InitalizeGraphics())
{
MessageBox.Show("不能够初始化Direct 3D,退出!");
}
frm.Show();
while (frm.Created)
{
frm.Render();
Application.DoEvents();
}
}
}
}
}
frmBaseFrameWork.cs
Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace DirectX3DTest
{
public partial class frmBaseFramework : Form
{
private Device device = null;
private bool pause = false;
CustomVertex.TransformedColored[] verts;
public frmBaseFramework()
{
InitializeComponent();
}
public bool InitalizeGraphics()
{
try
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.EnableAutoDepthStencil = true;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
device.DeviceReset += new System.EventHandler(this.OnResetDevice);
this.OnCreateDevice(device, null);
this.OnResetDevice(device, null);
}
catch (DirectXException)
{
return false;
}
return true;
}
public void OnCreateDevice(object sender, EventArgs e)
{
verts = new CustomVertex.TransformedColored[3];
verts[0].Position = new Vector4(150.0f, 50.0f, 0.5f, 1.0f);
verts[0].Color = Color.Aqua.ToArgb();
verts[1].Position = new Vector4(250.0f, 250.0f, 0.5f, 1.0f);
verts[1].Color = Color.Brown.ToArgb();
verts[2].Position = new Vector4(50.0f, 250.0f, 0.5f, 1.0f);
verts[2].Color = Color.LightPink.ToArgb();
}
public void OnResetDevice(object sender, EventArgs e)
{
}
public void Render()
{
if (device == null)
{
return;
}
if (pause)
{
return;
}
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,Color.FromArgb(204,238,208), 1.0f, 0);
device.BeginScene();
device.VertexFormat = CustomVertex.TransformedColored.Format;
device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts);
device.EndScene();
device.Present();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
this.Render();
}
private void Form1_Resize(object sender, EventArgs e)
{
pause = ((this.WindowState == FormWindowState.Minimized) || !this.Visible);
}
}
}
8.TransformedColored结构是根据透视原理在显示屏上直接绘制具有立体感的平面图形记顶点结构.因此使用TransformedColored
结构绘制图形,所有顶点z坐标是一致的.
使用Device类的DrawUserPrimitives(PrimitiveType primitiveType,int primitiveCount,object vertexStreamZeroData);
PrimitiveType指图形的类型,primitiveCount指绘制图形的个数,vertexStreamZeroData指图形顶点TransformedColored数组集合.
primitiveType取值如下:
PointList:绘制若干点.
LineList:绘制若干条线段,每条线段使用两个顶点,每个顶点只使用一次.4个点绘制2条线段.
LineStrip:绘制若干条相连线段,依次使用每个点进行相连绘制相连的线段,除第一个和最后一个顶点使用一次,其余顶点都使用二次.4个点绘制3条线段.
TriangleList:绘制若干三角形,每三个顶点绘制一个三角形,每个顶点只使用一次.6个顶点绘制2个三角形.
TriangleStrip:绘制若干相连三角形,每两面三刀个相连三角形共享两个顶点.例ABCDE五点,ABC一个三角形,BCD一个三角形,CDE一个三角形.
TriangleStrip:绘制若干相连的三角形,每两个相连的三角形共享两个顶点,所有三角形共享一个顶点.例ABCDE五点,ABC一个三角形,ACD一个三角形,ADE一个三角形.
9.VertexBuffer类提供显存缓存功能,提高绘制图形速度.
修改OnCreateDevice方法,使用VertexBuffer存储顶点数组,并为其添加监听器Create,当需要显存重构时,重新添加顶点数组到VertexBuffer中.
Code
public void OnCreateDevice(object sender, EventArgs e)
{
Device dev = (Device)sender;
vertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored), 3, dev, 0, CustomVertex.TransformedColored.Format, Pool.Default);
vertexBuffer.Created += new EventHandler(this.OnCreateVertexBuffer);
this.OnCreateVertexBuffer(vertexBuffer, null);
}
缓存重构时,调用重新添加顶点数组.
Code
public void OnCreateVertexBuffer(object sender, EventArgs e)
{
CustomVertex.TransformedColored[] verts = (CustomVertex.TransformedColored[])vertexBuffer.Lock(0,0);
verts[0].X = 150;
verts[0].Y = 50;
verts[0].Z = 0.5f;
verts[0].Rhw = 1;
verts[0].Color = Color.Aqua.ToArgb();
verts[1].X = 250;
verts[1].Y = 250;
verts[1].Z = 0.5f;
verts[1].Rhw = 1;
verts[1].Color = Color.Brown.ToArgb();
verts[2].X = 50;
verts[2].Y = 250;
verts[2].Z = 0.5f;
verts[2].Rhw = 1;
verts[2].Color = Color.LightPink.ToArgb();
vertexBuffer.Unlock();
}
渲染方法体内使用Drawprimitives进行渲染
Code
public void Render()
{
if (device == null)
{
return;
}
if (pause)
{
return;
}
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,Color.White, 1.0f, 0);
device.RenderState.CullMode = Cull.None;
device.BeginScene();
device.VertexFormat = CustomVertex.TransformedColored.Format;
device.SetStreamSource(0, vertexBuffer, 0);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
device.EndScene();
device.Present();
}
10.背面剔除是指按逆(顺)时针方向绘制图形时将不显示.
Device属性RenderState.CullMode控制背面剔除.
CounterClockwise:不显示按逆时针绘制的三角形,默认.
Clockwisc:不显示按顺时针绘制的三角形.
None:没有背面剔除功能,三角形总被显示.