• <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>

            無我

            讓內(nèi)心永遠燃燒著偉大的光明的精神之火!
            靈活的思考,嚴謹?shù)膶崿F(xiàn)
            豪邁的氣魄、頑強的意志和周全的思考

            DirectDraw編程方法與技巧


             
             DirectDraw編程方法與技巧
            添加時間:2006-10-18   出處:www.3DGameDev.org  作者:songtao
             
             
            1 概 述

              DirectX是Microsoft為軟件開發(fā)人員提供的一套精心設(shè)計的接口,用于開發(fā)高性能、實時的應(yīng)用程序。它以COM(component object modal)為基本結(jié)構(gòu)[1],位于硬件和軟件之間,像gdi(graphics device interface)一樣提供了硬件無關(guān)的API(application programming interface)接口;它和GDI有一重要不同點:DirectX是一套底層的API接口,它提供了直接訪問硬件的能力,使得DirectX應(yīng)用程序能充分發(fā)揮硬件的威力。
              DirectDraw是DirectX中提供直接操縱顯存、執(zhí)行硬件映射、硬件覆蓋及切換顯示頁等功能的組件。它不但兼容已有的Windows應(yīng)用程序和驅(qū)動程序,而且還兼容許多顯示卡:從簡單的SVGA到支持圖像剪裁、拉伸和非RGB格式圖像的高檔顯示卡。DirectDrawHAL(hardware-abstraction layer)抽象了顯示卡的硬件功能,以設(shè)備無關(guān)的方式提供了一些以前是設(shè)備相關(guān)的功能,如多顯示頁技術(shù)、訪問并控制顯示卡映射寄存器、支持3DZ-Buffer、支持Z-order硬件覆蓋、訪問圖像拉伸硬件,以及同時訪問標準顯存和控制顯存。正因為DirectDraw有這些優(yōu)點,現(xiàn)在許多基于Windows95/98/NT的游戲程序都使用了DirectDraw;而它的設(shè)備無關(guān)性使開發(fā)者擺脫了繁重的顯示卡接口工作,集中精力實現(xiàn)程序的主要功能。DirectX中的DDraw.dll實現(xiàn)了DirectDraw所需要的函數(shù)、對象及其接口。下面先介紹DirectDraw中主要的函數(shù)、對象和接口,然后再說明DirectDraw的使用方法。

            2 DirectDraw中的函數(shù)、對象和接口簡介

              DirectDraw包括一個代表顯示卡的主對象DirectDraw,由函數(shù)DirectDrawCreate創(chuàng)建,實現(xiàn)接口IDirectDraw和IDirectDraw2。如果機器上裝有多個顯示卡,可以為每個顯示卡創(chuàng)建一個DirectDraw對象。也可以創(chuàng)建多個DirectDraw對象,它們各自獨立并代表同一物理對象。IDirectDraw是為了和以前版本DirectX兼容而保留的接口,基于DirectX3以上版本的程序應(yīng)該使用IDirectDraw2。IDirectDraw2和IDirectDraw接口所包含的方法定義基本相同,但具體實現(xiàn)不同。DirectDraw對象主要用于創(chuàng)建其它3個對象:DirectDrawSurface、DirectDrawPalette、DirectDrawClipper。
              DirectDrawSurface對象由函數(shù)IDirectDraw2::CreateSurface創(chuàng)建,代表顯存中一塊線性區(qū)域,實現(xiàn)接口IDirectDrawSurface和IDirectDrawSurface2。IDirectDrawSurface是為了和以前版本DirectX兼容而保留的接口,基于DirectX3以上版本的程序應(yīng)該使用IDirectDrawSurface2。二者的接口定義也基本相同。可以為一個DirectDraw對象創(chuàng)建多個IDirectDrawSurface對象,代表物理屏幕或邏輯屏幕,通過IDirectDrawSurface2::Flip、IDirectDrawSurface2::BltFast等方法切換顯示頁或映射部分屏幕內(nèi)容。
              DirectDrawPalette對象由函數(shù)IDirectDraw2::CreatePalette創(chuàng)建,實現(xiàn)接口IDirectDrawPalette。它代表顯示卡的物理調(diào)色板,可以是16色或256色。每個DirectDrawPalette必須附著(attach)在一個DirectDrawSurface上,不同的DirectDrawSurface對象可以有不同的DirectDrawPalette。
              DirectDrawClipper對象由函數(shù)IDirectDraw2::CreateClipper或DirectDrawCreateClipp
            er創(chuàng)建,實現(xiàn)接口IDirectDrawClipper。DirectDraw用它來處理屏幕的剪貼。它常用于在Window模式(與全屏模式相對應(yīng))下運行的DirectDraw程序,在使用前也必須被附著在一個DirectDrawSurface上。

            3 DirectDraw程序一般工作過程

              和一般的Windows程序[2]一樣,DirectDraw程序要先創(chuàng)建一個主窗口,然后進行DirectDraw的初始化:創(chuàng)建所需要的對象,設(shè)置程序的工作模式,建立必要的數(shù)據(jù)結(jié)構(gòu)。在初始化工作完成后,就可以在主窗口的消息循環(huán)中根據(jù)用戶的輸入調(diào)用相應(yīng)對象的方法。

            3.1 初始化DirectDraw
            3.1.1 創(chuàng)建DirectDraw對象
              首先調(diào)用DirectDrawCreate創(chuàng)建代表某個顯示卡的DirectDraw對象:
              ddres=DirectDrawCreate(NULL,&lpDD,NULL);
              DirectDrawCreate的第一項參數(shù)是代表顯示卡驅(qū)動程序的GUID(globally unique identifier),若為NULL則表示采用系統(tǒng)默認的驅(qū)動程序。第二項參數(shù)是IDirectDraw接口類型指針的地址,用于接收指向由DirectDrawCreate所創(chuàng)建對象的指針。這個指針不需應(yīng)用程序預先分配內(nèi)存。DirectDrawCreate成功時會調(diào)用AddRef將對象的引用計數(shù)加1。如果要知道系統(tǒng)中所有驅(qū)動程序的GUID,可以調(diào)用DirectDrawEnumerate,它接收兩個參數(shù):回調(diào)函數(shù)的地址和傳給回調(diào)函數(shù)的自定義數(shù)據(jù)的地址,其工作方式和Win32 API Enum Windows類似。
            3.1.2 設(shè)置DirectDraw的工作模式
              創(chuàng)建DirectDraw對象后應(yīng)該馬上設(shè)置DirectDraw對象的工作模式:
              ddres=lpDD→SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE|DDSCLFUL_LSCREEN);
              SetCooperativeLevel的第一個參數(shù)是和DirectDraw對象關(guān)聯(lián)的窗口句柄,一般是程序主窗口的句柄;第二個參數(shù)指明了DirectDraw對象的工作模式。DirectDraw對象有兩種工作模式:普通模式(Windowedmode,參數(shù)DDSCL_NORMAL)和獨占模式(Full_Screen mode,參數(shù)DDSCL_EXCLUSIVE)。普通模式下DirectDraw和普通Windows程序的區(qū)別不大,主要是DirectDraw程序可以隨心所欲地讀取整個屏幕的內(nèi)容或在屏幕的任意位置輸出,而其它的Windows程序毫無察覺。獨占模式就是游戲“紅色警報”和“赤壁”所采用的方式,并必須和全屏模式(參數(shù)DDSCL_FULLSCREEN)聯(lián)用,此時程序的主窗口被擴展為整個屏幕。其它應(yīng)用程序都成為后臺程序,使用Alt+Tab鍵可以在程序間切換。
            3.1.3 得到IDirectDraw2類型的接口
              接下來利用COM的重要方法QueryInterface,通過IDirectDraw接口得到一個IDirectDraw2類型的接口。QueryInterface成功時會將對象的引用計數(shù)加1,而我們也不再需要IDirectDraw接口,因此這里調(diào)用IDirectDraw::Release將對象的引用計數(shù)減1,也即釋放先前得到的IDirectDraw接口。
            3.1.4 根據(jù)需要切換屏幕顯示模式
              如果DirectDraw的工作模式設(shè)定為全屏獨占模式,則可以根據(jù)需要切換屏幕顯示模式:
              ddres=lpDD2→SetDisplayMode(800,600,16);
              SetDisplayMode的前兩個參數(shù)是屏幕的橫、縱分辨率,最后一個是每個像素點的顏色位數(shù)。上例將屏幕設(shè)為800×600,16位色。
            3.1.5 創(chuàng)建DirectDrawSurface對象并得到IDirectDrawSurface2接口
              創(chuàng)建DirectDraw對象后,下一步調(diào)用IDirectDraw2::CreateSurface創(chuàng)建代表物理屏幕或邏輯屏幕的DirectDrawSurface對象。IDirectDraw2::CreateSurface的第一個參數(shù)是DDSURFACEDESC結(jié)構(gòu)的地址,第二個參數(shù)是一個IDirectDrawSurface接口類型的指針地址,第三個參數(shù)必須是NULL。數(shù)據(jù)結(jié)構(gòu)DDSURFACEDESC包含了創(chuàng)建DirectDrawSurface所需信息。在得到一個IDirectDrawSurface類型接口后,仍使用QueryInterface得到一個IDirectDrawSurface2類型的接口,并釋放先前得到的IDirectDrawSurface接口:
              //Get the IDirectDrawSurface2interface.
              LPDIRECTDRAWSURFACE2lpDDSPrimary=NULL;
              ddres=lpDDSPrimaryTemp>QueryInterface(IID_IDirectDrawSurface2,(LPVOID)&lpDDSPrimary;
              lpDDSPrimaryTemp→Release();
              上面得到的lpDDSPrimary指向代表物理屏幕的對象。還需調(diào)用IDirectDrawSurface2::GetAttachedSurface得到指向創(chuàng)建時附帶的代表相關(guān)邏輯屏幕的對象指針。至此,DirectDraw初始化工作完成。

            3.2 使用DirectDraw
            3.2.1 使用GDI函數(shù)向物理屏幕或邏輯屏幕輸出
              調(diào)用IDirectDrawSurface2::GetDC可得代表某個屏幕的設(shè)備描述表的句柄,使用GDI函數(shù)輸出,最后調(diào)用IDirectDrawSurface2::ReleaseDC釋放句柄。為防止在對屏幕作圖期間其它應(yīng)用程序爭奪顯存,IDirectDrawSurface2::GetDC調(diào)用IDirectDrawSurface2::Lock得到Winl6 Lock。這意味著其它程序在該程序釋放Win16Lock前都不能訪問GDI和USER資源。IDirectDrawSurface2::ReleaseDC調(diào)用IDirectDrawSurface2::Unlock釋放Win16 Lock。于是,在調(diào)用IDirectDrawSurface2::GetDC和IDirectDrawSurface2::ReleaseDC期間,Windows將被掛起。因此,應(yīng)用程序應(yīng)盡量縮短這一對函數(shù)調(diào)用之間的間隔時間,而且調(diào)試程序也無法跟蹤這段時間內(nèi)執(zhí)行的操作。
            3.2.2 交替切換物理屏幕和邏輯屏幕或執(zhí)行屏幕內(nèi)容的映射
              準備好內(nèi)存中的邏輯屏幕后,可以調(diào)用IDirectDrawSurface2::Flip方法切換物理屏幕和邏輯屏幕,也可調(diào)用IDirectDrawSurface2::BltFast、IDirectDrawSurface2::Blt等方法執(zhí)行部分屏幕內(nèi)容的映射。一般情況下程序采用異步方式,在顯示卡硬件執(zhí)行切換動作的同時準備下一頁屏幕,使CPU和顯示卡硬件并行,提高整體執(zhí)行速度。
              使用Flip切換物理屏幕和邏輯屏幕后,原指向物理屏幕的指針仍然指向物理屏幕,原指向邏輯屏幕的指針仍然指向邏輯屏幕,即指針所指內(nèi)容也被交換了,便于程序操縱各個屏幕而不至于混淆。
            3.2.3 釋放DirectDraw對象
              程序結(jié)束之前要釋放所創(chuàng)建的DirectDraw對象。這只要在相應(yīng)接口上調(diào)用Release方法即可。

            4 使用DirectDraw的技巧和注意事項

            4.1 檢查方法的返回值
              正確執(zhí)行DirectDraw方法時都返回DDOK。且其值是零。返回其它值表明發(fā)生了某種錯誤。一般地,程序應(yīng)檢查這些返回值以決定是否出錯。

            4.2 檢查Flip和Blt的狀態(tài)
              如果在Flip或Blt操作的返回值是DDERR_WASSTILLDRAWING情況,為提高效率,DirectDraw提供了IDirectDrawSurface2::GetFlipStatus和IDirectDrawSurface2::GetBltStatus方法。它們能立即返回當前的Flip和Blt狀態(tài),于是應(yīng)用程序可以在上一操作完成之前執(zhí)行某些其他的任務(wù)。

            4.3 在位圖映射中使用ColorKey
              ColorKey是一種或幾種顏色的集合,用于在位圖映射操作中區(qū)分前景色和背景色。ColorKey包括兩種:Source color key和Destination color key。前者是指源位圖中代表透明色的顏色,在執(zhí)行映射操作時將不被映射到目標位圖上;后者是指目標位圖中將被源位圖中相應(yīng)位置顏色取代的顏色,如果目標位圖指定了Destination color key,則只有這些指定的顏色被替換。可以在創(chuàng)建DirectDrawSurface對象時指定Color Key;也可使用方法IDirectDrawSurface2::GetColorKey和IDirectDrawSurface2::SetColorKey以獲取和設(shè)置已有的DirectDrawSurface對象的ColorKey。

            4.4 GDI重定向
              由于GDI在Windows系統(tǒng)啟動時先于DirectDraw被裝入,而DirectDraw工作時又繞過了GDI,因此GDI不知道DirectDraw對物理屏幕所進行的操作。即使DirectDraw調(diào)用了Flip方法將先前的物理屏幕切換為邏輯屏幕,如不采取措施,GDI將仍然向切換后的邏輯屏幕上輸出。如果DirectDraw程序擁有菜單、滾動條等由GDI負責繪制的元素,那么在Flip完成后這些元素就會成為不可見,而在對應(yīng)的邏輯屏幕被切換成物理屏幕時又會顯示出來。為避免屏幕閃爍,DirectDraw提供了IDirectDraw2::GetGDISurface,用于確定當前被GDI認為是物理屏幕的DirectDrawSurface對象;以及IDirectDraw2::FlipToGDISurface,用于將GDI的輸出重新定向到當前的物理屏幕上。如果需要,可以在每次Flip操作后調(diào)用它,以保證屏幕正常。

            4.5 在顯存中存放位圖
              由于從顯存到顯存的映射比從系統(tǒng)內(nèi)存到顯存的映射快,所以經(jīng)常將需要映射的位圖存放在顯存中以提高速度。大多數(shù)顯示卡在存放了物理屏幕和相關(guān)邏輯屏幕之外還有足夠的內(nèi)存可以用來存放位圖。可以調(diào)用IDirectDraw2::GetCaps檢查顯存;在創(chuàng)建DirectDrawSurface對象時可以通過結(jié)構(gòu)DDSURFACEDESC中的DDSCAPS域指定該對象存在于顯存或系統(tǒng)內(nèi)存中。如果指定在顯存中創(chuàng)建對象,而顯存又沒有地方容納該對象,IDirectDraw2::CreateSurface會返回錯誤信息DDERR_OUTOFVIDEOMEMORY。如果沒有指定創(chuàng)建的位置,DirectDraw總是盡量利用空閑的顯存。

            4.6 檢查硬件的性能
              雖然DirectDraw通過HAL和HEL屏蔽了硬件的具體特性,但應(yīng)用程序也需根據(jù)硬件的不同性能來改變自身的執(zhí)行方式。利用IDirectDraw2::GetCaps方法可以得到有關(guān)硬件性能的詳細信息。

            4.7 保持主窗口的消息循環(huán)暢通
              在調(diào)用SetCooperativeLevel設(shè)置DirectDraw的工作模式時,應(yīng)用程序為DirectDraw指定了主窗口。由于DirectDraw直接操縱硬件可能導致死機,因此DirectDraw在后臺監(jiān)視主窗口的消息循環(huán),當消息循環(huán)長時間沒有反應(yīng)時,DirectDraw就釋放所有的資源,結(jié)束應(yīng)用程序的執(zhí)行。所以DirectDraw程s序應(yīng)該注意避免長時間封鎖消息循環(huán)。

             

            posted on 2007-07-22 15:27 Tim 閱讀(6887) 評論(0)  編輯 收藏 引用 所屬分類: 游戲編程

            <2012年4月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            導航

            統(tǒng)計

            公告

            本博客原創(chuàng)文章,歡迎轉(zhuǎn)載和交流。不過請注明以下信息:
            作者:TimWu
            郵箱:timfly@yeah.net
            來源:www.shnenglu.com/Tim
            感謝您對我的支持!

            留言簿(9)

            隨筆分類(173)

            IT

            Life

            搜索

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            久久国产成人精品国产成人亚洲| 99久久夜色精品国产网站| 一级做a爰片久久毛片看看| 少妇人妻综合久久中文字幕| 久久久久久久久久久精品尤物| 亚洲日韩中文无码久久| 亚洲国产精品久久久久网站| 中文字幕亚洲综合久久| 午夜精品久久久久久影视riav| 久久精品国产清高在天天线| 久久亚洲av无码精品浪潮| 久久综合给久久狠狠97色| 久久精品成人一区二区三区| 亚洲欧美成人综合久久久| 精品视频久久久久| 久久偷看各类wc女厕嘘嘘| 久久青青草原亚洲av无码| 久久精品国产精品青草app| 亚洲乱码精品久久久久..| 狠狠久久综合| 国产精品成人精品久久久| 久久久久久久亚洲Av无码| 亚洲AV成人无码久久精品老人| 久久精品亚洲精品国产欧美| 国产情侣久久久久aⅴ免费| 亚洲伊人久久大香线蕉综合图片 | 亚洲综合伊人久久大杳蕉| 久久强奷乱码老熟女| 国产精品美女久久久久AV福利| 久久人妻少妇嫩草AV无码专区| 久久久久av无码免费网| 久久久午夜精品福利内容| 中文精品久久久久人妻| 伊人久久大香线蕉综合网站| 婷婷久久综合| 尹人香蕉久久99天天拍| 亚洲人成无码网站久久99热国产| 久久AⅤ人妻少妇嫩草影院| 欧美一级久久久久久久大| 久久久久亚洲AV成人网人人网站| 久久精品无码专区免费|