zoukankan      html  css  js  c++  java
  • 在 Direct3D 中绘制二维图像

    因为二维的游戏已经逐渐减少并且显卡对二维的支持也不再增加新的功能,所以从 DirectX7开始,DirectDraw 被逐渐淡化,代之的是 Direct3D ,但是在3D 中有时也是需要绘制二维的,且不说材质贴图的支持,就是一般的游戏特效(例如在近景是三维的,但是当镜头拉伸到较远的距离时,直接显示二维的地形图)也是需要二维处理的,当然在 Direct3D 中二维的处理方式比较多,最常用的是创建遮盖表面,然后将二维的图作为材质贴在这个表面上,该表面的法线总是指向摄像机并且距离保持恒定,但是这个过程却比较复杂,需要创建场景、摄像机、面片等,本文却介绍一种在 Direct3D 中很简单的二维绘制方法,主要用来进行简单的二维图形处理,首先是声明相关的头文件并连接对应的库:

    #include <d3d9.h>
    #pragma comment( lib, "dxerr.lib" )
    #pragma comment( lib, "dxguid.lib" )
    #pragma comment( lib, "d3d9.lib" )

    CComPtr
    < IDirect3D9 > spDirect3D;
    CComPtr
    < IDirect3DDevice9 > spDirectDevice;

    然后创建 Direct3D 和 Direct3DDevice,参考如下的代码:

        if! spDirect3D )
        {
            spDirect3D 
    = Direct3DCreate9( D3D_SDK_VERSION );
            CHK_EXP_RET( 
    ! spDirect3D , ERROR_SUCCESS );

            D3DPRESENT_PARAMETERS xD3DPP; 
            ZeroMemory( 
    &xD3DPP, sizeof(xD3DPP) );
            xD3DPP.Flags 
    = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER ;
            xD3DPP.SwapEffect 
    = D3DSWAPEFFECT_COPY;
            xD3DPP.Windowed   
    = TRUE;

            DWORD dwFlags 
    = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE ;
            HRESULT hr 
    = spDirect3D->CreateDevice( D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL , m_hWnd , dwFlags , & xD3DPP , & spDirectDevice );
            CHK_EXP_RET( FAILED( hr ) , ERROR_SUCCESS );
        }

    上面的代码中使用了一个简单的宏处理 CHK_EXP_RET ,其定义如下:

    #define CHK_EXP_RET( exp , ret ) if( exp ){ return (ret) ; }
    创建了设备之后,在绘图时就可以使用如下的代码来进行处理了:
        CComPtr< IDirect3DSurface9 > spSurface;
        HRESULT hr 
    = spDirectDevice->GetBackBuffer( 0 , 0 , D3DBACKBUFFER_TYPE_MONO , & spSurface );
        CHK_EXP_RET( FAILED( hr ) , ERROR_SUCCESS );

        HDC hDC;
        hr 
    = spSurface->GetDC( & hDC );

        DrawGraphics( hDC , rcView );

        spSurface
    ->ReleaseDC( hDC );

        hr 
    = spDirectDevice->Present( NULL , NULL , NULL , NULL );
    请注意如果 GetBackBuffer 函数返回错误,那么请检查相关的参数是否指定正确,例如 D3DPRESENT_PARAMETERS 的成员 Flags 是否包含 D3DPRESENTFLAG_LOCKABLE_BACKBUFFER 标志;
    具体的二维图形绘制可以在 DrawGraphics 中随心所遇的绘制,因为有 HDC ,也可以使用 GDI+ 进行处理;当然还是尽可能的使用 DirectX 中的接口以保证效率;另外如果需要直接写屏可以使用 spSurface->LockRect 方法,但是该方法和 GetDC 是互斥使用的,因为这两个方法会都锁定该表面的存储区;
    一般情况下都希望有一个离线的表面来进行绘图,而前面代码中的 spSurface 仅仅是用来进行显示,那么可以使用 IDirect3DDevice::CreateOffscreenPlainSurface 函数来创建一个离线的表面,然后在该表面上进行绘图,然后使用 IDirect3DDevice::UpdateSurface 将该表面更新到显示表面上,这样就可以根据需要创建较多的离线表面,每个离线表面单独绘制,然后合成一个最终的图形;
    最后,需要注意的是,如果是窗口模式的应用,那么在 WM_SIZE 消息中需要对 IDirect3DDevice 设备进行 Reset ,否则绘图表面的大小将永远是创建时的大小,这将导致窗口放缩时,绘制的原始图形大小不变,但是在屏幕上根据窗口的大小进行放缩,其实该函数调用很简单,如下所示:
        CHK_EXP_RET( ! spDirectDevice , 0 );

        D3DPRESENT_PARAMETERS xD3DPP; 
        ZeroMemory( 
    &xD3DPP, sizeof(xD3DPP) );
        xD3DPP.Flags 
    = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER ;
        xD3DPP.SwapEffect 
    = D3DSWAPEFFECT_COPY;
        xD3DPP.Windowed   
    = TRUE;

        spDirectDevice
    ->Reset( & xD3DPP);

        
    return 0;
  • 相关阅读:
    webpack入门
    Javascript隐式转换
    一个最小手势库的实现
    运用JS设置cookie、读取cookie、删除cookie
    不同浏览器下兼容文本两端对齐
    使用CSS3实现一个3D相册
    JavaScript 火的有点过头了,但又能火多久呢?
    强大的css3
    CSS3与页面布局学习总结
    红米手机真机调试问题记录
  • 原文地址:https://www.cnblogs.com/WonKerr/p/Direct3D_Surface_2D.html
Copyright © 2011-2022 走看看