RSS 2.0 Feed
Managed DirectX学习笔记
摘要:上一次我们在Managed DirectX世界里接触到了Direct3D设备的概念,它是Direct3D中几乎所有功能的开始。从这次我要开始在DirectX中绘出3D图形了。3D图形常常用一组包围形状表面的多边形来表示,无论形状多么复杂,我们都可以用一定数目的多边形来逼近。目前用于游戏的显卡多使用三角形网格系统,即用一系列三角形来表示物体的表面。在电影级渲染中,还常常用到四边形网格。关于网格(mesh)这个重要的概念以后还会遇到,这次我将学习如何绘制三角形。 Direct3D支持的图元(Primitive)类型有点、线段、线条、三角、成片三角和三角扇形等。要绘制图元,必须将点集载入到数据流中。顶点缓冲区(Vertex Buffer)即是DirectX保存顶点数据的常用方式。在顶点缓冲区内我们可以对顶点进行各种操作,比如坐标变换、光照等。Direct3D支持灵活顶点格式(FVF),用户可以自行决定在一个顶点数据中包含那些数据,比如顶点的坐标、颜色、法向量等。可以自由搭配各种属性,以至于我们可用自定义的结构体来保存顶点数据。这次我选择的是一种已经预定义在DirectX类库中的类型:CustomVertex::TransformedColored。它包含顶点的坐标、经变换后的坐标以及顶点的漫反射颜色。 创建顶点缓冲区需要使用VertexBuffer类。要定义一个顶点缓冲区,需要下列参数:顶点的结构体类型、个数、设备、顶点缓冲区属性、顶点格式和顶点缓冲区的资源位置。顶点的结构体类型是一个System::Type类型参数(主要是获取顶点结构体的内存大小)。顶点缓冲区属性可以是Usage枚举中的任意值的组合,我这次就用None。顶点格式是对于灵活顶点格式的描述,必须准确指出顶点结构体中包含哪些数据。最后一个顶点缓冲区的资源位置表示将顶点缓冲区置于内存还是显存中。基于这些设置,就可以写出一个初始化顶点缓冲区的函数: //顶点缓冲区全局对象static VertexBuffer^ vb; static Boolean InitializeVertexBuffer(){    //初始化一个三角形的顶点数组    array<CustomVertex::TransformedColored>^ vertices =         gcnew array<CustomVertex::TransformedColored>(3);     vertices[0] = CustomVertex::TransformedColored(150.0, 50.0, 0.5, 1.0, 0xffffff00);    vertices[1] = CustomVertex::TransformedColored(250.0, 250.0, 0.5, 1.0, 0xff00ff00);    vertices[2] = CustomVertex::TransformedColored(50.0, 250.0, 0.5, 1.0, 0xff0000ff);     try    {        //创建顶点缓冲区        vb = gcnew VertexBuffer(            typeid<CustomVertex::TransformedColored>,                          3,  /* 顶点个数 */            d3dDevice,  /* 要使用的Direct3D设备 */            Usage::None,  /* 顶点缓冲区属性 */            CustomVertex::TransformedColored::Format,  /* 灵活顶点格式 */            Pool::Default /* 顶点缓冲区资源位置,这里选择显存 */        );         //填充顶点缓冲区        GraphicsStream^ gs = vb->Lock(0, 0, LockFlags::None);          gs->Write(vertices);         vb->Unlock();         return true;    }    catch(DirectXException^)    {        return false;    }} 别忘了在CleanUp方法中清理使用过的VertexBuffer对象。接下来,我们需要在渲染函数中增加绘制图元的代码。注意:这些代码一定要放在对设备BeginScene函数和EndScene函数的调用之间,否则就会出错。 d3dDevice->SetStreamSource(0, vb, 0);d3dDevice->VertexFormat = CustomVertex::TransformedColored::Format;d3dDevice->DrawPrimitives(PrimitiveType::TriangleList, 0, 1); 最后,我们只要在main函数中添加调用创建顶点缓冲区函数的代码即可: int Main(){    TestMDXForm^ f = gcnew TestMDXForm();    if (DirectXProgram::InitializeDirect3D(f)......[阅读全文]

posted @ | Feedback (20) | Filed Under [ 技术随笔 Managed DirectX学习笔记 ]

摘要:从本篇起,我将进入DirectX图形和游戏的世界。更多Managed DirectX的信息,可以参考IceShark的Blog文章,我这里简单提一下我的感受。Managed DirectX是对DirectX大部分功能的托管封装,可以用任何支持.NET的语言开发。MDX只对DirectX做了非常低层次的封装,因此保持了用COM接口DirectX开发时的大部分原貌。MDX的性能是不用担心的,因为它还是象COM DirectX一样提供对硬件层次的访问,大部分功能都是在你的显卡/网卡/声卡上起作用的,托管部分只是它的接口。事实证明MDX在DirectX Graphics中的性能与COM接口的DirectX不相上下。既然MDX的开发方式、API和性能都与COM接口的DirectX差不多,那为什么要用MDX呢?我自己对这个问题的回答是: 1、托管代码的对象模型更好。MDX基于类库的组织结构,比用COM接口的处理方式更方便。2、用MDX,一般不用操心资源释放的问题。很大一部分资源释放的操作,都被封装好了。3、与更多现代技术结合得更好。我们可以让DirectX程序使用XML、WebService和智能客户端等技术。 Direct3D程序最基本的流程是:创建Windows窗口、创建设备、处理消息循环、物体图形显示、退出和清理。在MDX的世界里,窗口创建和处理消息循环我们交给Windows Forms模型来做,剩下最主要的任务就是创建设备和物体图形显示。Direct3D设备是Direct3D开发最基本的入口,它定义了Direct3D所有的绘图组件,大部分的操作都需要从Direct3D设备开始。创建设备需要设定几个参数,包括显卡序号、设备类型、所属窗口、3D运算方式等。除了这些信息外,还需要一个PresentParameters类型的参数,其中定义了Direct3D设备所需的相关信息。下面代码中的InitializeDirect3D函数完整的演示了创建设备的步骤 设备类型:Direct3D支持3种设备,其中HAL和REF最为重要。HAL通过硬件进行光栅化、坐标变换和光照处理等,速度最快。REF则是用软件实现相关的操作,仅用于硬件不支持某种操作的情况。DeviceType枚举定义了设备类型可能的选项。 3D运算方式包括一些选项,如HardwareVertexProcessing,PureHardwareVertexProcessing等,用于指定顶点运算由硬件执行还是软件执行等。 PresentParameters还包括一些设置,如后台缓冲区的高度、宽度和像素格式,以及从后台缓冲区复制到前台缓存屏幕显示的方式等等。如果Direct3D采用窗口方式运行,像素格式必须查询当前的显示模式获得。 Direct3D设备创建成功以后,就可以进入图形显示阶段。在下面的代码中以Render()函数的形式出现。在绘制图形前,需要调用Device::Clear()函数重制ViewPort的颜色缓冲区。ViewPort就是3D形状投射到平面显示器上供我们看到的那个区域。Clear函数的Flag参数指定了对颜色缓冲区、深度缓冲区还是模板缓冲区进行初始化。因为我用ATI显卡,所以我选择了将颜色缓冲区初始化为红色:)。接下来是调用BeginScene()函数和EndScene()函数。实际的绘图中,所有渲染的代码都必须放在BeginScene函数和EndScene函数之间,否则就会出错。最后调用Present()函数,将后台缓冲区中的数据复制到前台缓冲区,我们就能看见图形了。 下面就是完成这个步骤所需的类。我将其定义为sealed,并将构造函数私有。这样做是为了让这个类仅仅成为我所用静态函数的容器。(在C#中,可以用静态类;在VB中,可以用模块)。 public ref class DirectXProgram sealed{private:    DirectXProgram(void)    {    }public:    //Direct3D 设备全局对象    static Device^ d3dDevice;    static Boolean InitializeDirect3D(Form^ window)    {        //获取显示适配器信息,以便查询显示模式信息        AdapterListCollection^ adapters = Manager::Adapters;        DisplayMode d3ddm = adapters->Default->CurrentDisplayMode;        //创建设备所需的参数        PresentParameters^ params = gcnew PresentParameters();        params->Windowed = true;        params->SwapEffect = SwapEffect::Discard;         params->BackBufferFormat = d3ddm.Format;        try        {            d3dDevice = gcnew Device(0,                 DeviceType::Hardware,                 window,                 CreateFlags::HardwareVertexProcessing,                 params);            return true;        }        catch(DirectXException^)        {            return false;        }    }    static void Render()    {        if(!d3dDevice)        {            return;        }        //后台缓冲区设置为红色        d3dDevice->Clear(ClearFlags::Target, Color::Red, 1.0f, 0);        d3dDevice->BeginScene();        //在这里加入图形绘制程序        d3dDevice->EndScene();        d3dDevice->Present();     }    static void CleanUp()    {        if(d3dDevice)        {            d3dDevice->Dispose();        }    }}; 这是DirectXProgram.h的完整代码 #pragma once namespace......[阅读全文]

posted @ | Feedback (12) | Filed Under [ 技术随笔 Managed DirectX学习笔记 ]