Direct3D中,DrawIndexedPrimitive的使用方法

来源:互联网 发布:淘宝天猫怎么申请 编辑:程序博客网 时间:2024/05/17 23:47

一、IDirect3DDevice9::DrawIndexedPrimitive

 
           DrawIndexedPrimitive声明如下:
       
   HRESULT   IDirect3DDevice9::DrawPrimitive(
          D3DPRIMITIVETYPE  PrimitiveType,
          INT               BaseVertexIndex,
          UINT            MinIndex,
          UINT            NumVertices,
          UINT            StartIndex,
          UINT            PrimitiveCount
          );

        ●  PrimitiveType  所要绘制的图元类型。
        ●  BaseVertexIndex  为索引增加的一个基数。
        ●  MinIndex   允许引用的最小索引值。
        ●  NumVertices  本次调用中将引用的顶点总数。
        ●  StartIndex      顶点缓存中标识索引的读取起始点的元素的索引。
        ●  PrimitiveCount  所要绘制的图元总数。

        下面分析参数BaseVertexIndex的使用方法:

         局部索引缓存的内容应与局部顶点缓存中的顶点一致。假定我们想将球、盒以及圆柱体的顶点合并到同一个全局缓存中。对于每个物体,我们必须重新计算索引,以保证这些索引正确地指向全局顶点缓存中对应的顶点。如下图所示:

         


       新索引的计算方法是为每个索引增加一个指定了物体顶点在全局缓存中存储的其实位置的偏移量,该偏移量用顶点个数来度量而非字节。我们无需手工计算物体相对于全局缓存的索引位置,因为Direct3D允许我们通过给参数BaseVertexIndex传递一个顶点偏移值,然后由Direct3D在内部重新对索引进行计算。

        例如:
        假定我们将要绘制一个矩形和一个三角形,把两者的顶点存储到同一个顶点缓存中:

CUSTOMVERTEX vertices[7] = { 
//前四个为矩形的顶点坐标,后三个为三角形的顶点坐标
-15, -5, 0, D3DCOLOR_XRGB(255, 0, 0),
         -15,  5, 0, D3DCOLOR_XRGB(0, 255, 0),
          -5,  5, 0, D3DCOLOR_XRGB(0, 0, 255),
          -5,  -5, 0, D3DCOLOR_XRGB(255, 255, 0),

                   5, -5, 0, D3DCOLOR_XRGB(0, 255, 0),
          15,  -5, 0, D3DCOLOR_XRGB(0, 255, 255),
          10,  5, 0, D3DCOLOR_XRGB(255, 0, 255),
    };

        pIB_Rectangle为矩形的索引缓存,pIB_Triangle为三角形的索引缓存,则绘制时应以如下方式调用:

//绘制矩形,设置为矩形的索引缓存
g_pd3dDevice->SetIndices(pIB_Rectangle);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2 );

//绘制三角形,设置为三角形的索引缓存
g_pd3dDevice->SetIndices(pIB_Triangle);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,4,0,3,0,1 );

        在绘制三角形时,DrawIndexedPrimitive的第二个参数设置为4,表示三角形的顶点在全局顶点缓存中的起始位置为4(从0开始计数)。

二、示例代码


        下面的代码将矩形和三角形的顶点存储在同一个顶点缓存中。

#include <d3d9.h>#pragma warning( disable : 4996 ) // disable deprecated warning #include <strsafe.h>#pragma warning( default : 4996 )#include <d3dx9math.h>LPDIRECT3D9             g_pD3D = NULL; LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; LPDIRECT3DINDEXBUFFER9   pIB_Rectangle = NULL;LPDIRECT3DINDEXBUFFER9   pIB_Triangle = NULL;struct CUSTOMVERTEX{    FLOAT x, y, z;     DWORD color; };#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)HRESULT InitD3D( HWND hWnd ){    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )        return E_FAIL;    D3DPRESENT_PARAMETERS d3dpp;    ZeroMemory( &d3dpp, sizeof( d3dpp ) );    d3dpp.Windowed = TRUE;    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,                                      &d3dpp, &g_pd3dDevice ) ) )    {        return E_FAIL;    }    return S_OK;}HRESULT InitVB(){ CUSTOMVERTEX vertices[7] = {         //前四个为矩形的顶点坐标,后三个为三角形的顶点坐标     -15, -5, 0, D3DCOLOR_XRGB(255, 0, 0),     -15,  5, 0, D3DCOLOR_XRGB(0, 255, 0),      -5,  5, 0, D3DCOLOR_XRGB(0, 0, 255),      -5, -5, 0, D3DCOLOR_XRGB(255, 255, 0),               5, -5, 0, D3DCOLOR_XRGB(0, 255, 0),      15, -5, 0, D3DCOLOR_XRGB(0, 255, 255),      10,  5, 0, D3DCOLOR_XRGB(255, 0, 255), };    if( FAILED( g_pd3dDevice->CreateVertexBuffer( sizeof( vertices ),                                                  0, D3DFVF_CUSTOMVERTEX,                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )    {        return E_FAIL;    }VOID* pVertices;    if( FAILED( g_pVB->Lock( 0, sizeof( vertices ), ( void** )&pVertices, 0 ) ) )        return E_FAIL;    memcpy( pVertices, vertices, sizeof( vertices ) );    g_pVB->Unlock();//设置矩形的索引缓存if( FAILED( g_pd3dDevice->CreateIndexBuffer( 6 * sizeof( WORD ),                                                  0, D3DFMT_INDEX16,                                                  D3DPOOL_DEFAULT, &pIB_Rectangle, NULL ) ) ){return E_FAIL;}WORD* pIndices = NULL;pIB_Rectangle->Lock(0, 0, (void**)&pIndices,0);pIndices[0] = 0, pIndices[1] = 3, pIndices[2] = 1, pIndices[3] = 1, pIndices[4] = 3, pIndices[5] = 2;pIB_Rectangle->Unlock();//设置三角形的索引缓存   if( FAILED( g_pd3dDevice->CreateIndexBuffer(3 * sizeof( WORD ),                                                  0, D3DFMT_INDEX16,                                                  D3DPOOL_DEFAULT, &pIB_Triangle, NULL ) ) ){return E_FAIL;}WORD* Indices = NULL;pIB_Triangle->Lock(0, 0, (void**)&Indices,0);Indices[0] = 0, Indices[1] = 1, Indices[2] = 2;pIB_Triangle->Unlock();       return S_OK;}VOID Cleanup(){    if( g_pVB != NULL )        g_pVB->Release();    if( pIB_Rectangle != NULL )        pIB_Rectangle->Release();    if( g_pd3dDevice != NULL )        g_pd3dDevice->Release();    if( g_pD3D != NULL )        g_pD3D->Release();    if(pIB_Triangle !=NULL)pIB_Triangle->Release();}VOID SetupMatrices(){D3DXVECTOR3 vEyePt(0.0f, 0.0f, -20);D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);D3DXMATRIXA16 matView;D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);//D3DXMatrixPerspectiveFovLH()函数中的最远、最近距离为相对于视点的距离(即vEyePt中的距离)D3DXMATRIXA16 matProj;D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 2, 1.0f, 1.0f, 200.0f);g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);}VOID Render(){    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 255, 255 ), 1.0f, 0 );    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )    { SetupMatrices();                g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );                g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);//绘制矩形,设置为矩形的索引缓存g_pd3dDevice->SetIndices(pIB_Rectangle);g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2 );//绘制三角形,设置为三角形的索引缓存g_pd3dDevice->SetIndices(pIB_Triangle);g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,4,0,3,0,1 );                g_pd3dDevice->EndScene();    }    // Present the backbuffer contents to the display    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );}LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){    switch( msg )    {        case WM_DESTROY:            Cleanup();            PostQuitMessage( 0 );            return 0;    }    return DefWindowProc( hWnd, msg, wParam, lParam );}INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT ){    // Register the window class    WNDCLASSEX wc =    {        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,        "D3D Tutorial", NULL    };    RegisterClassEx( &wc );    // Create the application's window    HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial: DrawIndexedPrimitive",                              WS_OVERLAPPEDWINDOW, 100, 100, 400, 400,                              NULL, NULL, wc.hInstance, NULL );    if( SUCCEEDED( InitD3D( hWnd ) ) )    {        // Create the vertex buffer and index buffer        if( SUCCEEDED( InitVB() ) )        {            // Show the window            ShowWindow( hWnd, SW_SHOWDEFAULT );            UpdateWindow( hWnd );            // Enter the message loop            MSG msg;            ZeroMemory( &msg, sizeof( msg ) );            while( msg.message != WM_QUIT )            {                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )                {                    TranslateMessage( &msg );                    DispatchMessage( &msg );                }                else                    Render();            }        }    }    UnregisterClass( "D3D Tutorial", wc.hInstance );    return 0;}

 
运行效果如下: