• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            坐標系與基本圖元(5)

            使用索引緩沖區(qū)繪制圖形

            當繪制一個比較復雜的圖形時,需要使用許多相互鄰接的三角形。如果為每個三角形準備三個頂點數據,顯然有許多數據是重復的,這樣會浪費大量的內存和系統(tǒng)帶寬。為了解決這一問題,可以先創(chuàng)建一個頂點緩沖區(qū),將不重復的頂點數據寫入頂點緩沖區(qū),然后創(chuàng)建一個頂點索引緩沖區(qū)(index buffer),存放各個三角形的頂點索引信息,最后通過頂點索引和頂點數據共同完成圖形繪制。

            在Direct3D中一個頂點的索引只需要用一個16位或32位的整數表示,因此當多邊形的頂點有較多重復使用時,使用索引數組通常能夠比直接繪制頂點序列節(jié)省一部分內存空間和系統(tǒng)帶寬。同時,Direct3D渲染流水線避免了對相同頂點進行重復計算,從而可以相應地提高圖形程序的整體性能。

            首先定義頂點結構和靈活頂點格式:

            struct sCustomVertex
            {
            float x, y, z, rhw;
            DWORD color;
            };
            #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) 

            接著創(chuàng)建頂點緩沖區(qū)和索引緩沖區(qū),各頂點位置如下圖所示:

            void init_vertices()
            {
            sCustomVertex vertices[9];
            	vertices[0].x	  = 300.0f;
            vertices[0].y = 250.0f;
            vertices[0].z = 0.5f;
            vertices[0].rhw = 1.0f;
            vertices[0].color = 0xffff0000;
            	for(int i = 0; i < 8; i++)
            {
            vertices[i+1].x = (200 * sin(i * 3.14159f / 4.0f)) + 300;
            vertices[i+1].y = -(200 * cos(i * 3.14159f / 4.0f)) + 250;
            vertices[i+1].z = 0.5f;
            vertices[i+1].rhw = 1.0f;
            vertices[i+1].color = 0xff00ff00;
            }
            	WORD indices[] = { 0,1,2, 0,2,3, 0,3,4, 0,4,5, 0,5,6, 0,6,7, 0,7,8, 0,8,1 };
            	// push vertex data into vertex buffer
            	g_device->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &g_vertex_buffer, NULL);
            	void* ptr;
            	g_vertex_buffer->Lock(0, sizeof(vertices), (void**)&ptr, 0);
            memcpy(ptr, vertices, sizeof(vertices));
            g_vertex_buffer->Unlock();
            	// push vertex index into index buffer
            	g_device->CreateIndexBuffer(sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_index_buffer, NULL);
            	void* index_ptr;
            	g_index_buffer->Lock(0, sizeof(indices), (void**)&index_ptr, 0);
            memcpy(index_ptr, indices, sizeof(indices));
            g_index_buffer->Unlock();
            }

            在上面的代碼段中,使用IDirect3DDevice9::CreateIndexBuffer()函數創(chuàng)建所需要的索引緩沖區(qū),該函數的聲明如下:

            Creates an index buffer.

            HRESULT CreateIndexBuffer(
            UINT Length,
            DWORD Usage,
            D3DFORMAT Format,
            D3DPOOL Pool,
            IDirect3DIndexBuffer9** ppIndexBuffer,
            HANDLE* pSharedHandle
            );

            Parameters

            Length
            [in] Size of the index buffer, in bytes.
            Usage
            [in] Usage can be 0, which indicates no usage value. However, if usage is desired, use a combination of one or more D3DUSAGE constants. It is good practice to match the usage parameter in CreateIndexBuffer with the behavior flags in IDirect3D9::CreateDevice. For more information, see Remarks.
            Format
            [in] Member of the D3DFORMAT enumerated type, describing the format of the index buffer. For more information, see Remarks. The valid settings are the following:
            D3DFMT_INDEX16
            Indices are 16 bits each.
            D3DFMT_INDEX32
            Indices are 32 bits each.
            Pool
            [in] Member of the D3DPOOL enumerated type, describing a valid memory class into which to place the resource.
            ppIndexBuffer
            [out, retval] Address of a pointer to an IDirect3DIndexBuffer9 interface, representing the created index buffer resource.
            pSharedHandle
            [in] Reserved. Set this parameter to NULL.

            Return Values

            If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be one of the following: D3DERR_INVALIDCALL, D3DERR_OUTOFVIDEOMEMORY, D3DXERR_INVALIDDATA, E_OUTOFMEMORY.

            Remarks

            Index buffers are memory resources used to hold indices, they are similar to both surfaces and vertex buffers. The use of index buffers enables Direct3D to avoid unnecessary data copying and to place the buffer in the optimal memory type for the expected usage.

            To use index buffers, create an index buffer, lock it, fill it with indices, unlock it, pass it to IDirect3DDevice9::SetIndices, set up the vertices, set up the vertex shader, and call IDirect3DDevice9::DrawIndexedPrimitive for rendering.

            The MaxVertexIndex member of the D3DCAPS9 structure indicates the types of index buffers that are valid for rendering.

            接著使用索引緩沖區(qū)繪制圖形:

            void render()
            {
            g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_X#050505, 1.0f, 0);
            	g_device->BeginScene();
            	g_device->SetRenderState(D3DRS_FILLMODE, g_fill_mode);
            g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
            g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);
            g_device->SetIndices(g_index_buffer);
            g_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 9, 0, 8);
            	g_device->EndScene();
            	g_device->Present(NULL, NULL, NULL, NULL);
            }

            函數IDirect3DDevice9::DrawIndexedPrimitive()使用當前設置的索引緩沖區(qū)繪制圖形:

            Based on indexing, renders the specified geometric primitive into an array of vertices.

            HRESULT DrawIndexedPrimitive(
            D3DPRIMITIVETYPE Type,
            INT BaseVertexIndex,
            UINT MinIndex,
            UINT NumVertices,
            UINT StartIndex,
            UINT PrimitiveCount
            );

            Parameters

            Type
            [in] Member of the D3DPRIMITIVETYPE enumerated type, describing the type of primitive to render. D3DPT_POINTLIST is not supported with this method. See Remarks.
            BaseVertexIndex
            [in] Offset from the start of the vertex buffer to the first vertex. See Scenario 4.
            MinIndex
            [in] Minimum vertex index for vertices used during this call. This is a zero based index relative to BaseVertexIndex.
            NumVertices
            [in] Number of vertices used during this call. The first vertex is located at index: BaseVertexIndex + MinIndex.
            StartIndex
            [in] Index of the first index to use when accesssing the vertex buffer. Beginning at StartIndex to index vertices from the vertex buffer.
            PrimitiveCount
            [in] Number of primitives to render. The number of vertices used is a function of the primitive count and the primitive type. The maximum number of primitives allowed is determined by checking the MaxPrimitiveCount member of the D3DCAPS9 structure.

            Return Values

            If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be the following: D3DERR_INVALIDCALL.

            Remarks

            This method draws indexed primitives from the current set of data input streams. MinIndex and all the indices in the index stream are relative to the BaseVertexIndex.

            The MinIndex and NumVertices parameters specify the range of vertex indices used for each IDirect3DDevice9::DrawIndexedPrimitive call. These are used to optimize vertex processing of indexed primitives by processing a sequential range of vertices prior to indexing into these vertices. It is invalid for any indices used during this call to reference any vertices outside of this range.

            IDirect3DDevice9::DrawIndexedPrimitive fails if no index array is set.

            The D3DPT_POINTLIST member of the D3DPRIMITIVETYPE enumerated type is not supported and is not a valid type for this method.

            When converting a legacy application to Direct3D 9, you must add a call to either IDirect3DDevice9::SetFVF to use the fixed function pipeline, or IDirect3DDevice9::SetVertexDeclaration to use a vertex shader before you make any Draw calls.

             

            完整源碼如下:

            #include <d3d9.h>
            #include 
            <math.h>

            #define CLASS_NAME    "GameApp"

            #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;
            IDirect3DVertexBuffer9
            * g_vertex_buffer;
            IDirect3DIndexBuffer9
            *    g_index_buffer;

            DWORD                    g_fill_mode 
            = D3DFILL_SOLID;

            struct sCustomVertex
            {
                
            float x, y, z, rhw;
                DWORD color;
            };

            #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) 

            void init_vertices()
            {
                sCustomVertex vertices[
            9];
                
                vertices[
            0].x      = 300.0f;
                vertices[
            0].y      = 250.0f;
                vertices[
            0].z      = 0.5f;
                vertices[
            0].rhw      = 1.0f;
                vertices[
            0].color = 0xffff0000;

                
            for(int i = 0; i < 8; i++)
                {
                    vertices[i
            +1].x        =  (200 * sin(i * 3.14159f / 4.0f)) + 300;
                    vertices[i
            +1].y        = -(200 * cos(i * 3.14159f / 4.0f)) + 250;
                    vertices[i
            +1].z        = 0.5f;
                    vertices[i
            +1].rhw    = 1.0f;
                    vertices[i
            +1].color = 0xff00ff00;
                }

                WORD indices[] 
            = { 0,1,20,2,30,3,40,4,50,5,60,6,70,7,80,8,1 };

                
            // push vertex data into vertex buffer

                g_device
            ->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &g_vertex_buffer, NULL);

                
            void* ptr;

                g_vertex_buffer
            ->Lock(0sizeof(vertices), (void**)&ptr, 0);
                memcpy(ptr, vertices, 
            sizeof(vertices));
                g_vertex_buffer
            ->Unlock();

                
            // push vertex index into index buffer

                g_device
            ->CreateIndexBuffer(sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_index_buffer, NULL);

                
            void* index_ptr;
                
                g_index_buffer
            ->Lock(0sizeof(indices), (void**)&index_ptr, 0);
                memcpy(index_ptr, indices, 
            sizeof(indices));
                g_index_buffer
            ->Unlock();
            }

            bool init_d3d(HWND hwnd)
            {
                g_d3d 
            = Direct3DCreate9(D3D_SDK_VERSION);

                
            if(g_d3d == NULL)
                    
            return false;

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

                d3dpp.Windowed            
            = TRUE;
                d3dpp.SwapEffect        
            = D3DSWAPEFFECT_DISCARD;
                d3dpp.BackBufferFormat    
            = D3DFMT_UNKNOWN;

                
            if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                              
            &d3dpp, &g_device)))
                {
                    
            return false;
                }

                init_vertices();
                
                g_device
            ->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

                
            return true;
            }

            void cleanup()
            {
                release_com(g_index_buffer);
                release_com(g_vertex_buffer);
                release_com(g_device);
                release_com(g_d3d);
            }

            void render()
            {
                g_device
            ->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(555), 1.0f0);

                g_device
            ->BeginScene();

                g_device
            ->SetRenderState(D3DRS_FILLMODE, g_fill_mode);
                g_device
            ->SetStreamSource(0, g_vertex_buffer, 0sizeof(sCustomVertex));
                g_device
            ->SetFVF(D3DFVF_CUSTOM_VERTEX);
                g_device
            ->SetIndices(g_index_buffer);
                g_device
            ->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 00908);       

                g_device
            ->EndScene();

                g_device
            ->Present(NULL, NULL, NULL, NULL);
            }

            LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                
            switch(msg)
                {
                
            case WM_KEYDOWN:
                    
            switch(wParam)
                    {    
                    
            case VK_SPACE:
                        g_fill_mode 
            = (g_fill_mode == D3DFILL_WIREFRAME) ? D3DFILL_SOLID : D3DFILL_WIREFRAME;
                        
            break;
                    
            case VK_ESCAPE:
                        DestroyWindow(hwnd);
                        
            break;
                    }    
                    
            break;

                
            case WM_DESTROY:        
                    PostQuitMessage(
            0);
                    
            return 0;
                }

                
            return DefWindowProc(hwnd, msg, wParam, lParam);
            }

            int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
            {
                WNDCLASSEX wc;

                wc.cbSize            
            = sizeof(WNDCLASSEX);
                wc.style            
            = CS_CLASSDC;
                wc.lpfnWndProc        
            = WinProc;
                wc.cbClsExtra        
            = 0;
                wc.cbWndExtra        
            = 0;
                wc.hInstance        
            = inst;
                wc.hIcon            
            = NULL;
                wc.hCursor            
            = NULL;
                wc.hbrBackground    
            = NULL;
                wc.lpszMenuName        
            = NULL;
                wc.lpszClassName    
            = CLASS_NAME;
                wc.hIconSm            
            = NULL;

                
            if(! RegisterClassEx(&wc))
                    
            return -1;

                HWND hwnd 
            = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200100600500,
                                         NULL, NULL, wc.hInstance, NULL);

                
            if(hwnd == NULL)
                    
            return -1;

                
            if(init_d3d(hwnd))
                {
                    ShowWindow(hwnd, SW_SHOWDEFAULT);
                    UpdateWindow(hwnd);

                    MSG msg;
                    ZeroMemory(
            &msg, sizeof(msg));

                    
            while(msg.message != WM_QUIT)
                    {
                        
            if(PeekMessage(&msg, NULL, 00, PM_REMOVE))
                        {
                            TranslateMessage(
            &msg);
                            DispatchMessage(
            &msg);
                        }
                            
                        render();
                    }
                }

                cleanup();

                UnregisterClass(CLASS_NAME, wc.hInstance);    

                
            return 0;
            }


            運行截圖:

            實體模式

            線框模式

            也可以只使用頂點緩沖區(qū)通過三角扇形圖元來繪制,改動init_vertices()和render()即可,需要增加一個頂點使多邊形封閉(即,使v9==v1)。

            void init_vertices()
            {
            sCustomVertex vertices[10];
            	vertices[0].x	  = 300.0f;
            vertices[0].y = 250.0f;
            vertices[0].z = 0.5f;
            vertices[0].rhw = 1.0f;
            vertices[0].color = 0xffff0000;
            	for(int i = 0; i < 9; i++)
            {
            vertices[i+1].x = (200 * sin(i * 3.14159f / 4.0f)) + 300;
            vertices[i+1].y = -(200 * cos(i * 3.14159f / 4.0f)) + 250;
            vertices[i+1].z = 0.5f;
            vertices[i+1].rhw = 1.0f;
            vertices[i+1].color = 0xff00ff00;
            }
            	// push vertex data into vertex buffer
            	g_device->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &g_vertex_buffer, NULL);
            	void* ptr;
            	g_vertex_buffer->Lock(0, sizeof(vertices), (void**)&ptr, 0);
            memcpy(ptr, vertices, sizeof(vertices));
            g_vertex_buffer->Unlock();
            }
            void render()
            {
            g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_X#050505, 1.0f, 0);
            	g_device->BeginScene();
            	g_device->SetRenderState(D3DRS_FILLMODE, g_fill_mode);
            g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
            g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);
            	g_device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 8);	
            	g_device->EndScene();
            	g_device->Present(NULL, NULL, NULL, NULL);
            }

            posted on 2008-04-30 17:39 lovedday 閱讀(1613) 評論(0)  編輯 收藏 引用

            公告

            導航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            伊人色综合九久久天天蜜桃| 久久国产乱子伦精品免费强| 久久夜色精品国产www| 精品久久久久久国产三级| 亚洲国产天堂久久久久久| 成人久久免费网站| 99久久99久久精品国产片果冻| 久久夜色精品国产www| 激情伊人五月天久久综合| 久久中文精品无码中文字幕| 无码AV波多野结衣久久| 国产精品99久久久久久宅男 | 久久噜噜久久久精品66| 天天爽天天狠久久久综合麻豆| 久久se精品一区二区| 国产激情久久久久久熟女老人| 久久99精品国产麻豆宅宅| 狠狠综合久久AV一区二区三区| 国产成人无码精品久久久久免费| 精品国产乱码久久久久久呢| 国产精品亚洲美女久久久| 国产精品青草久久久久婷婷| 国产成人精品综合久久久| 久久精品国产福利国产琪琪| 国产精品福利一区二区久久| 亚洲欧美日韩久久精品第一区| 久久精品国产WWW456C0M| 成人a毛片久久免费播放| 久久精品一区二区三区不卡| 久久久久久久久久久久中文字幕| 中文精品久久久久人妻| 麻豆久久久9性大片| 开心久久婷婷综合中文字幕| 久久99精品免费一区二区| 国产69精品久久久久99| 国产精自产拍久久久久久蜜| 久久超碰97人人做人人爱| 久久精品人成免费| 久久国产精品久久久| 国产日韩久久久精品影院首页| 日韩一区二区久久久久久|