个人对DirectX3D做2D编程的理解

很多年前就知道DirectX是用来做游戏的,从DOS时代直接操作显存,到Windows时代只能通过驱动,并觉得DirectX的API太多,弄不清楚,感觉太麻烦,一直以来想写个游戏都是用GDI,但是GDI的效率很低,游戏做不大,只好硬着头皮去啃DirectX的SDK了,还好现在网络发达,资源很多,总是能学会不是。

在网上看了很多文章,感觉对初学者还是太难,做2D游戏也不需要太多D3D知识,大概整理了一下可能对初学者有些帮忙吧。

以下是以DirectX9的SDK进行描述的,另外渲染跟绘制差不多意思。


1、初始化一个D3D的接口IDirect3D9,方法永远是Direct3DCreate9( D3D_SDK_VERSION );

2、获取设备能力,GetDeviceCaps,Adapter取默认值D3DADAPTER_DEFAULT,DeviceType一般选硬件显卡,即D3DDEVTYPE_HAL

3、获取显示模式描述表 GetAdapterDisplayMode,在这个描述表里可以修改高宽、颜色模式、缓冲区类型等一堆信息

4、创建设备IDirect3DDevice9,用CreateDevice来创建,设备有一个就行了,设备要与窗口句柄关联

5、其它设置,什么世界矩阵,渲染状态

HRESULT InitDirect3D( HWND hWnd, BOOL bWindowed )
{
    g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );

    D3DCAPS9 d3dCaps;
    g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps );

    D3DDISPLAYMODE d3ddm;
    g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );

    if( bWindowed == TRUE )
    {
        d3dpp.Windowed         = TRUE;
        d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat = d3ddm.Format;
    }
    else
    {
        d3dpp.Windowed         = FALSE;
        d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferWidth  = SCREEN_WIDTH;
        d3dpp.BackBufferHeight = SCREEN_HEIGHT;
        d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    }

    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE; // Do NOT sync to vertical retrace
    //d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT; // Sync to vertical retrace
    d3dpp.Flags                  = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

    g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                          &d3dpp, &g_pd3dDevice );

    D3DXMATRIX matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 45.0f ), 
                                SCREEN_WIDTH / SCREEN_HEIGHT, 0.1f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

    g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

    return S_OK;
}


6、创建2D精灵,D3DXCreateSprite,一行就够了,这个精灵创建一个就行,可以加载多个纹理进行批量渲染

7、创建纹理,我们这里说的是加载2D图片,可以从文件加载,从内存加载,也可以创建一个空的,自己填数据

8、渲染,先Device.Clear,再开启设备渲染事务Device.BeginScene,然后可以进行精灵渲染,也可以通过获取设备后备缓冲直接写,最后结束设备渲染事务Device.EndScene

9、精灵渲染有很东西可以设置,很麻烦有兴趣的自己学习,这里只说一个一定要在精灵渲染事务里加允许透明渲染的标志D3DXSPRITE_ALPHABLEND,事务中可以进行多项纹理绘制,所有的绘制都必须在事务中才会生效

10、精灵渲染可以渲染整个纹理,也可以只渲染其中一部分

11、精灵渲染的缩放、旋转、位置的问题,在D3D里使用3D的向量,我们搞2D编程所以Z坐标永远是1.0,缩放可以纹理的表面进行复制自动缩放,有的版本可以直接在Draw方法里旋转和缩放


终于有时间,而且对渲染这一块又有了一些了解

12、渲染到纹理,一个纹理中可以有多个表面,不过通常只用一个,可以将这个表面设为当前渲染的表面,纹理创建时有要求

 a)创建可以用GDI、GDI+作图的纹理,MipLevels=1,Usage=0,Pool=D3DPOOL_MANAGED

 b)创建可以作为渲染目标的纹理,MipLevels=1,Usage=1,Pool=D3DPOOL_DEFAULT,取纹理第0个表面Texture.GetSurfaceLevel(0, surface);然后设置为渲染目标Device.SetRenderTarget(0, surface);,这样一样ID3DXLine、ID3DXFont都可以绘制到当前纹理了(太基础了,没什么人讲,弄了好久才明白),渲染完后应该还原

13、纹理之间可以通过Device.StrechRect、Device.UpdateSurface来进行数据复制(拉伸和原样复制,无法使用Alpha混合的效果)

14、Alpha混合,用于给纹理叠加颜色或叠加透明度,参数很多通过Device.SetRenderState来设置,用好了可以化腐朽为神奇

//设置Alpha混合模式
    Sprite._Begin(D3DXSPRITE_DONOTSAVESTATE);
    Device.SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
    Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR);
    Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
    Device.SetRenderState(D3DRS_BLENDFACTOR,
      D3DCOLOR_ARGB(Round(255.0* Rate),Round(255.0* Rate),Round(255.0* Rate),Round(255.0* Rate)));
//绘制纹理
TDXManager.Sprite.Draw(texture, nil, 0, nil, $FFFFFFFF);

//设置透明度
  Device.SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  Device.SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
  Device.SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_ARGB(255, 255, 255, 255));
//然后绘制纹理。。。
TDXManager.Sprite.Draw(texture, nil, 0, nil, $FFFFFFFF);


有空了我会上个图,最烦写渲染不上图的,没图对比根本看不懂嘛


你可能感兴趣的:(DirectX)