OpenGL在MFC下的多視圖顯示在很多場合都能用到,而且表現力夠強。前段時間自己需要做一個類似於MAX之類的場景編輯工具,用來編輯自己正在做的FPS游戲中所需要的場景。由於自己不懂美工、不會用MAX,所以在學習MAX與做一個自己更容易操作的編輯器兩者間,就一直很糾結,最終還是選擇做一個自己的編輯器。現在看來這個選擇是明智的,因為用自己的編輯器來處理自己胡思亂想出來的場景時能更方便地與自己的游戲進行融合,對後期的工作帶來了很大的便利。
編輯器的顯示界面與MAX的類似,多個窗口分別顯示3D、前、側、俯四個投影視圖。在MFC中創建多個視圖就不用說了,初學MFC的都會搞。在創建完分割視圖、搭完程序的框架之後即需要將初圖與OpenGL進行關聯。我最初采用的方法也是很原始的那種:在整個程序中創建一個OpenGL的RC,然後在需要刷新視圖時將視圖的DC逐個與這個唯一存在的RC進行關聯,然後繪制,在繪制完之後再解除當前的關聯並與下一個視圖進行關聯……,如此循環。在這個過程中,不說繁瑣的關聯DC與RC的過程了,最要命的就是這個過程是灰常慢的,在實現時發現,對於當前的活動視圖刷新率還行,但對於其它的非活動視圖,那個刷新率就不能容忍了(這裡面可能是由於我最初的實現代碼有問題,按理說幾個視圖的刷新率應該差不多才對呀,是不?但即便這樣也還是很低),這樣很不爽,所以感覺有很必要大改,一查資料,發現這個是普遍問題,解決辦法就是多線程下的多初圖,於是就用多線程對自己的編輯器進行了大改。
整個程序以MainFrm為單位進各個子視圖進行管理,各個子視圖對應一個自己的渲染線程,每個線程裡邊有一個相互獨立的GL RC,這幾個RC之間的狀態不會相互影響,因此在繪制的時間各個視圖間也是相互獨立的。
在具體實現中用一個類似於如下的類來對RC及DC及其它相應的資源進行管理:
class CMultiThreadRCManager
{
private:
int m_viewNums;
HGLRC* m_hglRCList;
CDC** m_hDCList;
//…
//…
}
在實現過程中發現有如下一些問題需要特別注意:
1. 在線程中要注意資源的上鎖與解鎖,否則就會造成越界訪問,這是屬於多線程的相關內容,而且是很容易出bug的地方。
2. 在我的實現裡邊用MainFrm來作為所有操作的主體,用它來對視圖及相關的線程進行操作維護,感覺效果挺好。
3. 在視圖線程的主循環中加上一定的延時,Sleep(time),可使線程間的調度更加流暢,降低CPU的工作負載。
4. 使用臨界區來對線程間共享的資源進行管理時(我在實現時是利用臨界區進行資源管理),界區對象CCriticalSection應保證能被所有讀寫此資源的線程所訪問,否則不能起到資源臨界的作用。若有多個共享資源,最好對每個共享資源設置臨界區,可以線程之間進行更好的調度。
總之,OpenGL多線程的多視圖渲染最容易出現問題的地方就是多線程時的資源讀寫操作,如果這部分順利搞定,其他地方一般不會有什麼問題的。最終,我的程序跑起來了,在ATI3470上測試,對於四個視圖,每個視圖都能達到90幀以上的刷新率,效果還可以,能滿足自己丑陋的編輯器的需要了。
下圖為編輯器的一個截圖: