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

            醬壇子

            專注C++技術(shù) 在這里寫下自己的學(xué)習(xí)心得 感悟 和大家討論 共同進(jìn)步(歡迎批評(píng)!!!)

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              66 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

            公告

            王一偉 湖南商學(xué)院畢業(yè) 電子信息工程專業(yè)

            常用鏈接

            留言簿(19)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            積分與排名

            • 積分 - 387834
            • 排名 - 64

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            由于Aug 8造成的D3D9恐懼癥已經(jīng)完全消除了,這一章將會(huì)給大家介紹將3D引擎轉(zhuǎn)向D3D9的各個(gè)方面,包括終于出現(xiàn)的全屏幕模式。從這章以后,我將使用D3D9作為講解的語言繼續(xù)D2D教程。

            【OP結(jié)束,開始正片】

            『Why?』

              估計(jì)大家首先要問的就是“Why?”為什么要前進(jìn)到D3D9?理由如下:
            1、D3D9修復(fù)了D3D8已知的所有Bug,因此運(yùn)行起來更穩(wěn)定,速度也要快。
            2、D3D9提供了許多便利的新功能,雖然絕大多數(shù)是面向3D的,但是也有不少2D適用的,比如IDirect3DDevice9::StretchRect,以及對(duì)IDirect3DSurface9的改進(jìn)等等。D3DX庫就更多了,比如D3DXSaveSurfaceToFileInMemory,一開始沒發(fā)現(xiàn)這個(gè)函數(shù)有啥用處,現(xiàn)在基本離不開了。
            3、HLSL。就像上一話我說的那樣,D2D教程以后會(huì)有PixelShader的內(nèi)容。我可不想拿匯編來寫Shader,會(huì)死人的(祝賀我吧,終于拋棄匯編Shader了……)。雖然說這不是決定性的理由,因?yàn)檫€有Cg什么的,不過我想編寫顯卡無關(guān)的代碼,因此我不去研究Cg(反正和HLSL差不多)以及R2VB之類。
            4、ID3DXFont,往下看你就知道了。

            《D3D的變化》

            『界面名稱變化』

              一句話:8改成9就行。

            『“創(chuàng)建”型方法的一個(gè)統(tǒng)一變化』

              許多Create*()方法,比如創(chuàng)建設(shè)備、創(chuàng)建紋理、創(chuàng)建頂點(diǎn)緩沖等等,多了一個(gè)HANDLE* pSharedHandle參數(shù),無用,NULL之(看來微軟原打算弄個(gè)共享句柄之類,不過被D3D10巨大的變化浮云了)

            『創(chuàng)建D3D設(shè)備的變化』

              D3DPRESENT_PARAMS的FullScreen_PresentationInterval變成了PresentationInterval,也就是說即使在窗口模式下也可以做到垂直同步來防止撕裂現(xiàn)象(2D的福音啊)。相應(yīng)的,D3DSWAPEFFECT_COPY_VSYNC消失了,反正這個(gè)效果也不咋的,消失了也好。
              要做到垂直同步需要給PresentationInterval賦值D3DPRESENT_INTERVAL_DEFAULT或D3DPRESENT_INTERVAL_ONE。其中D3DPRESENT_INTERVAL_ONE的效果比D3DPRESENT_INTERVAL_DEFAULT好一點(diǎn),不過相應(yīng)的也會(huì)占用多一點(diǎn)點(diǎn)系統(tǒng)資源……真的只有一點(diǎn)點(diǎn)而已,實(shí)在是無所謂的……
              如果不要垂直同步,想要看看實(shí)際禎速的話,D3DPRESENT_INTERVAL_IMMEDIATE。
              注意在窗口模式下,你只能使用這三種Present模式,全屏幕模式下就可以使用別的(但是要首先檢測(cè)D3DCAPS9以查看顯卡是否支持)。不過我感覺對(duì)99%的游戲來說,有這三個(gè)就足夠了。
              另外在窗口模式下,BackBufferFormat也可以設(shè)置成D3DFMT_UNKNOWN,D3D會(huì)自動(dòng)獲取當(dāng)前桌面的格式設(shè)定成后備緩沖的格式,省去GetDisplayMode。實(shí)際上,窗口模式下的后備緩沖已經(jīng)不需要和桌面格式相同,你可以通過IDirect3D9::CheckDeviceFormatConversion來檢查,如果這個(gè)設(shè)備支持這兩種顏色格式之間的轉(zhuǎn)換,就可以給程序的后備緩沖設(shè)定上不同的格式。我試過在桌面格式為32Bit(D3DFMT_X8R8G8B8)時(shí)將程序的后備緩沖格式設(shè)置為D3DFMT_R5G6B5(16Bit),發(fā)現(xiàn)了速度提升,也就是說這個(gè)設(shè)定是有意義的。
              可創(chuàng)建的設(shè)備類型多了一種D3DDEVTYPE_NULLREF,在安裝了D3D SDK的機(jī)子上等同于D3DDEYTYPE_REF,在其他的機(jī)子上,這種設(shè)備實(shí)際上沒有創(chuàng)建真正意義的D3D設(shè)備,只是允許你創(chuàng)建的紋理、表面等資源,但是Render、Present等操作都會(huì)無效(實(shí)際上這些資源都創(chuàng)建在了D3DPOOL_SCRATCH池里,不管你設(shè)定使用的是什么POOL)。也就是說,僅僅在模擬基本的運(yùn)行而已。你可以用這個(gè)設(shè)備來編寫一個(gè)利用D3DX函數(shù)庫進(jìn)行圖像格式轉(zhuǎn)換的程序,比如把一大堆不同的格式轉(zhuǎn)換成易于D3D9使用的DDS格式。因?yàn)閷?shí)際上沒有創(chuàng)建設(shè)備,你甚至可以編寫成控制臺(tái)的,通過GetConsoleWindow的方法獲得HWND。Mercury 3用的MIF格式的轉(zhuǎn)換器就是這么做出來的。注意D3DDEVTYPE_NULLREF只能用在IDirect3D::CreateDevice時(shí),其他的方法都不行。

            『創(chuàng)建表面的變化』

              創(chuàng)建表面(Surface)的方法變成了IDirect3DDevice9::CreateOffscreenPlainSurface,參數(shù)很簡單不用多說,需要注意的是可以選擇POOL了。

            『設(shè)定FVF的變化』

              設(shè)定FVF時(shí),原來通過IDirect3DDevice8::SetVertexShader,現(xiàn)在有了一個(gè)專門用來設(shè)定FVF的方法:IDirect3DDevice9::SetFVF。這是個(gè)很好的變化,省得把FVF和Shader弄混(題外話:也就是因?yàn)檫@個(gè)變化,讓Shader在設(shè)備Reset后得以保存,不錯(cuò)不錯(cuò))

            『獲取后備緩沖』

              D3D9現(xiàn)在允許有多個(gè)后備緩沖交換鏈,不過對(duì)于2D來說,基本不需要這種東西,IDirect3DDevice9::GetBackBuffer多出來的第一個(gè)參數(shù)賦值0即可。如果你有興趣,可以去研究一下這個(gè)玩意,有時(shí)候可以用來做分場(chǎng)。

            『SetStreamSource』

              這個(gè)方法的功能被擴(kuò)展了,對(duì)比參數(shù)就可以知道,多出來的OffsetInBytes允許你選擇一個(gè)頂點(diǎn)緩沖的Offset,D3D9將從這個(gè)Offset之后開始讀取數(shù)據(jù)。因此你可以把幾組用來渲染紋理的正方形頂點(diǎn)存儲(chǔ)到一個(gè)頂點(diǎn)緩沖里面。

            『SetSamplerState』

              這個(gè)是D3D9的新方法,把原先SetTextureStageState的一些功能獨(dú)立了出來,和2D關(guān)系最密切的就是紋理過濾了。原先的D3DTSS_MINFILTER變成了D3DSAMP_MINFILTER,相應(yīng)的D3DTSS_MAGFILTER也變成D3DSAMP_MAGFILTER,D3DTSS_MAXANISOTROPY變成D3DSAMP_MAXANISOTROPY。另外還有更多的,比如紋理尋址等。你去看一下D3DSAMPLERSTATETYPE枚舉類型的內(nèi)容就知道它“遷移”了些什么。
              這個(gè)變化對(duì)于Shader來說很方便。改成Sampler的東西在PixelShader過程也會(huì)有效,而沒有更改的東西在PixelShader就不會(huì)有效了。D3D8時(shí)候把這些全都放在了一起,容易造成混亂。

            『SetRenderTarget』

              D3D9現(xiàn)在允許多重RenderTarget存在,不過我們基本上只用一個(gè),RenderTargetIndex設(shè)為0,第二個(gè)參數(shù)仍然是需要設(shè)定的表面。與D3D8相同的是,在設(shè)定之前仍然需要先通過GetSurfaceLevel獲得表面才行。

            『頂點(diǎn)緩沖的鎖定』

              注意IDirect3DVertexBuffer9::Lock的第三個(gè)參數(shù),從原來的BYTE**變成了void**。也就是這樣了……

            『其他的一些變化』

            1、CopyRects變成了UpdateSurface。和UpdateTexture一樣,只能從D3DPOOL_SYSTEMMEM拷貝到D3DPOOL_DEFAULT
            2、增加了一個(gè)比較有用的IDirect3DDevice9::ColorFill方法,作用是向D3DPOOL_DEFAULT的某個(gè)區(qū)域填充顏色,和Clear的功能類似,但是在使用目的上要比Clear明確的多,并且由于不牽扯深度緩沖之類,速度要快一些。
            3、增加了一個(gè)IDirect3DDevice9::StretchRect方法,通過這個(gè)方法就可以在D3DPOOL_DEFAULT的表面或紋理之間進(jìn)行帶過濾器的縮放操作,免去利用Render的過程,非常有用。不過這個(gè)方法由于使用了硬件處理,限制較多,請(qǐng)大家仔細(xì)看SDK文檔的Remarks部分。

            《D3DX的變化》

              D3DX的變化實(shí)際上相當(dāng)?shù)亩啵缥乙婚_始所說,基本都是面向3D的。需要我們注意的有以下幾種:
            1、D3DX***FromFile之類的函數(shù)支持的圖像格式增加了,不過所增加的都是很少見的格式。平時(shí)基本上還是用BMP、TGA和PNG就足夠。
            2、增加了D3DXSave***ToFileInMemory,將會(huì)把文件寫入內(nèi)存。這個(gè)函數(shù)的作用似乎不是很容易想到,但是如果你要寫一個(gè)集成了轉(zhuǎn)換、打包功能的工具,這個(gè)就很有用了,省去了通過臨時(shí)文件操作造成的各種問題。另外如果你熟悉某種圖形文件的格式的話,還可以通過直接訪問這個(gè)文件獲得RAW信息。注意,這類函數(shù)寫入的是一個(gè)ID3DXBuffer,這個(gè)東西很簡單,只有兩個(gè)特定的方法,一看便懂,不再多言。
            3、增加了一個(gè)ID3DXLine,可以方便你在2D上畫線,創(chuàng)建ID3DXLine的方法是D3DXCreateLine。這個(gè)東西也不復(fù)雜,使用方法有點(diǎn)像ID3DXSprite,稍微研究一下就能弄懂,注意每次Draw的是D3DPT_LINESTRIP。用它比直接用頂點(diǎn)緩沖的好處是可以方便的打開反鋸齒,效果嘛……基本滿意。
            4、增加了一個(gè)ID3DXRenderToSurface,“理論上來說”方便了利用RenderTarget的過程……不過我感覺反而弄得復(fù)雜了。創(chuàng)建的方法是D3DXCreateRenderToSurface,有心情的朋友自己研究看看吧,我就不講了。

              ID3DXSprite和ID3DXFont在Summer 2004的DX9 SDK(也就是第一版DX9.0c)開始發(fā)生了很大變化,下面詳述:

            『ID3DXSprite』

              你會(huì)發(fā)現(xiàn)ID3DXSprite::DrawTransform不見了,取而代之的是其功能被整合到ID3DXSprite::SetTransform里面,也就是說為了縮放和旋轉(zhuǎn),我們不得不和矩陣打交道了。其實(shí)也不會(huì)太復(fù)雜,因?yàn)槲覀冎皇亲鲆恍┚仃囘\(yùn)算,學(xué)過線性代數(shù)的朋友肯定會(huì)很熟悉,就算你不怎么熟悉線性代數(shù),也沒關(guān)系,D3DX函數(shù)庫提供了現(xiàn)成的矩陣運(yùn)算函數(shù),你只要用就行了。

            D3DXMatrixScaling
            D3DXMatrixRotationZ
            D3DXMatrixTranslation

              按照順序調(diào)用這三個(gè)函數(shù)……或許學(xué)過3D的馬上就想到這點(diǎn)了,的確是沒錯(cuò)啦。注意順序哦:Scaling -> Rotation -> Translation,簡稱SRT(看過全金屬狂潮嗎?看過的話這個(gè)單詞很好記吧^_^),弄錯(cuò)了可是得不到正確結(jié)果的。
              你是不是想到把同一個(gè)D3DXMATRIX當(dāng)作參數(shù)使用三次?錯(cuò)啦!你要用矩陣乘法。創(chuàng)建三個(gè)D3DXMATRIX,比如mat1、mat2、mat3,分別用這三個(gè)函數(shù)將其創(chuàng)建為縮放矩陣、旋轉(zhuǎn)矩陣和平移矩陣,然后在ID3DXSprite::SetTransform時(shí),這樣寫:

            SetTransform(mat1 * mat2 * mat3);

              有夠麻煩的是不?ID3DXSprite方便了做3D的,可害苦了做2D的,所以我已經(jīng)不直接用這個(gè)了(什么叫不直接用?往下看)。

            『ID3DXFont』

              大家來歡呼吧!Summer 2004改進(jìn)的ID3DXFont徹底槍斃掉了上一話那個(gè)字體引擎……
              這東西的改進(jìn),怎么說呢,應(yīng)該說是改頭換面吧,速度、效果都和以前不是一個(gè)數(shù)量級(jí)。可憐的PixelFont,才存在了一話就要被拋棄了。
              ID3DXFont多出來的幾個(gè)方法,Preload*()這類的,就是把一些常用的字的字模提前讀取到內(nèi)存里面加快速度,同時(shí)還可以使用ID3DXSprite渲染,進(jìn)一步加快速度。雖然內(nèi)部仍然有GDI的部分,不過很明顯工作方式發(fā)生了極大的變化。根據(jù)我的估計(jì),這次的ID3DXFont很聰明的利用GDI獲得文字的輪廓,然后通過紋理來渲染。這樣的速度就快得多了,而且文字質(zhì)量也得到了很好的控制,基本和直接用GDI的質(zhì)量相同了。
              由于PreloadCharacters()和PreloadGlyphs()不是那么好理解,一般用PreloadText()就行。建議將所有ASCII字符、標(biāo)點(diǎn)符號(hào)和部分漢字預(yù)讀進(jìn)去。這個(gè)預(yù)讀過程略微有點(diǎn)慢,而且根據(jù)預(yù)讀的文字?jǐn)?shù)量和你創(chuàng)建文字的字號(hào),占用的內(nèi)存也不同。這里給大家一堆文字,你Copy過去就行:

            引用

            const char strPreloadText[] = " 1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM~!@#$%^&*()-=[]\\;',./_+{}|:\"<>? 、。·ˉˇ¨〃—~‖…‘’“”〔〕〈〉《》「」『』〖〗【】!"#¥%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}我人有的和主產(chǎn)不為這工要在第一上是中國經(jīng)已發(fā)了民同";

              注意第一個(gè)字符是空格哦!把空格預(yù)讀進(jìn)去可是很重要的^_^
              看上去并不多,因?yàn)橐紤]到內(nèi)存占用及速度,我只預(yù)讀了一些符號(hào)和五筆的一鍵字。這些字符在24號(hào)字時(shí)候已經(jīng)占用了快1MB了,比起PixelFont字庫占用的要大得多。天知道ID3DXFont到底預(yù)讀了些什么……
              PreloadText()的第二個(gè)參數(shù)不要用strlen,sizeof(strPreloadText)即可。
              然后就是利用ID3DXSprite來渲染。注意ID3DXFont::DrawText的第一個(gè)參數(shù)就是LPD3DXSPRITE,因此如果要利用ID3DXSprite,要將ID3DXFont::DrawText放到ID3DXSprite::Begin和ID3DXSprite::End之間。這就是我剛才說的不直接用ID3DXSprite的意思,ID3DXFont會(huì)完成ID3DXSprite的全部調(diào)用,你不用擔(dān)心。
              另外你應(yīng)該注意到ID3DXSprite::Begin增加了參數(shù),實(shí)際上DX文檔里面沒說,但是示例里面有,如果想讓ID3DXSprite發(fā)揮作用并且最大幅度的提升效率,參數(shù)上設(shè)定D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE即可。意思很明白:打開Alpha過濾和紋理篩選。這里DX文檔上有個(gè)錯(cuò)誤一直沒改:文檔里給出的是D3DXSprite__SORT_TEXTURE,但是你可以試試,絕對(duì)報(bào)錯(cuò)。
              剩下的就沒啥了,ID3DXFont的使用方法上一話已經(jīng)講過。要注意的是D3DXCreateFont和D3DXCreateFontIndirect都發(fā)生了變化。D3DXCreateFont已經(jīng)不再牽扯GDI了,D3DXCreateFontIndirect所使用的結(jié)構(gòu)也變成了D3DXFONT_DESC,相對(duì)于LOGFONT結(jié)構(gòu),除去了一些用不著的參數(shù),增加了一個(gè)MipLevels,就是MipMap等級(jí)啦,不用多說,2D下只用1。其他的上一話都有。實(shí)際上由于D3DXCreateFont已經(jīng)不再關(guān)聯(lián)GDI,D3DXCreateFontIndirect的存在僅僅是由于歷史原因(為了兼容像我這種人的使用習(xí)慣),大家還是用D3DXCreateFont吧,省事。
              截圖就不貼了,沒啥意義。你可能覺得直接向后備緩沖上DrawText還不夠好看,那么就先畫到一張紋理上,然后將紋理錯(cuò)位渲染到后備緩沖并且打開線型過濾,就可以達(dá)到和PixelFont相同的效果了。
              速度嘛……我畫了整整一屏幕字,在不緩沖文字的情況下(這個(gè)“緩沖文字”和ID3DXFont的文字緩沖可不是一回事啊!看過上一話的都應(yīng)該知道我這里指的是什么),速度仍然在120FPS以上。或許你會(huì)覺得速度還是有點(diǎn)慢,但是,如果用D3D8的ID3DXFont畫上這么一屏幕,基本就只剩20FPS了。
              使用ID3DXFont替換掉PixelFont的優(yōu)勢(shì)就是可以方便的自定義字體字號(hào)了,并且也不再受GB2312字庫的限制。所以大家都換了吧……都換了吧……把PixelFont忘了吧……

            『穩(wěn)定的DX9 SDK版本』

              我現(xiàn)在用的是April 2006,而且應(yīng)該會(huì)用很長時(shí)間。August 2006我是肯定不會(huì)去用啦!即使我不再恐懼D3D9,也會(huì)對(duì)這個(gè)SDK避讓三分的。其實(shí)對(duì)于2D,我感覺用到April 2006就足夠了,之后的DX9 SDK主要在D3DX的3D函數(shù)庫部分進(jìn)行更改……其實(shí)也是秋后的螞蚱蹦達(dá)不了幾天,D3D10馬上就要出來了。要說D3D10啊……你還是看我另外一篇日志好了,總之打死我都不拿它做2D。

              實(shí)際上僅僅是2D的話,從D3D8轉(zhuǎn)向D3D9并沒有多少變化,主要是穩(wěn)定嘛!只要你不調(diào)用一些D3D9專用的功能,即使拿D3D9來做2D,在絕大多數(shù)顯卡上還是能夠運(yùn)行的。嗯……GF2等級(jí)以上吧,GF2之前的,也太老了,無視好了。

            《再上點(diǎn)菜好了:全屏幕模式》

              其實(shí)并不是多么復(fù)雜的問題,讓我拖了這么久……不拖了,這里就教給大家如何做全屏幕模式以及如何處理設(shè)備丟失的問題。

            『創(chuàng)建全屏幕模式』

              D3DPRESENT_PARAMS里面,Windowed設(shè)定為false,并且一定要設(shè)定BackBufferWidth和BackBufferHeight,完畢。
              哈哈,就這么簡單,或許早就有人嘗試過了,但是你試試按下Alt+Tab,再切換回去,保證你什么都看不到。
              之前曾經(jīng)說過,DX8之前的版本,在全屏幕下工作比在窗口下容易,到DX8之后就則完全顛倒過來。因?yàn)樵诖翱谀J较虏挥脫?dān)心設(shè)備丟失(除非你更改桌面分辨率),全屏幕模式下就會(huì)有這個(gè)問題了。下面詳述:

            『設(shè)備、資源丟失』

              設(shè)備丟失會(huì)發(fā)生在全屏幕模式下切換回桌面時(shí)(不論是通過Alt+Tab還是QQ上有人給你發(fā)了張圖片-_-bbb),而且如果在調(diào)用IDirect3DDevice9::Reset(從現(xiàn)在開始就是D3D9了啊!忘記D3D8吧……)的時(shí)候發(fā)生錯(cuò)誤,設(shè)備也會(huì)丟失。
              設(shè)備丟失會(huì)造成資源丟失:所有創(chuàng)建在D3DPOOL_DEFAULT池的資源都會(huì)丟失,需要重新創(chuàng)建,其內(nèi)容當(dāng)然也會(huì)消失,需要重寫。
              然而創(chuàng)建在D3DPOOL_SYSTEMMEM和D3DPOOL_SCRATCH池的資源不會(huì)受到影響。創(chuàng)建在D3DPOOL_MANAGED池的資源也不會(huì)丟失,而且在設(shè)備重新可用的時(shí)候,D3DPOOL_MANAGED池的資源也可以立即投入使用,內(nèi)容也不會(huì)改變。看這個(gè)池名字:托管池就能知道,D3D幫你處理了所有問題。
              因此避免設(shè)備丟失后資源丟失的簡易方法就是將所有資源創(chuàng)建在D3DPOOL_MANAGED池內(nèi)。不過這并不是個(gè)好方法,這意味著不能用渲染對(duì)象——記得嗎?RenderTarget只能創(chuàng)建在D3DPOOL_DEFAULT。實(shí)際上最好的方法是跟蹤所有D3DPOOL_DEFAULT資源,比如利用std::list,將所有D3DPOOL_DEFAULT資源勾住,在設(shè)備發(fā)生丟失的時(shí)候釋放掉資源,設(shè)備可以繼續(xù)使用的時(shí)候重新創(chuàng)建資源,記得把數(shù)據(jù)寫回去。對(duì)于其他的池就不用這么折騰了。

            『當(dāng)設(shè)備丟失之后』

              不論通過任何方式發(fā)生了設(shè)備丟失,所有的操作幾乎都會(huì)失效,只有Release()可以用——其實(shí)D3D會(huì)保證有部分操作可以成功,但是也僅僅是“可以”成功而不是“一定”成功,所以你還不如認(rèn)定丟失的時(shí)候全都會(huì)失敗比較好——以及IDirect3DDevice9::TestCooperativeLevel。因此在設(shè)備丟失之后,你應(yīng)該停止整個(gè)游戲循環(huán),而通過反復(fù)調(diào)用IDirect3DDevice9::TestCooperativeLevel判斷設(shè)備是否可用。

            『IDirect3DDevice9::TestCooperativeLevel』

              這個(gè)方法檢測(cè)當(dāng)前的設(shè)備狀態(tài)。返回值有四種:D3D_OK一切正常,D3DERR_DEVICELOST設(shè)備丟失,D3DERR_DEVICENOTRESET設(shè)備可以Reset。另外還有D3D9新增的D3DERR_DRIVERINTERNALERROR,遇到這個(gè)你就完蛋了,基本不可能恢復(fù)了,終止程序吧。
              按照順序來講,如果游戲在正常運(yùn)行,D3D_OK會(huì)返回;如果發(fā)生了設(shè)備丟失并且在這個(gè)時(shí)候不能恢復(fù),比如全屏幕模式的時(shí)候用戶切換到了Windows桌面,就會(huì)返回D3DERR_DEVICELOST;如果用戶又切換回了游戲,設(shè)備可以恢復(fù)了(還沒恢復(fù)呢!只是“可以”恢復(fù)而已),就會(huì)返回D3DERR_DEVICENOTRESET。
              另外,IDirect3DDevice9::Present也會(huì)返回類似的值,不過你最好別指望這個(gè),老老實(shí)實(shí)的用TestCooperativeLevel。因?yàn)镻resent在設(shè)備可以恢復(fù)的時(shí)候還是返回D3DERR_DEVICELOST(外一句:D3D10的時(shí)候TestCooperativeLevel就會(huì)完全整合到Present里面了,可喜可賀可喜可賀)

            『處理設(shè)備丟失』

              看下面的偽代碼:

            switch (IDirect3DDevice9::TestCooperativeLevel()){
              case D3D_OK:
                GameLoop();
                break;
              case D3DERR_DEVICELOST:
                break;
              case D3DERR_DEVICENOTRESET
                OnLostDevice();
                IDirect3DDevice9::Reset();
                OnResetDevice();
                break;
              default:
                QuitGame();
                break;
            }

              GameLoop()就是你的游戲運(yùn)行的過程了。把這個(gè)switch寫在我們游戲框架的GameMain()部分,具體的位置可以看任何一話附帶的源代碼。
              好像我一直沒有講IDirect3DDevice9::Reset的參數(shù)啊?因?yàn)橹挥幸粋€(gè)參數(shù),就是指向D3DPRESENT_PARAMS的指針。把你第一次創(chuàng)建設(shè)備時(shí)使用的D3DPRESENT_PARAMS結(jié)構(gòu)保存起來,供Reset來用。
              OnLostDevice()就是Release掉所有D3DPOOL_DEFAULT的資源,OnResetDevice()就是Create*()恢復(fù)啦!你可能注意到ID3DXFont、ID3DXSprite等等都有同名的方法,就是在這個(gè)時(shí)候調(diào)用的。如果你沒有這么做,也就是說還保留著任何D3DPOOL_DEFAULT的資源的話,IDirect3DDevice9::Reset就一定會(huì)失敗。
              另外在OnResetDevice里面你還要重新進(jìn)行SetRenderState、SetSamplerState等等,Reset之后這些東西也丟失了。實(shí)際上Reset和重新創(chuàng)建一次設(shè)備類似,所不同的是重新創(chuàng)建設(shè)備的話你需要連D3DPOOL_MANAGED的資源也Release掉。這個(gè)話題就不討論了。
              從代碼可以看出來,D3DERR_DEVICELOST時(shí)程序什么都沒做,只是在傻等。我認(rèn)為這是一個(gè)好習(xí)慣,因?yàn)閷?shí)在不能保證在D3DERR_DEVICELOST時(shí)除了Release還能干什么,與其這樣還不如等設(shè)備能用了再說。

              實(shí)在懶得管資源的話,全部D3DPOOL_MANAGED好了。至于渲染對(duì)象?自己想辦法。

            『人工制造“設(shè)備丟失”』

              “干嘛還要制造設(shè)備丟失啊?”如果更改游戲分辨率、色深、切換全屏幕及窗口狀態(tài),進(jìn)行這樣的操作也要通過Reset,同樣的,Reset之前也要釋放掉所有D3DPOOL_DEFAULT資源(其實(shí)嚴(yán)格來說,還有更多的資源也要釋放,不過在2D下基本不會(huì)創(chuàng)建這類資源,你就不用管了)并且調(diào)用ID3DXSprite::OnLostDevice之類的方法。這就是人工制造“設(shè)備丟失”了。實(shí)際上在這個(gè)過程設(shè)備并沒有真正的丟失,只是會(huì)有一段時(shí)間處于不可用的狀態(tài),此時(shí)Reset尚未返回,整個(gè)D3D設(shè)備就好像死了一樣。舉個(gè)例子,你切換桌面分辨率,會(huì)有那么一段時(shí)間顯示器上什么都不顯示,然后很快就正常了。和這個(gè)現(xiàn)象是同一個(gè)原因。Reset成功后記得恢復(fù)資源。
              你可能注意到這里的Reset和上面的Reset不是一回事。的確是這樣,這里是為了重設(shè)狀態(tài)而不是恢復(fù)設(shè)備。因此更改分辨率、色深的Reset需要寫到switch外面,也就是別和它攪和的意思-_-bb。而且你只需要OnLostDevice -> Reset -> OnResetDevice。記住:正確的調(diào)用Reset不會(huì)造成設(shè)備丟失,這個(gè)概念別弄混了。

            『切換全屏幕模式時(shí)的注意事項(xiàng)』

              注意WindowStyle的變化。切換成全屏幕模式后,只能使用WS_POPUP,不然顯示會(huì)變得怪怪的,你可以通過SetWindowLongPtr函數(shù)更改窗口外觀,第二個(gè)參數(shù)指定GWL_STYLE即可。別忘了WS_VISIBLE啊!不然你什么都看不見。

            『更詳細(xì)的文檔』

              我這里只是簡單討論了造成設(shè)備丟失的原因及處理方法,更詳細(xì)的內(nèi)容你可以參考DX SDK文檔的Lost Device文章,人家是權(quán)威的。

            【以上,正片結(jié)束,后面是ED】

              我們前進(jìn)到了D3D9,趕上了時(shí)代。
              我們創(chuàng)建了全屏幕游戲,趕上了時(shí)代。
              我卻變得一腦子漿糊,被觀眾拋棄了。
              哈哈,開玩笑啦,不過這一話很亂倒是真的,因?yàn)椴徽撌歉碌紻3D9還是設(shè)備丟失,牽扯的東西都太散太雜,結(jié)果弄得這一話也是一盤散沙(居然又沒有附帶代碼)。唉,大家就忍了吧,忍不了的話就來PIA我吧。

              關(guān)于更新至D3D9更多的內(nèi)容,你可以參考SDK文檔的《Converting to Direct3D 9》。

            【以上,ED結(jié)束,后面是……】

              第一季完結(jié)了……
              回過頭來看看,從第一話創(chuàng)建一個(gè)Windows窗口,到這一話的設(shè)備丟失,話題的層次一直在深入,現(xiàn)在已經(jīng)深入到了不再是“學(xué)習(xí)”而是“研究”的范圍。我也不再想僅僅是搞“教學(xué)”而是想和大家“討論”。不過第一季主要還是教學(xué)吧。能堅(jiān)持著看D2D教程到現(xiàn)在的,應(yīng)該基本能夠?qū)懗鐾暾?D Demo來了吧。如果有什么問題的話,歡迎提出,我在看到后會(huì)立刻回答的……只要你這個(gè)問題不太RP的話……
              那么,第二季會(huì)是什么樣子?
              第二季就不再是教學(xué)了,而開始我和大家的討論過程。第二季的第一話,也就是第09話,我將提供一些高級(jí)技巧給大家,并希望有興趣的朋友和我一起進(jìn)行這些技巧的研究。另外在第二季里面,我們還要?jiǎng)?chuàng)建一個(gè)2D圖形引擎。原來打算給大家講解Medux 2,不過現(xiàn)在感覺這東西實(shí)在小兒科,絕對(duì)會(huì)讓大家B4的。那么既然如此,干脆介紹Mercury 3好了,有意見無?
              透漏一點(diǎn)下一話的內(nèi)容吧:模糊精度和多次紋理渲染,嘿嘿,聽上去挺高深的是不?實(shí)際上超級(jí)簡單,就看你能不能想到而已。
              希望你在看完這一話之后,返回去再把前面的內(nèi)容看看,相信你會(huì)得到新的收獲。搞不好你還能抓出幾個(gè)Bug呢!因?yàn)槲沂窍氲绞裁磳懯裁矗瑳]個(gè)章法,Bug是難免的。
            posted on 2007-01-04 00:57 @王一偉 閱讀(18327) 評(píng)論(4)  編輯 收藏 引用

            Feedback

            # re: D3d9的一些更新 2007-02-06 11:04 baisix
            D3DXSaveSurfaceToFileInMemory你會(huì)用嗎?  回復(fù)  更多評(píng)論
              

            # re: D3d9的一些更新 2007-02-07 00:21 醬菜
            D3DXSaveSurfaceToFileInMemory
            Saves a surface to an image file.

            HRESULT D3DXSaveSurfaceToFileInMemory(
            LPD3DXBUFFER * ppDestBuf,
            D3DXIMAGE_FILEFORMAT DestFormat,
            LPDIRECT3DSURFACE9 pSrcSurface,
            CONST PALETTEENTRY * pSrcPalette,
            CONST RECT * pSrcRect
            );
            Parameters
            ppDestBuf
            [out] Address of a pointer to an ID3DXBuffer that will store the image.
            DestFormat
            [in] D3DXIMAGE_FILEFORMAT specifying the file format to use when saving. This function supports saving to all D3DXIMAGE_FILEFORMAT formats except Portable Pixmap (.ppm) and Targa/Truevision Graphics Adapter (.tga).
            pSrcSurface
            [in] Pointer to IDirect3DSurface9 interface containing the image to be saved.
            pSrcPalette
            [in] Pointer to a PALETTEENTRY structure containing a palette of 256 colors. This parameter can be NULL.
            pSrcRect
            [in] Pointer to a RECT structure. Specifies the source rectangle. Set this parameter to NULL to specify the entire image.
              回復(fù)  更多評(píng)論
              

            # re: D3d9的一些更新 2007-08-18 16:45 林坤忠
            我的媽媽咪壓.ˊ˙&^%&&^%$^$^%^&^%^%$  回復(fù)  更多評(píng)論
              

            # re: D3d9的一些更新 2007-08-20 17:21 horeaper
            壇子認(rèn)識(shí)我嗎?  回復(fù)  更多評(píng)論
              


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            色综合久久综合网观看| 人人狠狠综合久久亚洲| 色悠久久久久久久综合网| 久久久久久久国产免费看| 亚洲国产成人久久精品99| 亚洲国产精品成人久久蜜臀| 亚洲国产小视频精品久久久三级| 青青热久久国产久精品 | 欧美日韩成人精品久久久免费看| 色综合久久天天综线观看| 久久www免费人成看片| 久久国产免费观看精品3| 久久久久人妻一区精品| 久久无码专区国产精品发布 | 久久人人爽人人爽人人片AV高清| 伊人久久大香线蕉亚洲| 久久国产成人午夜AV影院| 欧洲人妻丰满av无码久久不卡| 免费一级做a爰片久久毛片潮| 亚洲∧v久久久无码精品| 中文字幕精品久久| 精品久久久久久成人AV| 亚洲精品午夜国产VA久久成人| 一本大道加勒比久久综合| 久久精品国产亚洲一区二区| 午夜精品久久久久久99热| 狠狠狠色丁香婷婷综合久久俺| 一级女性全黄久久生活片免费| 人人狠狠综合久久亚洲婷婷| 欧美大香线蕉线伊人久久| 久久天天婷婷五月俺也去| 久久精品国产一区二区 | 久久国产免费观看精品3| 亚洲中文字幕无码一久久区| 午夜精品久久影院蜜桃| 久久精品成人免费观看97| 国产精品99久久精品爆乳| 亚洲精品tv久久久久久久久久| 国产免费久久精品99久久| 日韩精品久久久久久| 国产精品久久久久久|