DirectX图形处理(4)

初始化系统对象
   在创建了应用程序窗口之后,即可以开始初始化主DirectX对象。主DirectX对象提供的服务可用于在场景上进行绘制6杂谝桓?/SPAN>Direct3D应用程序,初始化过程就是创建和配置DirectDraw、绘制表面、一个绘制设备和一个视口的过程。为了清楚起见,Triangle例子程序将系统对象初始化代码从初始化场景的代码中分离出来。结果几何图形、特定于应用程序的数据结构和像材料这样次要的Direct3D对象与场景一起初始化,其实并不要求这样做,但这样会使代码更简单。

   Triangle例子程序在应用程序定义的Initialize3DEnvironment函数中执行系统初始化,在创建窗口之后从WinMain中调用。Initialize3DEnvironment函数所采用的步骤显示在下列子步骤中。

   注意: Triangle例子程序代码通过在WinMain函数中调用初始化方法来执行初始化过程,而且是在创建应用程序窗口之后立即进行的,并不是在响应诸如WM_CREATE等系统创建消息时进行的。这样就避免了对系统消息顺序的依赖,因为顺序在不同的平台上可能不一样。

(1)初始化DirectDraw

   在创建了应用程序窗口之后,需要创建的第一个对象是DirectDraw对象,在设置应用程序的协同等级、创建显示表面和用做绘制设备的绘制目标时需要该对象。

   Triangle例子程序通过创建一个DirectDraw对象并设置应用程序的协同等级来开始执行初始化,如下列代码所示:

HRESULT Initialize3DEnvironment( HWND hWnd )

{

    HRESULT hr;

 

    hr = DirectDrawCreateEx( NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL );

    if( FAILED( hr ) )

        return hr;

   上面的代码通过调用DirectDraw的全局函数DirectDrawCreateEx创建了一个DirectDraw对象。通过在第一个参数中传递NULL来请求函数为活动显示驱动程序创建一个DirectDraw对象。对于不支持GDI的硬件,例如仅有3-D功能的硬件,应当在第一个参数中显式指定所需要的驱动程序的全局惟一标识符(GUID)。这些GUID一般通过列举来获取。第二个参数是一个由DirectDrawCreateEx用DirectDraw对象的IDirectDraw7接口的地址来填充的全局变量的地址。将最后一个参数设置为NULL,表明新对象不能用于COM聚合特色。

   例子程序接下来设置应用程序的协同等级,如下所示:

    hr = g_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL );

    if( FAILED( hr ) )

        return hr;

   例子程序通过调用IDirectDraw7::SetCooperativeLevel方法来设置协同等级。设置协同等级可有效地通知系统应用程序是在全屏模式下还是在窗口中进行绘制。

   注意:一些硬件不能在窗口中进行绘制。在调用IDirectDraw7::GetCaps时检查是否缺乏DDCAPS2_CANRENDERWINDOWED能力标志可以检查这样的硬件。

   代码通过在传递给SetCooperativeLevel的第二个参数中包括DDSCL_NORMAL来请求窗口化协作等级,也叫做“正常”协作等级。如果另一个应用程序已经控制了自身的全屏独占模式,则SetCooperativeLevel方法可能失败。

   注意:DDSCL_FPUSETUP协作等级标志可以提高性能。

(2)设置DirectDraw表面

   在创建了DirectDraw对象并设置了协同等级之后,就可以创建应用程序用来绘制和显示场景的表面了。具体怎样创建表面,在很大程度上取决于应用程序是在窗口中运行还是在全屏模式下运行。

   注意:在全屏模式下运行的应用程序可以按照前面的代码示例中的方法来创建表面。一般情况下,应用程序应当利用页面翻转,这是一种在全屏独占模式下才能使用的特色。在这种情况下,代替显式创建两个表面,可以在一次调用中创建一个表面翻转链。

   Triangle例子程序运行于窗口之中,通过创建一个主表面开始,该主表面代表了显示,如下所示:

    DDSURFACEDESC2 ddsd;

    ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );

    ddsd.dwSize = sizeof(DDSURFACEDESC2);

    ddsd.dwFlags = DDSD_CAPS;

    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

 

    // 创建主表面

    hr = g_pDD->CreateSurface( &ddsd, &g_pddsPrimary, NULL );

    if( FAILED( hr ) )

        return hr;

   主表面的描述不包括尺寸或像素格式信息,因为已假定这些特性与显示模式相同。如果当前显示模式是800×600,16位彩色,则DirectDraw保证主表面与之相匹配。在创建了主表面之后,就可以创建绘制目标表面。在Triangle的情况下,绘制目标表面是一个分离的离屏表面,其创建过程如下所示:

    ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;

    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;

 

    // 设置后台缓冲区的尺寸。如果窗口改变尺寸,需要销毁该表面并创建一个新

    // 表面

    GetClientRect( hWnd, &g_rcScreenRect );

    GetClientRect( hWnd, &g_rcViewportRect );

    ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.left );

    ClientToScreen( hWnd, (POINT*)&g_rcScreenRect.right );

    ddsd.dwWidth  = g_rcScreenRect.right - g_rcScreenRect.left;

    ddsd.dwHeight = g_rcScreenRect.bottom - g_rcScreenRect.top;

 

    // 创建后台缓冲区。最可能的失败原因是用尽了视频内存(更复杂的应用程序应

    // 当处理这种情况)

    hr = g_pDD->CreateSurface( &ddsd, &g_pddsBackBuffer, NULL );

    if( FAILED( hr ) )

        return hr;

   上面的代码创建了一个与程序窗口尺寸相同的离屏表面。不需要创建一个更大的表面,因为窗口的尺寸规定了什么地方对用户是可见的(代码也初始化了两个后面用于设置视口和跟踪应用程序窗口尺寸和位置的全局变量)。正如上面的代码片段所示,必须为每一个将用做绘制目标的表面包括DDSCAPS_3DDEVICE能力。这个能力导致系统分配附加的仅用于3-D绘制的内部数据结构。在创建主表面时,当没有在表面描述中提供离屏表面的像素格式时假定离屏表面的像素格式与显示模式的像素格式一样。

   注意:要使用深度缓冲区的应用程序应当创建一个深度缓冲区并马上将其联系到绘制目标表面。为了简单起见,本示例没有使用深度缓冲区。

   在创建了主表面和绘制目标表面后,可以创建并联系一个DirectDrawClipper对象到显示表面。使用剪裁器可以避免在窗口的局部被其他窗口所覆盖或窗口的一部分位于显示区域之外时需要进行的处理。运行在全屏模式下的应用程序不需要剪裁器。Triangle例子程序用下列代码来创建一个剪裁器,并将其与显示窗口相联系:

    LPDIRECTDRAWCLIPPER pcClipper;

    hr = g_pDD->CreateClipper( 0, &pcClipper, NULL );

    if( FAILED( hr ) )

        return hr;

 

    // 将其指派给窗口句柄,然后将剪裁器设置到需要的表面

    pcClipper->SetHWnd( 0, hWnd );

    g_pddsPrimary->SetClipper( pcClipper );

    pcClipper->Release();

(3)初始化Direct3D

   在创建了表面之后,应用程序必须绘制并显示场景。通过为DirectDraw对象获取一个指向IDirect3D7接口的指针,可以开始初始化Direct3D对象。该指针用于创建绘制场景所需要的所有对象。该接口是由DirectDraw对象暴露的,代表一个分离的特色集合,而不是分离的对象。通过调用DirectDraw 对象的IUnknown::QueryInterface方法来获取IDirect3D7接口。下列来自Triangle的代码用于执行这一任务:

    // 查询DirectDraw以便访问Direct3D

    g_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&g_pD3D );

    if( FAILED( hr) )

        return hr;
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值