3D遊戲引擎設計與實現1-15

 /***********************************
 *作者:蔡軍生
 *出處:http://blog.csdn.net/caimouse/
 ************************************/
 
 3D遊戲引擎設計與實現1-15
3D遊戲引擎設計與實現(1)
       當寫這個標題時,心裏想:有可能實現出來嗎?現在抱着學習與實踐態度,只要去努力,肯定會有收穫的。費話少說,下面就開始把自己的想法先寫出來,因爲有目的而來,從來不打沒有準備的仗。
       在進行這個項目之前,肯定先去學習一下什麼叫Computer graphics,就是計算機圖像,它跟圖像處理是大的不同,因爲它是研究怎麼樣生成圖像,而圖像處理主要圖像壓縮存儲等。除了這個之後,還要學習一點線性代數和空間解析幾何。有這些基礎之後,就可以去看看DirectX的例子,看看什麼是3D,在計算機怎麼樣表示3D物體,當然要了解複雜的光照,還需要物理知識等。
       我設計這個3D遊戲引擎,主要實現很簡單的功能,細節的東西目前先不用考濾,因爲開發過程是迭代的,不可能第一次就開發一個完美的引擎,也不可能一下子完成。先選擇合適平臺、開發工具和設計大體架構。這裏我選擇主要是Windows平臺,並且3D的API就選擇DirectX,目前不支持OpenGL。開發工具就用VS 2003.net中文版,因爲它支持C++達到98%,這樣可以完全使用C++的性能,面向對象的設計,模板方式重用代碼。架構設計取用模塊式設計,採用COM方式的DLL實現,這樣可以把每個模塊開發來,達到代碼最大化的重用。
       現在總結一下目標是什麼,如下:
l         平臺:Windows平臺
l         3D API: DirectX
l         開發工具:VS 2003.net中文版
l         架構:COM方式的DLL
還有很多東西沒有想到,等着後面更進一步的設計。
 
 3D遊戲引擎設計與實現(2)
3D遊戲引擎設計與實現(2)
       經過幾天萌思苦想,總算又設計3D遊戲引擎的架構細節部份。原來說到要用到像COM組件的DLL實現,因此怎麼樣把遊戲公共部份寫到一起,變化部份寫到一起,這樣就能達到源程序重用,也可以簡少維護工作。同時又把不同的功能模塊儘量分開,把每個模塊變成單一的功能,這樣就可以複雜性降到最低了。
       目前大體分爲:加載程序,DLL管理模塊,引擎管理模塊,UI模塊,渲染模塊,文件管理模塊,遊戲邏輯功能模塊,遊戲AI功能模塊。以後想到的模塊再添加也是可以的,因爲都基於接口的方式實現,每個DLL都有自己的接口。
       下面來說明這些模塊的作用:
l         加載程序
這個模塊主要是實現遊戲目錄的重定位,或者一些其它的初始化工作。
l         DLL管理模塊
這個模塊主要實現所有DLL加載,創建對象,它就是所有DLL對象工廠,由它來創建所有對象,並且負責刪除所有對象。
l         引擎管理模塊
這個模塊主要把其它各個模塊組合在一起,並且進行遊戲狀態機更新和維護,還有消息處理,窗口維護,輸入控制並把當前控制消息傳給遊戲邏輯模塊。
l         UI模塊
這個模塊主要實現窗口的UI配置,比如創建新遊戲,參數配置等。
l         渲染模塊
這個主要在3D API之上實現更好用的Render功能,當然在這個模塊裏分成DX7,DX8,DX9等等的DLL,以便實現遊戲可以在不同的平臺上運行,這裏的平臺差別主要指顯示卡的差別,因爲不同的DX顯示卡,使用不同的加速功能。有用戶有錢就可以買最好的DX9顯卡,沒有多少錢的也許就是DX8的顯卡。但總不能把遊戲寫成DX8的標準方式,因爲買DX9顯卡的用戶肯定想:我花了那麼多錢,還玩這破遊戲。
l         文件管理模塊
這個主要實現資源的加載和管理,比如基於MDL,或者DX的X文件格式。同時也可以進行遊戲截圖保存等等功能。
l         遊戲邏輯功能模塊
這個是不同的遊戲產品,肯定不同的,比如基於FPS的遊戲和RPG的遊戲就不一樣的遊戲邏輯。因此這裏主要進行遊戲具體實現的功能,比如人物角色怎麼樣在地圖裏行走。
l         遊戲AI功能模塊
這個功能主要實現AI部份,比如尋路算法,NPC的控制。
目前,又想到這麼多了,更多的東西還要更深入地去分析和設計,更加需要實踐。
 

 3D遊戲引擎設計與實現(3)
3D遊戲引擎設計與實現(3)
       經過幾天編寫,3D遊戲引擎的架構代碼大體架構已經搭好。
       下面來每個模塊說明:
l         加載程序
Engine/MM3DMain.exe
l         DLL管理模塊
Engine/bin/MM3DRun.dll
l         引擎管理模塊
Engine/bin/MM3DEngine.dll
l         UI模塊
Engine/bin/MM3DGameUI.dll
l         渲染模塊
Engine/bin/MM3DRender.dll
l         文件管理模塊
Engine/bin/MM3DFileSystem.dll
l         遊戲邏輯功能模塊
Engine/bin/MM3DGame.dll
l         遊戲AI功能模塊
Engine/bin/MM3DGameAI.dll
上面就是每個模塊的DLL,分別實現相應的功能和接口,所有DLL都是通過接口來實現對外功能。已經可以讓程序運行起來,創建了基於窗口的模式。

 3D遊戲引擎設計與實現(4)
已經把每個DLL的架構已經搞好,還把接口也定義了相應部份,目前這個程序已經可以運行,那麼怎麼樣進行下一步設計呢?
我是先把所有消息循環寫好,然後創建窗口,就基於寫好主體程序,接着就要寫相應DirectX初始化部份,就是要寫MM3DRenderDX9.dll模塊.
就是用它來封裝所有DX接口,並提供給引擎管理模塊使用,當然,還要給UI部份使用.
接着下來,就是實現UI部份DLL.它是通紋理來實現一個3D對話框.
好了,今天就寫到這裏,繼續寫代碼.....................................


 3D遊戲引擎設計與實現(5)
        今天終於實現了UI的顯示,但還是比較初步的,已經可以顯示按鈕在窗口上,還沒有添加事件響應,不過也會很快實現的.到此,基本上UI方面沒有什麼大的問題,還要解決輸入法方面問題,因爲在遊戲中可能要輸入中文,讓所有遊戲玩家可以相互聊天.
        接着下來,就是全部寫UI部份,然後再寫好窗口模式和全屏模式的相互轉換,還要檢查設備是否丟失等等.在寫查找3D設備顯示模式時的代碼,還是非常的傍大.經過一個晚上不斷地努力,總算實現出來了.
        到目前爲止,這個3D引擎可以顯示基於紋理的UI.還有很多東西在後面,還需要不斷地努力.


 3D遊戲引擎設計與實現(6)
今天又有一點進展,主要實現UI的消息處理。因爲每個UI界面上的控件,比如按鈕都自己實現消息處理。鼠標消息、鍵盤消息等等,非常之多。所以目前的工作主要在GameUI模塊,目前實現的漸漸顯示出來效果,還是不大好看,等以後有時間再重新考慮改進。

 3D遊戲引擎設計與實現(7)
3D遊戲引擎設計與實現(7)
       昨天在調試代碼時,發現大量佔用CPU資源,不知那裏出什麼問題,這個可以真是無從下手,正在苦惱時,突現發現,爲什麼不用幀速率來看看顯示了多少幀。接着下來就添加幀速率上去,在調試時輸出,發現每秒鐘只有2到5幀,爲什麼會這麼少的呢?又要從哪裏下手去找出爲什麼這麼慢的原因。只能用最笨的辦法了,首先查看設備類型,因爲它決定主要因素。接着去創建D3D設備的函數裏調試,發現創建設備類型的參數是REF,就是使用標準設備,用軟件模擬的,心裏想:不慢纔怪呢。所有東西都是用軟件實現。原因肯定是在這裏了,接着就跟蹤爲什麼不能創建HAL類型的設備。最後找到了原因,就改正過來,結果顯示到60多幀了。總算解決了一個問題。
       在調試窗口與全屏模式時,也經常出現調試程序和VC死鎖問題,看來這種切換是不能單步調試,只能寫LOG實現調試了。
   
 3D遊戲引擎設計與實現(8)
3D遊戲引擎設計與實現(8)
       昨天主要進行窗口模式切換到全屏模式的編寫,這裏的代碼也非常的多,很多地方都要注意,很多細節都要處理,否則就可能程序死在那裏,或者全屏模式時轉換不到窗口模式,又或者當用戶改變屏幕分辯率,這時如果沒有改變窗口的模式的話,又會出現錯誤。還有一種情況,當切換失敗時,又要儘量回退到原來顯示參數的模式等等。這個功能實現,幾乎就把DX的初始化功能基本上完成了。當然,當窗口改變大小,D3D的設備也要跟着改變。還要不斷地調試才能完成這部份的功能。Coding................

 3D遊戲引擎設計與實現(9)
 
       昨天還是進行窗口模式與全屏模式相互切換的代碼工作,還有調試。不斷地寫LOG,不斷跟蹤,排除了一個又一個BUG後,總算可以自由地切換窗口模式與全屏模式。在這個過程中,不知道死了多少次VC,還好Windows2000的死進程管理能力還不錯,還是沒有要按下電源的鍵。當從全屏模式切換到窗口模式時,一定不要進行單步調試,否則就要死在那裏。不過也沒有辦法,死幾回還是需要的。這樣慢慢地改進,就可以從全屏切換到窗口模式。
       這個功能總算實現了,後面接着又寫當窗口改變大小的處理代碼,因爲所有的UI,在窗口方式中處理時,都跟窗口大小有關係。繼續Coding..................

 3D遊戲引擎設計與實現(10)
    經這幾天的努力,已經把UI,D3D設備管理完成了,接着要開始寫其它部份。要寫哪部份才更好呢?我想肯定是先考慮怎麼樣渲染世界裏所有的物品。要渲染物品得確定使用什麼模型文件。現在可以選擇的有好幾種格式,第一種最方便的,應是用X的文件格式,因爲D3D已經把它完全封裝好。第二種是使用MDL文件格式,就是HL的格式。第三種就是QUAKE3使用MD3的格式。其實每種格式都有自己的優點和缺點,就看着自己喜歡用那種格式,看起來還是比較難選擇的。
    經過不斷地考慮,想試着使用MDL的文件格式。因爲我沒有美工,至少可以拿當前的CS的資源來實現一下,比較現實一點。   
    目前暫時不考慮加載的資源的內存管理方面,先實現加載模式文件作爲第一步,然後再考慮怎麼樣顯示這些物體在場境裏。說到場境,主要分爲兩大類:室內和室外。每種場境都要分開來實現,室內場境比較好實現,因爲就是在一個四方體的盒裏,粘貼上不同的紋理來實現。室外的就比較麻煩,因爲要有天空,樹木,花草以及地表。
    今天身體不大舒服,有點發熱,可能要過幾天才寫這個了。
 3D遊戲引擎設計與實現(11)
3D遊戲引擎設計與實現(11)
       已經到開始考慮怎麼樣去渲染場境,因爲遊戲裏主要部份就是由場境組成,然後再添加各種人物在裏面,因此就要思考怎麼樣保存場境,3D引擎怎麼樣加載它。現在爲了用到CS的資源,當然要用它的地圖文件,纔可以更加方面。到目前,就決定使用BSP的地圖文件格式,這種文件格式比較複雜,保存的數據也比較多。
       接着下來的,就是實現怎麼樣讀取BSP文件格式,然後把它渲染到D3D設備裏,所以要在MM3DFileSystem.dll裏添加所讀取BSP文件的代碼。

 3D遊戲引擎設計與實現(12)
3D遊戲引擎設計與實現(12)
       遊戲的地圖文件格式是非常重要的一種格式,設計得好與壞,都關係到讀寫和渲染速度。如果保存的信息過少,就會導致渲染時花費大量的時間在計算。就目前主流的3D遊戲,都會用這種思想:就是能預先計算的東西,就要先計好,不是在遊戲中實現計算。比如用BSP樹來保存衝突檢測,保存可見性等,都是爲了提高渲染速度。
       在CS的BSP文件格式中也是這樣的,先計算好所有場境的BSP數據,這樣就可以快速渲染。起先我還不知道什麼叫BSP,就得趕緊去學習什麼叫BSP。看看那本計算機圖形學原理的書,原來只是用來保存面的可見性。BSP就是Binary Space Partition(ing)。這個文件裏除了保存BSP樹的數據外,還有使用到的紋理信息,模型信息等。
 3D遊戲引擎設計與實現(13)
3D遊戲引擎設計與實現(13)
       繼續寫讀取地圖文件格式的代碼,因爲這裏保存了很多信息。又沒有什麼好文檔,只好慢慢來找出BSP文件有用的信息,比如頂點,紋理座標等。先讀取顯示場境裏所有頂點數擾,平面方程數據,多邊形的邊數據,然後就可以構造自己的世界裏的平面了。目前還沒有加載紋理進來。Coding......


 3D遊戲引擎設計與實現(14)
    今天沒有寫什麼代碼,主要看看地勢生成算法。這個算法叫做Real-Time Optimal Adapting Mesh。它的思想就利用等邊直角三角形可以無限分成兩個等邊直角三角形來表示地勢的細節程度。如果要表示高細節的地表,就可以用分解成更多的直角三角形,如果表示不要求那麼多的細節,着重於在速度,就可以分解三等邊直角三角形少一點。
這個算法就稱爲ROAM算法。
 3D遊戲引擎設計與實現(15)
    今天在寫遊戲邏輯部份的代碼,主要實現遊戲邏輯的實現,比如世界的場境是怎麼樣渲染,當然這些都是按照地圖文件裏定義,根據BSP樹保存着的信息,就可以渲染場境出來.這樣就可把需要的模型加載進來,每當玩家改變輸入裝態時,就會作出來不同的響應.比如行走系統,就是當玩家按下不同的方向時,就可以按着一定的速度向前移動,這裏的移動,就是通過向量相加實現.當改變方向,就是繞着不同的軸進行旋轉.
    同時,我在MM3DGame模塊里加入渲染接口,讓這裏可以隨便實現渲染.這裏有很多問題要考濾,比如使用頂點緩衝區的方式,可以直接使用,或者使用頂點緩衝索引也可以.繼續Coding.....

 

發佈了2 篇原創文章 · 獲贊 13 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章