分享
 
 
 

深入Managed DirectX9(一)

王朝c/c++·作者佚名  2006-01-06
窄屏简体版  字體: |||超大  

作者:clayman

Device类是DirectX里的所有绘图操作所必须的。可以把这个类假想为真实的图形卡。场景里所有其他图形对象都依赖于device。你的计算机里可以有一个到几个device,在Mnaged DirctX3D里,你可以控制任意多个device。

Device共有三个构造函数,现在我们只讨论其中的一个,但我们会在后边的内容里讨论其他的。先来看看具有如下函数签名的构造函数

public Device(int adapter,DeviceType deviceType,Control renderWindow,CreateFlags behaviorFlags, PresentParameters[] presentationParameters);

(构造函数的第二种重载类似于上边这个,但它接受来自非托管(或者非windows form)的窗口句柄作为renderWindow。而只接受一个IntPtr参数的重载是非托管com组建指向Idirect3Ddevice9的接口。当你的代码需要和非托管的程序协作时则应用它)

好了,这些参数是什么意思,以及我们怎样来使用呢?呵呵,参数adapter表示我们将要使用哪个物理图形卡。计算机里的所有图形卡都有一个唯一的适配器标识符(通常是0到你的图形卡数量-1),默认的显卡总是表示为0 的图形卡。

下一个参数,DeviceType,告诉了DirectX3D你要创建那种类型的device。这里最常用的值就是DeviceType.Hardware,表示你将创建一个硬件设备。另一个选项是DeviceType.Reference,这种设备允许你使用“参考光栅器”(reference rasterizer),所有的效果由DirectX3D运行时来实现,以很慢、很慢、很慢的速度运行^_^。应该仅在调试时或测试你的显卡所不支持的特性时使用这个选项。

(注意参考光栅器只包含在DirectX SDK里,so DirectX运行时是不能使用这个特性的。最后一个为DeviceType.Software的值允许使用用户自定义的软件光栅器(custom software rasterizer)在不确定是否有这样一个光栅器存在时,忽略这个选项吧^_^。)

rendrWindow表示把设备绑定到的窗口。因为windows form控件类都包含了一个窗口句柄(windows handle),所以很容易把一个确定的类作为渲染窗口。可以使用form、panel或其他任意的控件作为这个参数的值。但现在,我们只用form。

下一个参数用来描述设备创建之后的行为。大部分CreateFlags枚举的成员都能组合起来使用,使设备具有多种行为。但有一些flag是相互排斥的,我们稍后讨论。我们现在只使用SoftwareVertexProcessing标志。这个标志适合于所有定点处理都用CPU计算的情况。应此,这自然比所有点都用GPU处理要慢,因为我们不确定你的显卡是否支持所有特性。So,安全第一,假设你的CPU能完成现在的任务。

最后一个参数,它表示你的设备把数据呈现到显示器的方式。Presentation Parameter类的外观都可以由这个类来控制。我们过后再来深入讨论它的构造函数,现在,我们只关心“Windowed”成员和“SwapEffect”成员。

Windowed成员是一个布尔类型的值,决定设备是全屏还是窗口模式。

SwapEffect成员用于控制缓存交换的行为。如果选择了SwapEffect.Flip,运行时会创建额外的后备缓冲(back buffer),并且在显示时拷贝front buffer。SwapEffect.Copy与Flip相似,但要求你把后备缓冲设为1。我们将要选择的SwaoEffect.Discard,如果缓冲没有准备好被显示,则会丢弃缓冲中的内容(which simply discards the contents of the buffer if it isn’t ready to be presented)。

学了这么多,现在来创建一个设备吧。回到代码上来,首先为我们的程序将创建一个device对象:

(代码略,参见DirectX sdk Tutorial 1: Create a Device)

现在让我们来重写Paint()函数:

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

    {

        device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0);

        device.Present();

    }

我们使用Clear()方法把窗口填充为实心的颜色。它的第一个参数指定了我们要填充的对象;在例子里,我们填充的即是目标窗口。稍后再来讨论ClearFlags枚举的其它成员。第二个参数是我们所要填充的颜色。其他的两个参数先暂时忽略。在device被填充之后,我们必须更新显示:Present方法会为我们完成这个任务。这个方法也有几个重载的类型;上边使用的方法会显示device的整个区域。同样稍后再讨论。

看到有些枯燥了吗,好吧,现在我们来真正绘制一些图形

三维图形世界里最基本的图形就是三角形。使用足够的三角,我们可以呈现出任何东西,甚是是平滑的曲面。没有什么比画一个简单的三角和更好的了。为了使过程尽可能的简单,我们先避开“world space”以及各种变换(当然,我们马上就会提到他们),使用屏幕坐标来绘制一个简单的三角。再绘制我们迷人的三角前,我们必须做2件事。1,我们需要一些数据结构来保存三角的信息。2,我们告诉device来绘制它。

很幸运,DirectX已经有这样的一个数据结构来保存三角了。Direct3D名称空间里叫做CustomVertex的类可以用来储存大多数Direct3D中用到的“顶点格式”数据结构(vertex format)。

一个顶点格式结构把数据保存为一种DirectX3D认识并且可以使用的格式。我们将讨论很多这种结构,但先让我们来看看即将用来创建三角的TransformedColored结构。这个结构告诉DirectX3D运行时我们的三角不需要进行左边变换(比如旋转或移动),因为我们已经指定了使用屏幕坐标系。它也包含了每一个点(顶点)的颜色的信息。回到重写的OnPaint方法添加如下代码:

    CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[3];

    Verts[0].SetPosition(new Vector4(this.Width/2.0f,50.0f,0.5f,1.0f);

    Verts[0].Color = System.Drawing.Color.Aqua.ToArgb();

    Verts[1]`````````

    Verts[2]`````````

    (参见DirectX sdk Tutorial 2: Rendering Vertices)

数组里的每一个元素表示三角的一个顶点,所以我们创建了3个元素。然后我们使用新创建的Vector4结构为每一个成员调用SetPositin方法。变换过的顶点坐标包含了在屏幕上x和y的坐标(相对于屏幕的(0,0)点而言),当然也包括z坐标和rhw成员(reciprocal of homogenous w三维齐次坐标)。先忽略后边两个参数.Vector4结构(注:Vector4其实就是(x,y,z,w)经过变换后成为(x/w,y/w,z/w))是保存这种信息最方便的方式。然后我们设置了点的颜色。注意,我们使用了标准颜色的ToArgb方法。DirectX3D假设所接受的颜色为32为的int。

既然我们已经有了数据就可以告诉DirectX我们需要绘制这个三角形,并且绘制它。在重写的OnPaint里添加如下代码

    device.BeginScene();

    device.VertexFormat = CustomVertex.TransformedColored.Format;

    device. DrawUserPrimitives (PrimitiveType.TriangleList,1,verts); 注意和sdk中的示例有区别

    device.EndScene();

好了,这几行代码是什么意思呢?其实很简单。BefinScene方法告诉DirectX3D我们即将绘制一些东西,为绘制做好准备。现在我们已经告诉了DirectX3D要绘制一些东西,接下来就必须告诉它画什么。这就是VertexFormat属性的作用。它决定了DirectX3D运行时使用哪种“确定的功能管道”(fixed function pipline)格式。在我们的例子里使用变换过的,着色过的顶点管道。

不用担心你现在不明白确定的功能管道是什么意思,我们会很快来讨论它。

DrawUserPrimitives函数是真正发生绘图的地方。So,他的参数是什么意思呢?第一个参数是我们要绘制的初等几何体的类型。有很多种可用的类型,but now,我们只是画一系列的三角形。所以选择了PrimitiveType.TriangleList类型。第二个参数是我们要绘制的三角形的数量。对于一个三角形的集合来说,这个值应该是你的顶点数量除以3。我们只画一个三角,所以设为1。最后一个参数则是DirectX3D用来绘图的数据。最后一个EndSence方法通知DirectX3D我们不再绘图了。你必须再每次调用BeginSence之后都调用这个方法。

如果现在编译运行程序的话,你会发现但移动或重置窗口大小之后,并不会更新显示。原因是当我们需要重绘整个窗口时,Windows并不会每一次都计算窗口的收缩情况。因此,你只是移除了显示过的数据,当并没有删除已经显示的内容。很幸运,有个简单的方法解决这个问题,我们可以告诉Windows窗口总是需要被整个的重绘。在OnPaint的最后加上一下代码:

    this.Invalidate();

呵呵,现在再来试试看,哦,看起来我们破坏了程序!现在只能显示一片空白了,并且我们的三角看起来还在不停的闪烁,尤其是当你调整窗口大小的时候。我们都干了些什么呢?原来“聪明”的Windows总是尝试在Invalidate()方法后来绘制当前的窗口(即空白的这个窗口)。在我们的OnPaint方法之外还存在其他的绘制过程!能容易的通过改变窗口的“style”属性来解决。在构造函数里加上如下代码

    this.SetStyle(ControlStyles.AllPaintingInWmPaint | ConstolStyles.Opaque, true);

哦~,好了,终于erying works as expected。我们所做的就是告诉Windows一切绘图过程都在OnPaint里完成。

(第一部分完,下一步分我们将开始真正的3D之旅,使我们的三角形三维化)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有