Clayman的专栏

It's all about XNA & GPU Programming

孙凌峰ID:soilwork
188065次访问,排名376好友0人,关注者10
soilwork的文章
原创 85 篇
翻译 15 篇
转载 0 篇
评论 324 篇
clayman的公告
嘿嘿 ^o^....
最近评论
CYF:哈哈,楼上的楼上真搞笑。
在企业应用中,WEB是主流,也是趋势。
企业应用与图形完全是两个领域,不相干的东西,何必扯在一起?完全没可比性。。。。。。。
skbaker:应该整理一下,形成系列,方便查找。
文章对入门级用户帮助很大
kobeair:每当我要放弃的时候,我都会来你的博客,回到你写这篇帖子。学习的过程很枯燥并且现在学习的时间越来越少。但是看到这篇文章有种莫名的冲动,而且不断的问自己:“别人能做到!为什么我不行?”
lijunjun:做WEB的人最终是会后悔的.
老鬼菠萝:继续~~~
文章分类
收藏
    相册
    blogs
    David Weller
    nVidia Developer blog
    Rico Mariani
    Shawn Hargreaves
    XNA Team blog
    XNA资源
    XNA Creators Club
    ZBuffer
    Ziggyware XNA Resources
    中国XNA开发网
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 XNA Kick Start (三)收藏

    新一篇: 一些有用的xna站点 | 旧一篇: Need for Time

    第二章  XNA程序员手中的画笔——GraphicsDevice

    本文版权归我所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
    由于本人水平有限,难免出错,欢迎大家和我交流。
    作者:clayman
    Blog:
    http://blog.csdn.net/soilwork
    clayman_joe@yahoo.com.cn

     

           看过艺术家如何绘画吗?无论绘制油画或水彩画,他们总需要一只画笔作为工具。实时渲染和绘画相当类似,不同之处在于我们的画笔是图形加速器,而画布则是一块显存。从OOP的观点来看,我们需要一个类来抽象显卡,这个类就是GraphicsDevice

           这一章,我们将编写计算机图形世界中的“Hello World”程序,学习控制GraphicsDevice的初步技术。

     

    魔法的源泉——GraphicsDevice

           GraphicsDevice类位于Microsoft.Xna.Framework.Graphics名称空间下,它代表了我们系统中的图形加速设备,在XNA中,无论2D还是3D,最终所有的绘图工作都由它来完成,可以说是整个类库中最重要的类之一。相当于DirectX中的IDirect3DDevice9接口,或者Managed DirectX中的Device类。

           在阅读本教程时,你应该把XNA的帮助文件打开,以便随时查阅相关内容。希望你现在已经导航到了GraphicsDevice的成员列表,可以看到这是一个相当大的类,有数十个属性,方法和事件。哦,不要被那些陌生的成员名称吓倒了,我们会逐步学习他们。先来看看构造函数吧。

     

           public GraphicsDevice (GraphicsAdapter adapter, DeviceType deviceType, IntPtr renderWindowHandle,

           CreateOptions creationOptions, PresentationParameters presentationParameters)

     

           注意,与MDX不同,GraphicsDevice只有一个构造函数,不过这已经足够我们学习好一阵了。在编写winFormweb程序时,你也许很容易就猜出某个陌生构造函数中参数的含义,不过对于XNA中的函数,你恐怕就很难猜出其中含义了。一个一个来看这些参数:

     

    GraphicsAdapter示使用哪一个图形硬件创建GraphicsDevice对象。系统中可能会有多块显卡,你必须指定使用其中的哪一个。就像画家可能有很多画笔,但每次只使用一支。计算机中的每个图形加速器都有一个唯一的适配器标示符,它通常是一个32位的整数,并且从0开始计数。比如你的计算机中有2块显卡,那么它们的标示符就分别为01GraphicsAdapter类中的静态成员Adater集合包含了系统中所有可用的图形加速器标示符。集合中的第一个元素,也就是Adapter[0]总代表默认的图形设备。

           此外,GraphicsAdapter对象还能提供一些有用的信息,比如所支持的显示模式,显卡的驱动程序文件和版本,芯片类型,制造商ID等等。

     

    DeviceType:表示所创建的GraphicsDevice类型。DeviceType枚举共有三个值,其中最常用的就是Hardware,他表示将充分利用硬件的图形加速功能来绘图。Reference则意味着所有操作都由软件来模拟,完全放弃图形硬件的加速功能。通常只有在调试程序,或者使用图形硬件所不支持的功能时才使用这个选项。注意,用Reference设备来绘图将相当,相当慢。此外,终端用户所安装的DirectXXNA运行时是不支持Reference设备的。至于另外一个枚举值,你暂时可以忽略它了。

     

    IntPrt是一个指向windows form控件的句柄。把GraphicsDeivce绑定到一个特定控件上,并且在这个控件上绘图。可以使用formpanel或其他类型的控件,但大多数情况下都使用form

     

    CreateOptions:用来GraphicsDevice创建之后的工作行为。最常见的值是HardwareVertexProcessing,表示所有顶点变换都由硬件来进行。你可以把合适的值组合起来使用,比如CreateOptions.HardwareVertexProcessing | CreateOptions.SingleThreaded。更多信息请参考帮助文件。

     

    PresentationParameters:这是一个比较复杂的参数,用来设置许多基本的显示属性,包括刷新率,分辨率,是否以全屏模式绘图,抗锯齿模式,以及后备缓冲和深度/模板缓冲的属性。

           这里有必要介绍后备缓冲(BackBuffer的概念。如前所述,如果把GraphicsDevice比作画笔,那么后备缓冲就是画板。它是显卡中的一块显存,每一帧画面中所要渲染的图形都先保存到后备缓冲中,所有图形绘制完毕以后,再把整块内存提交给显示器,因此,有时也把它称为帧缓冲。提交给显示器的,当前正在显示的缓冲则称为前缓冲(FrontBuffer)。因为需要连续绘图,所以可能有一块以上的后备缓冲,以便把其中一块提交给显示器之后,可以继续在另一块缓冲中绘图,这样就形成了一个缓冲链。

           缓冲链的大小和所选择的缓冲交换模式SwapEffect有关。这个枚举有三个成员:copy模式下,将把当前后备缓冲中所储存的数据进行复制,然后显示。所以缓冲链中只需要一块缓冲,使用它进行重复绘制。Filp模式下,缓冲链将成为一个环,当前进行绘制的后备缓冲将成为下一帧的前缓冲,而当前的前缓冲则变为下一帧的后备缓冲。Discard是默认的交换模式,允许驱动选择最高效的交换方式来管理缓冲交换。它是一个队列,其中的0号元素总代表下一帧将要显示的后备缓冲,而这块缓冲一旦成为前缓冲后,就从队列中移出。

           特别需要注意的是,在全屏和窗口模式下,PresentationParameters成员值的行为是不同的。这里不再逐一讨论,详细的介绍已经甚至可以单独成文了,请仔细参考帮助文档中个成员用法。

     

    Hello XNA

           哦,仅仅一个构造函数就讲了那么多,你是否已经对学习xna有些退缩了。不要担心,对于初学来说,通常使用参数的默认值就行。是时候来编写一些代码了。

           安装了XNA Game Studio Express之后,你大概已经尝试过使用XNA模板生产的程序了,Game类非常简便易用,不是吗。可惜这个类太过于高级了,以至于隐藏了太多XNA的基础知识。所以我们将暂时忽略这个高级类,重新发明轮子,编写一个最简单的XNA程序。

           首先,打开XNA Game Studio Express,新建一个windows应用程序,是的,你没有看错,普通的Windows Application项目。之后,添加对XNA程序集的引用:


           Solution Explorer窗口中右键点击References项,在弹出菜单中选择Add Reference。在弹出的窗口中选中以下三个程序集,点击OK

           Solution Explorer窗口中,打开Form1.Designer.cs文件,编写代码添加对xna名称空间的引用:

     

         using Microsoft.Xna.Framework;

         using Microsoft.Xna.Framework.Graphics;

     

           为了使用XNA绘图,首先要创建GraphicsDevice对象。把它作为Form1的一个私有成员,添加如下代码:

     

         private GraphicsDevice graphicsDevice;

     

           接下来,把创建GraphicsDevice对象的实例的代码放到一个名为“InitializeGraphics”的函数中:

     

            public void InitializeGrahics()

            {

                PresentationParameters presentParsms = new PresentationParameters();

                presentParsms.IsFullScreen = false;

                presentParsms.SwapEffect = SwapEffect.Discard;

     

                graphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                    this.Handle, CreateOptions.HardwareVertexProcessing , presentParsms);

            }

     

           这里先创建PresentationParameters参数,并设置了几个重要的参数值,当然,你也可以根据需要,选择设置其它成员的值。使用默认的图形加速器来创建graphicsDevice对象,注意GrahicsAdapter.DefaultAdapterGraphcisAdapter.Adapters[0]是相等的。第二和第四个参数表示将充分使用图形硬件的加速功能。之后,this.Handle把当前窗口,也就是Form1绑定到了graphicsDevice对象上,表示我们只能对这个窗口进行绘图。

           打开Program.cs文件,把Main()函数修改为以下代码:

     

         static void Main()

         {

             using (Form1 frm = new Form1())

            {

                frm.Show();

                frm.InitializeGrahics();

                Application.Run(frm);

              }

          }

     

           虽然对原来的代码稍稍做了改变,但它仍然是相当标准的winForm程序初始化代码。需要提醒的是必须在Run方法之间调用InitializeGraphics方法。后面我会告诉你这样做的原因。

           好了,现在运行程序,可以看到和普通的winForm程序完全一样。显然,我们只是创建了graphicsDevice对象,还没使用它来绘图,绘图任务仍然是由GDI+来完成,因此,我们必须重载Form1OnPaint方法。程序运行之后,每次需要重新绘制窗口,都会调用这个函数绘图,也就是为什么必须确保在程序运行前创建graphicsDevice对象。在Form1中添加以下代码:

     

         protected override void OnPaint(PaintEventArgs e)

         {

             graphicsDevice.Clear(ClearOptions.Target, Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue, 1.0f, 0);

             graphicsDevice.Present();

         }

     

           还记得我们把后备缓冲比做画板吗,显存中可能包含着一些随机的数据,所以如果我们只是在后备缓冲中的部分区域绘图,那么显示时,未绘制过的部分中的随机数据也会被呈现出来,就像在一张不干净的画板上绘图一样。这当然不是我们想要的效果,应该在绘图前把画板“清洗”,或者说填充为预期的背景颜色。这就是Clear()方法的任务。它的第一个参数代表我们希望对哪种缓冲进行清洗,目前只需要使用Target参数就可以了,在后面的内容中会讨论其他选项。第二个参数则是我们预期的背景颜色。画家通常钟情于白色,而图形开发者更加偏爱黑色或者蓝色,当然,也可以是任何你喜欢的颜色,后面两个参数用来初始化深度和模板缓冲值,暂时可以忽略它们。

           至于Present()函数,它的任务就是在绘图结束之后,把后备缓冲提交给显示器,也就是完成前面所说的把后备缓冲变为前缓冲的任务。

           再次运行程序,可以看到窗口已经变为淡蓝色了。恭喜,你完成了第一个XNA程序。目前,只清洗了后备缓冲,并没有绘制其他图形,因此,窗口只显示一片实心蓝色。如果删除Clear(),并且你还运行过其他3D程序,那么再次运行Form1,则有可能看到一些混乱的图形。


    ~~~~~~~~~~~未完待续~~~~~~~~~~~


    ^_^

     

    发表于 @ 2007年02月08日 03:03:00|评论(loading...)|编辑

    新一篇: 一些有用的xna站点 | 旧一篇: Need for Time

    评论

    #ProjectDD 发表于2007-02-22 09:00:04  IP:
    果然,整个窗口变成蓝色了,呵呵...
    #flankerfc 发表于2007-04-26 06:18:03  IP: 124.114.56.*
    很不错! 用来学习
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © clayman