天天看點

irrlicht的顯示原理

我這個标題有點故弄玄虛的味道,其實我的本意是想通過閱讀irrlicht的源碼更好的了解irrlicht的原理。但是網上類似的文章太多了,魚龍混雜層次不齊。但是往往都是從helloworld開始到source code結束,再加上貼很多的代碼,始終還是停留在入門級别的講解。怎麼能讓做到深入淺出,讓讀者更好的了解背後的真相呢?這就是我寫着一些列部落格的目的。作為一個irrlicht的初學者,希望通過自己的了解和記錄獲得進步。

當我們運作hello world的時候一個小方塊的視窗就顯示在我們面前,程式會在自己的視窗clientarea内不停的更替圖形,形成我們看到的動畫效果。這個過程就是本文要講的主要内容,期間不會涉及到代碼,在後續的部落格中會陸續講解代碼。

Irrlicht程式怎麼通過這個視窗把圖形顯示在桌面上呢?相信很多童鞋都知道大緻的原理,但是一說到細節就迷茫了。了解這個過程不是寫irrlicht程式的必要條件,甚至可以說毫無關系。我們隻要會調用irrlicht封裝好了的API就可以寫出一個漂亮的3D動畫。但是如果我們的目的不止是用API出一個程式,而是要高效的運用、靈活的應用,那麼我們不得不面對這些看上去毫無關系的話題。是以本文的話題不适合3D的初學者。

我們先從桌面管理說起。在XP時代,桌面的本質就是記憶體中的一個緩存,這塊記憶體同時在CPU和GPU的位址空間内,除了做桌面以外不能挪為它用。對于這塊記憶體大家都不陌生,在32位系統的機器上,我們買了一條2G的記憶體條,但是我們隻得到了1G多的可使用記憶體。那些消失的記憶體有一部分就是被GPU使用了,我們的桌面正在其中。作業系統把各個視窗的像素值寫到這個緩存内。當視窗A被視窗B遮擋的時候,在顯存緩存中的像素值也被B所覆寫。這時候我們用程式去抓取A的截圖的時候,會得到視窗B的像素。我們可以通過很多方式去繪制這塊顯存中的資料,比如API GetDC就可以得到桌面的裝置上下文,也可以用Windbg直接修改顯存的實體位址。Win7/Vista以後windows引入了DWM來管理桌面。此時的DWM不是強制的,使用者可以将DWM關閉,讓Win7回到XP的桌面管理模式。但是到了Win8,DWM就不能關閉了。我們可以認為DWM就是我們看到的桌面,我們桌面上的一切都是DWM繪制或者整合成的。

實際上DWM的本身就是一個DX程式,就如同我們平時寫的DX程式一樣。所有的DX程式都具有一張或多張背景緩存(back buffer),用于将圖形預先渲染到背景中。至于背景緩存的作用,相信寫過畫圖程式的童鞋應該都很清楚,它用于提高程式的效率(消除閃爍)。DX的背景緩存的作用大緻差不多。身為DX程式的DWM也具有它背景緩存。桌面首先在背景緩存中組合完畢,然後顯示到我們面前。

Win7上面那些很炫的3D效果都是DWM引入的,除了效果好看外,還真的沒有發現什麼好的地方。DWM的功能有時候有造成一些程式的不相容,以至于不得不在運作的時候關閉DWM。一方面的原因是因為做了一張DX的紋理,它的存儲格式有可能不是線性的,所有我們得到的結果不一定是我們想要的結果。

Irrlicht可以同時運作在OpenGL和DX9圖形庫上,本文單表DX9。為了讓程式的渲染結果在桌面上顯示出來,程式必須和DWM有所互動,告訴DWM自己的背景緩存(back buffer)。如果你的程式是運作在視窗模式下,irrlicth的運作過程如下:

1)  Irrlicht應用程式建立了一個win32視窗。

2)  DWM通過顯示卡驅動程式建立了一張共享的GDI紋理,大小通常等于client area。

3)  Irrlicht通過DX9建立了一張背景緩存紋理(back buffer),将圖形渲染到這張紋理中。

4)  DX9調用present,告訴OS這張紋理可以顯示了。

5)  OS将irrlicht建立的背景緩存紋理拷貝到共享的GDI紋理中。

6)  DWM将這張GDI紋理拷貝到自己的back buffer中。

7)  DWM的backbuffer通過present API把back buffer顯示到桌面。

Irrlicht完成了視窗的顯示。如果運作的全屏模式,DWM就不起作用,出irrlicht外的其他程式也不會進行present,irrlicht的back buffer就是桌面的back buffer,最後顯示在桌面的就是irrlicht。在win7以後大部分的視窗都是一個DX程式,顯示的原理和上面所講的差不多。