Direct3D程序最基本的流程是:创建Windows窗口、创建设备、处理消息循环、物体图形显示、退出和清理。
在MDX的世界里,窗口创建和处理消息循环我们交给Windows Forms模型来做,
剩下最主要的任务就是创建设备和物体图形显示。Direct3D设备是Direct3D开发最基本的入口,它定义了Direct3D所有的绘图组件,大部分的操作都需要从Direct3D设备开始。
创建设备需要设定几个参数,包括显卡序号、设备类型、所属窗口、3D运算方式等。除了这些信息外,还需要一个PresentParameters类型的参数,其中定义了Direct3D设备所需的相关信息。PresentParameters包括一些设置,如后台缓冲区的高度、宽度和像素格式,以及从后台缓冲区复制到前台缓存屏幕显示的方式等等。如果Direct3D采用窗口方式运行,像素格式必须查询当前的显示模式获得。
设备类型:Direct3D支持3种设备,其中HAL和REF最为重要。HAL通过硬件进行光栅化、坐标变换和光照处理等,速度最快。REF则是用软件实现相关的操作,仅用于硬件不支持某种操作的情况。DeviceType枚举定义了设备类型可能的选项。
Direct3D设备创建成功以后,就可以进入图形显示阶段。
绘制图形前需要使用Device.clear()方法重制ViewPort的颜色缓冲区。ViewPort就是3D形状投射到平面显示器上供我们看到的那个区域。Clear中的Flag参数指定了对颜色缓冲区、深度缓冲区还是模板缓冲区进行初始化
实际的绘图中,所有渲染的代码都必须放在BeginScene函数和EndScene函数之间,否则就会出错。最后调用Present()函数,将后台缓冲区中的数据复制到前台缓冲区,我们就能看见图形了。
绘制图形
Direct3D支持的图元(Primitive)类型有点、线段、线条、三角、成片三角和三角扇形等。
要绘制图元,必须将点集载入到数据流中。顶点缓冲区(Vertex Buffer)即是DirectX保存顶点数据的常用方式。在顶点缓冲区内我们可以对顶点进行各种操作,比如坐标变换、光照等。Direct3D支持灵活顶点格式(FVF),用户可以自行决定在一个顶点数据中包含那些数据,比如顶点的坐标、颜色、法向量等。可以自由搭配各种属性,以至于我们可用自定义的结构体来保存顶点数据。
创建顶点缓冲区需要使用VertexBuffer类
Eg. vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);
参数:顶点的结构体类型、个数、设备、顶点缓冲区属性、顶点格式和顶点缓冲区的资源位置。
Device类:
绘图操作可必须的,假想为真实的图形卡。场景里所有的图形对象依赖于它。
构造函数:public Device(int adapter,DeviceType deviceType,Control renderWindow,CreateFlags behaviorFlags, PresentParameters[] presentationParameters);
Eg. device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
参数1: adapter表示将要使用那个图形卡,默认为0.
参数2: 告诉DirectX3D要创建那种类型的device,最常用的是DeviceType.Hardware,表示将创建一个硬件设备,还可以用DeviceType.Reference,表示允许你使用“参考光栅器”(reference rasterizer),所有的效果由DirectX3D运行时来实现。
参数3:表示把设备绑定到的窗口
参数4:描述设备创建之后的行为。SoftwareVertexProcessing标志适合于所有定点处理都用CPU计算的情况,但这比所有点都用GPU处理要慢
还可以是:Hardware VertexProcessing, MixedVertexProcessing。若硬件不支持,将失败。
参数5:表示你的设备把数据呈现到显示器的方式。 其中,PresentParameters presentParams = new PresentParameters();Presentation Parameter类的外观都可以由这个类来控制
PresentParameters类应用
Eg. PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
其成员1:Windowed属性,是一个布尔类型的值,决定设备是全屏还是窗口模式。
成员2:SwapEffect 用于控制缓存交换的行为
Device.Clear()方法:将视区或视区中的一组矩形清除为指定的 RGBA 颜色,清除深度缓冲区并清除模具缓冲区。
Device.Clear(ClearFlags, Color, Single, Int32)
Eg. device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0);
参数1:flags指示要清除的图面的标志。枚举类型
· Stencil:将模具缓冲区清除为 stencil 参数中的值。
· Target:将呈现目标清除为 color 参数中的颜色。
· ZBuffer:将深度缓冲区清除为 zdepth 参数中的值。
Device.Present()方法:更新显示。按照设备拥有的后台缓冲区的顺序,在显示器上呈现下一个缓冲区的内容。
DirectX已经有这样的一个数据结构来保存三角了。Direct3D名称空间里叫做CustomVertex的类可以用来储存大多数Direct3D中用到的“顶点格式”数据结构(vertex format)。
CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[3];
verts[0].X=150;verts[0].Y=50;verts[0].Z=0.5f; verts[0].Rhw=1; verts[0].Color = System.Drawing.Color.Aqua.ToArgb();
verts[1].X=250;verts[1].Y=250;verts[1].Z=0.5f; verts[1].Rhw=1; verts[1].Color = System.Drawing.Color.Brown.ToArgb();
verts[2].X=50;verts[2].Y=250;verts[2].Z=0.5f; verts[2].Rhw=1; verts[2].Color = System.Drawing.Color.LightPink.ToArgb();//使用了标准颜色的ToArgb方法。DirectX3D假设所接受的颜色为32为的int。
每个元素表示三角的一个顶点
绘制三角形
device.BeginScene();
device.VertexFormat = CustomVertex.TransformedColored.Format;
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
device.EndScene();
VertexFormat属性决定了DirectX3D运行时使用哪种“确定的功能管道”(fixed function pipline)格式
DrawUserPrimitives函数是真正发生绘图的地方,第一个参数是我们要绘制的初等几何体的类型,第二个参数是我们要加载的第一个顶点的索引,第三个数要呈现的基元的数量
三
先前在我们创建第一个三角形的时候,我们使用了一个叫做“经过变换的”(transformed)坐标系统。这种坐标是显示器的屏幕区所使用的坐标
应在世界坐标(world space)里定义每一个顶点。你可以把世界坐标设想为一个无限大的三维笛卡儿坐标。你可以把你的对象放到这个“世界”的任意位置。
CustomVertex.positionColored[] verts = new CustomVertex. positionColored[3];
device.VertexFormat = CustomVertex.PositionColored.Format;
1、 在世界坐标里绘制顶点
2、 使用摄像机使来观看顶点
在device上通过两个不同的变换来控制摄像机, 每一种变换都被定义为一个4×4的矩阵传递给DirectX3D
2.1映射变换定义了场景被怎样投影到显示器。最简单的产生投影矩阵的方法就是使用Matrix类的PerspectiveFovLH方法
public static Matrix PerspectiveFovLH (
float fieldOfViewY,
float aspectRatio,
float znearPlane,
float zfarPlane
)
投影变换描绘了场景的视见体(注:即可见部分)。视见体是由可视角度和前裁剪面(Near Plane)与后裁剪面(Far Plane)定义的一个平截头体.
函数头里的nearPlane和farPlane两个参数,描绘了锥体的边界:farPlane就是锥体的底面,而nearPlane则是横截面。fieldOfView参数描绘了锥体的角度。aspectRatio类似于电视的高宽比,比如,宽银幕电视的高宽比是1.85。你可以用可视区域的宽度来比上高度得出这个值。DirectX3D只绘制在这个平截头体中的物体。
2.2 包含摄像机信息的View Transform
可用下面的函数实现:
public static Matrix LookAtLH (
Vector3 cameraPosition,
Vector3 cameraTarget,
Vector3 cameraUpVector
)
3个参数用来描述摄像机的属性。
1 摄像机位置 2 它的观察点的位置 3被参考为“up”的方向,定义当前世界坐标系的上方的,一般为[0, 1, 0]。
3、设置灯光.
在没有经过变换的环境里,DirectX3D默认使用灯光来计算场景中几何体每一个象素的颜色.
可以安全并且简单的把场景里的灯关了, dev.RenderState.Lighting = false
4、 更改坐标,让图像转起来
Direct3D在改变窗口大小时,需要重置device,否则,DirectX会按照原来的分辨率继续渲染场景
只有在几何体的每一个面都有一条法线(normal)时,才会进行灯光的计算