2010-07-11 81 views
16

我已經開始一個新的遊戲項目,並決定學習和使用OpenGL(項目正在Windows和Linux上同時開發)。同時,我也對測試驅動開發非常感興趣,並且正在盡我所能編寫我的單元測試,以在任何實際代碼之前領導設計。然而,我認爲我缺乏知識可能會使我絆倒,並且在試圖爲代碼庫的「渲染」部分編寫單元測試時不斷碰壁。我希望有人能夠給我一些關於如何繼續的見解。在練習TDD(單元測試)時學習OpenGL

我知道我需要單元測試與OpenGL的交互,而不是OpenGL本身。我能看到的唯一方法是通過攔截OpenGL函數調用或創建一個全新的類接口,從某種程度上將OpenGL從其他代碼中抽離出來,從而允許我創建該類的模擬版本爲測試。 (更好的辦法是將它們抽象爲一組獨立命名空間中的非類函數,而不是虛擬類抽象,但我不明白我該如何嘲笑它。)

但是,因爲我還在學習OpenGL,我只知道抽象應該是什麼樣子。例如,我應該包裝每個OpenGL調用,還是根據要完成的任務將它們分組爲更高級的函數?薄包裝只會調用一個特定的OpenGL函數,所以我不需要事先對它們進行測試,但是我最終可能會包含大量的函數。然後,如果我以另一種方式走得太遠,並按任務將多個OpenGL調用分組在一起,我覺得最終會在我開始的地方結束,使用OpenGL的大量代碼本身需要在使用之前進行測試。

中間地帶在哪裏?如何在學習使用OpenGL的同時進行適當的單元測試?

回答

7

正確地測試渲染是不值得的。但是,您仍然可以在設計應用程序時使用TDD。

Here's a great article關於TDD,遊戲和OpenGL。

2

我建議製作一個小原型或其他一些小型項目,並與opengl一起玩耍。這會讓你對它有所瞭解。完成之後,使用tdd構建應用程序應該會容易得多。而你卻發現你需要模擬opengl而不是測試opengl。

0

看看What is the best way to debug OpenGL?;在這個問題的答案中提到的工具將使某種形式的測試成爲可能,特別是GLIntercept(一個OpenGL函數調用攔截器)聽起來像是一個非常有趣的選項/起點,以供進一步調查。

3

您不能自動測試渲染部分。爲此,你需要一個能夠看到和識別圖像的有情感的人。電腦沒有資格。

您可以自動測試成功創建資源 - VBO,紋理,着色器,顯示列表 - 您可以爲編譯錯誤單元測試着色器,測試數學庫,可以檢測OpenGL錯誤,但無法測試渲染部分。你可以做的最好的事情就是做一些測試例程來渲染一張圖片(可能是動畫和互動)並詢問它是否看起來是正確的。測試不會100%可靠 - 可能在一個硬件上工作,而不是在其他硬件上,人可能會錯過一個錯誤等。

例如,將我包裹OpenGL的每一個電話,

不,這是不值得的。

或根據要完成的任務將它們分組爲更高級別的功能?

這是有道理的寫了幾個電話/班創作的「紋理」,「網格」,「着色器程序」,使某種自動方式爲獲得均勻的位置(如果你使用的着色器),也許一些用於自動釋放OpenGL資源的類(即使用glDelete ***或使用glIsTexture之類的函數),但這是全部。通常情況下,你不應該引入額外的抽象/類,除非他們需要 - 因爲這將是額外的工作,沒有收益。

3

像對待數據庫一樣對待OpenGL。我最初會用一個界面開始。隨着時間的推移和添加更多方法,您可以開始將單個界面分解爲多個界面。

如前所述,您不能使用標準TDD庫來測試渲染。但這是可能的。想一想就像在Web客戶端測試HTML的呈現一樣。在編寫我的HTML時,我不使用TDD Firefox或Internet Explorer。

1

很多人似乎認爲圖形不受傳統TDD /單元測試的影響。這是不正確的。

圍繞TDD的問題是,圖像不會總是正好是一樣的。比如抗鋸齒設置(可以被驅動程序設置覆蓋)。不同GPU之間渲染同一圖像的差異(多邊形展開順序等)。同樣,當你的遊戲經歷發展時,像網格和紋理可能會改變或調整。

也有人認爲你經常需要做它,並在看到它之前,眼球的結果,如果它確定,然後將其添加爲通過測試用例(這將由於上述問題將打破)。

你可以將所有的OpenGL調用與日誌記錄包裝在一起,並確保所有的東西都按預期調用,但是這並不測試圖形實際上是否有效,它只是測試你的程序正在調用你預測它應該使。這不是非常有用,而且會有相當多的工作。此外,如果您需要優化不必要的繪圖調用等操作,將會很難維護。

我建議做的是將您的渲染輸出與窗口系統分離。我的意思是'Render to Texture'或使用FrameBuffer對象。這也有助於實現諸如視口和UI/HUD疊加等功能。

製作一個'窗口'對象。使用Qt,SDL,SFML,GLUT或其他方式打開實際桌面窗口的東西。並將某種渲染器傳遞給它。你可以做一些事情,比如允許多個渲染器並指定矩形座標(你可以在屏幕的角落渲染不同的視圖)。或者可以創建一個主渲染器,但可以繼承允許其擁有子渲染器的版本。 Window對象也可以處理輸入,這提供了一個注入假/模擬輸入對象的好方法,您可以測試玩家是否按預期向前移動。

這種模塊化方法就是那種不屬於TDD的東西,它也可以讓你的渲染器擁有自己的渲染器(也許你想單獨做一個天空盒,或者在遊戲中安全監視器上的圖片,反射,shadowmaps等)。您還可以輕鬆地以不同的分辨率渲染原生桌面(這對於在TDD中設置固定分辨率非常有用,對於簡單操作可能只是32x32之類的東西,但對於分辨率固定的Android等設備也很有用) GPU具有不同的功能,Nexus 10不足以讓你的遊戲在其XDPI上呈現出來嗎?縮小尺寸也有助於Linux/Xorg,它並不總能讓你設置GPU的所有分辨率,儘管現在這個問題不大)。

一旦你有了你的FBO,做一些函數來查詢像素顏色。然後你可以查詢你所有的基本操作。你的網格物體是否正確渲染?測試它。用一個白色的三角形做網格,並查詢你希望看到哪些位置是白色的,以及繪製該三角形時應該保持黑色。 1x1窗口中的1x1三角形應該覆蓋%50對角線,因此測試像素靠近邊緣和中間的兩側,窗口邊界和尖角位。接下來combine two triangles into a rectangle它應該填滿屏幕,現在所有的像素都應該是白色的。現在嘗試將它從相機移開,並檢查邊框是黑色的,但中心是白色的,1.0x1.0窗口中的1.0x1.0矩形位於1.0處,您可以應用一些簡單的幾何圖形來近似查看邊框的位置應該結束。 Test with a different color。用多色立方體制作更復雜的網格並測試旋轉。製作測試法線貼圖。

您可能可以通過渲染一個球體來檢測燈光,並檢查左側的光線是否比右側亮,如果在另一側添加另一個燈光,它們大致相同(只需將所有像素添加到左側和右側的所有像素,並在誤差範圍內進行比較)。增加光線亮度並查看像素總和是否增加。您可以通過在平面上的特定點處計算預期顏色來測試照明算法。 您可以看到,光譜突出顯示在預期區域最亮。爲您的正常/凹凸映射make a test texture

只是爲了避免任何真正具體的東西,例如,不要在邊緣完全測試。他們可能會反抗或輕微關閉。如果您正在測試照明的左/右亮度,不要指望像素數量在不同系統或甚至兩側(在對稱場景中)都是相同的數字,請使用誤差範圍。不要使用真實數據,請確保使用不會更改的基本「測試」紋理和網格。