zoukankan      html  css  js  c++  java
  • D3D学习摘记(I)下

    Note:这是(I)的下篇,并不是一篇独立的主题。它的上篇和中篇分别在这里这里

    Render()函数做了些什么

    在消息处理函数中,针对WM_PAINT消息,会有Render函数的调用。该函数负责D3D实体的绘制。让我们分析下它的代码。

    Code

    这段代码很简单,总共做了三件事。第一,清空后台缓冲区的数据;第二,绘制场景;第三,将绘制好的场景搬到前台缓冲区,以便显示在屏幕上。

    “清空后台缓冲区数据”是通过调用D3D设备对象的方法Clear方法起作用的。这个函数有6个参数,查找SDK,会发现它的原型如下:

    HRESULT Clear(DWORD Count,
                         const D3DRECT *pRects,
                         DWORD Flags
                         D3DCOLOR Color
                         float Z,
                         DWORD Stencil );

    下面依旧说说我的理解。

    Count and pRects这两个参数合起来约束了一件事情,即指定一堆需要清空的矩形。也就是说,我们可以指定清空屏幕上指定位置和大小的矩形范围的数据,而且这个矩形范围还可以不止一个(当然一个也可以)。你会猜到,这么“一堆”的矩形最好存放的地方就是在一个数组里。Count表示矩形的数量,而PRects是一个指向这个矩形数组的指针。一般情况下,这两个都是0,表示要清空“整屏”的数据。注意当pRects是0时Count一定要为0,反之当PRects不为0(代表至少指定了一个矩形)时Count也一定不能为0。

    Flags: 这个旗位的值是一组宏,代表了要清空的目标缓冲区是什么。我们知道后台缓冲区有多个类型(模板缓存、深度缓存、颜色缓存等等),因此需要明确清空的是哪个缓冲区。它的值有:D3DCLEAR_STENCIL, D3DCLEAR_TARGET, D3DCLEAR_ZBUFFER三种。分别表示模板缓冲区、目标缓冲区和深度缓冲区。一般选择D3DCLEAR_TARGET。模板缓冲区和深度缓冲区可以被清除的前提是它们首先是存在的,否则调用这个函数时就会返回一个错误。

    Color: 这是一个D3DCOLOR类型的数据,表示要以什么颜色清空(“填充”)该缓冲区。设定为什么颜色,被清空的区域的背景就会显示为什么颜色。关于D3DCOLOR的结构请自行查阅。这里这个值是D3DCOLOR_XRGB( 0, 0, 255 )。

    Z:用这个值填充指定区域的深度缓冲区数据。范围在0到1之间。如果关闭深度缓存,则不会被改写。

    Stencil:用这个值填充指定区域的模板缓冲区数据。范围在0到2n–1之间。这里的n是模板缓冲区一个像素单位的比特数。

    我们这里的代码仅仅指定了要清空整个目标缓冲区,颜色是蓝色。z为1和stencil为0不会发生作用,因为我们并没有指定要清空这两个区域。需要补充一句的是,Flags的值在实际应用中一般是D3DCLEAR_TARGET 和 D3DCLEAR_ZBUFFER的组合。

    接下来是绘制场景。这是通过D3D设备对象的一对方法共用来实现的。这一对方法是:

    D3DDeviceObj->BeginScene()
         //…具体绘制命令
    D3DDeviceObj->EndScene()

    如果你学过openGL,会发现它们在这一点的机制上有很大雷同之处。具体的图元绘制命令必须写在这一对命令之间才会起作用。我们这里的例子是空的,因为我们的目的仅仅是搭一个框架而已。

    再接下来我们把绘制好的后台缓冲区交换到前台缓冲区去。这里用到了D3D设备对象的Prensent方法。还是看看SDK上它的函数原型。

    HRESULT Present(CONST RECT *pSourceRect,
                            CONST RECT *pDestRect,   
                            HWND hDestWindowOverride,   
                            CONST RGNDATA *pDirtyRegion );

    它有四个参数。我对此的理解是:

    pSourceRect: 指向一个矩形结构,它表示源缓冲区(即后台缓冲区)中的一个矩形范围。如果为NULL的话,则表示整个缓冲区。注意,还记得我们一开始创建D3D设备对象时所指定的“参数”结构体(pPresentationParameters)吗?它里面指定了一个SwapEffect值,只有当这个值是D3DSWAPEFFECT_COPY时,这里的PSourceRect才可以不为NULL(至于为什么,我也不清楚)。所以一般来说,这个值设为NULL即可。

    pDestRect:和pSourceRect一样,只不过这里换成了目标缓冲区(前台缓冲区)中的矩形。

    hDestWindowOverride:指向一个窗口句柄,表示将把前台缓冲区绘制在哪个窗口里。如果设为NULL,则采用“参数”结构体(pPresentationParameters)里hDeviceWindow成员所指定的窗口。一般就是指当前窗口。

    pDirtyRegion:指向一个“脏矩形”的指针。有关“脏矩形”的话题我们以后单独再说。现在设为NULL即可。

    因此这个函数实际写起来会是一个很壮观的样子:g_pd3dDevice->Present( NULL, NULL, NULL, NULL )

    这个函数到这里就写完了。总结一下:当D3D设备对象创建好后,就可以进入帧循环中进行图形的绘制了。在每一次循环中,又包含了三步:清除缓冲区,绘制缓冲区和交换缓冲区。

    Cleanup()函数做了些什么

    当退出程序的时候,要执行Cleanup()函数。

    1 VOID Cleanup()
    2 {
    3     if( g_pd3dDevice != NULL) 
    4         g_pd3dDevice->Release();
    5 
    6     if( g_pD3D != NULL)
    7         g_pD3D->Release();
    8 }
    9 

    这个步骤很简单,首先检测有无D3D设备对象,有的话予以释放;接着检测有无D3D对象,有的话予以释放。

    总结

    总算讲完了。回顾看一下,我们发现搭建一个D3D应用程序框架的步骤其实仅仅几步:创建D3D对象->创建D3D设备对象->进入帧循环(清空缓冲区->绘制缓冲区->交换缓冲区)->释放对象和资源->结束。 但是在每一步进行时,要设置比较多的参数,因此就成了一件比较费力的事情(windows的每一个API无不充满了非常多的参数…汗)。因此倘若打算实用,则用一个框架类来封装这些基本设置是一个不错的主意。框架类是另一个我想记录的主题,以后会单独成章来写,这里就不提了。

  • 相关阅读:
    4.Eclipse下的Hadoop开发实践
    6.命令行编译打包运行五个MapReduce程序
    1.Hadoop初步环境搭建(ssh无密码通信)
    webkit中对incomplete type指针的处理技巧
    Windows平台编译Webkit
    利用Webkit抓取动态网页和链接
    用C#实现网络爬虫(一)
    C#中delegate对象Equals方法简析
    Webkit客户端进程解析
    用C#实现网络爬虫(二)
  • 原文地址:https://www.cnblogs.com/lookof/p/1564285.html
Copyright © 2011-2022 走看看