寫基於圖形API(如WebGL)的引擎主要考慮的設計因素有哪些?

比如Three.js, SceneJS, BabylonJS, 主要會考慮哪些設計要素,主要實現哪些功能?


我在一個創業公司寫webgl渲染引擎,公司的產品網址是http://www.modelo.io。

對於產品級的webgl引擎,首要考慮的因素並不是一堆渲染特效的堆積,而是分為應用場景設定,架構,易維護性,穩定性和對外介面這麼幾塊。

1. 應用場景指的是這個引擎具體是為什麼樣的產品服務,不同的產品對渲染的要求是不同。例如有些需要強跨平台,手機,平板,桌面都要適用,且表現結果差不多。所以這也是制約一些通用引擎往專業化產品化發展的最大障礙,例如three.js。即便為了加速產品開發,開始的時候基於這些通用引擎,到不了一年,這些通用引擎的代碼也慢慢被清除掉了。

2. 架構關鍵是清晰。總的來說一個層級架構就可以了,保證耦合性最低和封裝性最好。層級架構的層不要太多。不需要在一開始就定義一個終極的架構。這也不可能。應用需求在改變,架構總會跟進。

3. 易維護性就是對於創業公司來講,總是缺少文檔的。整個引擎的代碼庫要簡單明了,方便新來的同事上手。所以需要一個清晰的架構和盡量避免很fancy的coding技巧。此外,代碼風格要統一。

4. 穩定性就是在不同的平台上都能有相似的表現,雖然webgl天生有跨平台性,但是各種平台適配的坑還是需要時間來踩平。

5. 對外介面就是如何和前端對接,這個介面一定要清晰。為了做到這個,引擎和前端之間必然還有一個工具層,提供前端的需要的功能。

最後說說圖形相關的考慮,通用的部分我就不說了,例如場景樹,剔出,特效什麼的,因為任何一個引擎都一樣。我只講幾點webgl的特殊性。

1. 單線程,webgl只能在主線程渲染。如果代碼是cpu bound的,那麼需要考慮利用webworker來分擔cpu部分的計算量。modelo就大量使用了webworker,在資源載入的時候。

2. webgl1才是最通用的,webgl2因為蘋果不支持,所以現在還不能應用於產品。

3. 內存內存內存!因為瀏覽器是沙盒,無法精確的知道硬體配置和可用gpu內存,webgl程序非常容易因為資源消耗殆盡而crash。這個沒有特別好的解決辦法。


好久沒在知乎上認真寫答案了,剛好最近半年時間的主要工作就是基於WebGL的渲染引擎的開發,所以可以簡單分享我的看法。

首先想說的是引擎和圖形API的關係,圖形API相對於引擎來說是工具,所以說渲染引擎的核心不會是工具,而是如何用工具設計出相應的功能,因此我覺得API只需熟悉即可,熟悉的程度大致是了解每個API的功能,基本用法,並且對相應的開銷有一個大致的概念。至於細節可在用的時候查工具書或者文檔。譬如我現在基於WebGL2.0的標準開發,這部分的資料比較少,但可以大致對應到OpenGL ES3.0的API特性,因此可以基於OpenGL ES3去了解WebGL2,這裡推薦一本書:《OpenGL ES 3.0編程指南》,目前應該是第二版,作為工具書非常實用。

對API的學習和了解可以是漸進式的,核心還是在於圖形學的演算法和你在引擎開發之初希望你的引擎是什麼樣的,擁有什麼功能,核心優點是什麼,根據功能需求再去選取API加以利用,所以多讀圖形學相關的PAPER,關注SIGGRAPH,GDC這些圖形和遊戲的頂會是更為重要的事,通過實現功能去理解API的設計思路和用法,往往體會更深入。譬如在學習圖形之初,很多人都不理解Stencil Buffer,但是通過學習Shadow Volume的演算法,就能比較深入的理解它,再譬如glsl中的discard命令(hlsl的clip)可以通過了解alpha test來學習。實時圖形演算法幾乎都是基於現代的圖形API來實現的,而這些圖形API設計思路大同小異,通過了解這些演算法的實現,也就同時了解了相應API的用法。

不同引擎因為設計之初的需求不同,因此可能在功能的規划上也有區別,不過總體來說都會有一部分核心功能大家比較相似,另外的高級功能和定製功能可能會有較大差別。

核心功能部分大概包含了基本的場景概念,場景的層次結構,攝像機,場景的遍歷、剔除、光照、陰影、滑鼠拾取、動畫、材質系統、渲染結構的實現。

基本的場景管理部分是整個渲染數據架構的核心,一定程度決定了引擎渲染的方式,同時也很大程度決定了渲染在CPU端的提交效率,這部分可做的優化比較多,譬如用一些數據結構(BSP,OCTree)加速場景的遍歷,視錐剔除,遮擋剔除,LOD,材質排序等都能夠有效的提升引擎渲染效率,也是往往被忽略的部分,這部分在每年的相關會議上提的也比較少,葉老師翻譯的《遊戲引擎架構》和《3D Game Engine Design》裡面有涉及部分,GPU Gems中也有一些文章談及。

光照、陰影和渲染架構也是渲染引擎的核心功能,近年來延遲渲染(Deferred Rendering)是比較流行的渲染架構,在其基礎上衍生出了Tile Based Deferred Shading以及更進一步的Clustered Shading,如果基於前向渲染則可以考慮Forward+的技術;在光照模型方面,近年來大家已經不同程度趨向於基於物理的渲染(PBR),從2012年左右開始在各大會議上每年都有相關議題的分享;陰影也是非常重要的功能,主要的問題是陰影質量、軟陰影的模擬、多陰影的管理和陰影性能幾個方面,比較重要的幾個成果包括PSSM,SDSM(旨在提升陰影質量),Variance Shadow Map(旨在模擬軟陰影),《Real Time shadows》這本書對於陰影技術有一個詳細的匯總,至於多陰影和陰影性能方面,則需要通過閱讀一些商業引擎在陰影方面的具體實現來找到靈感,這裡推薦toughBro博客里的一篇導讀及其原文:[sig12]幾個AAA遊戲中的陰影技術;動畫部分也是較大的課題,不過每年也都有文章提及,內容較雜,比較重要的動畫類型包括骨骼動畫和Morph動畫,以及結合物理引擎的RagDoll(實際上也是骨骼動畫)。

高級功能
或許稱之為擴展功能更恰當,這部分功能並非必要,實現也依據引擎特點各有不同,主要是為渲染效果加分,用於渲染一些特殊的材質和效果或者後處理特效,比較重要的特殊材質包括半透明物體的渲染(depth peeling,alpha to coverage,per pixel linked list),水體的渲染(Simulating Ocean Water,Jerry Tessendorf;Real-time water rendering:Introducing the projected grid concept),皮膚的渲染(GPU Gems3,Advanced Techniques for Realistic Real-Time Skin Rendering),毛髮的渲染(GPU Gems2, Hair Animation and Rendering in the Nalu Demo;An Energy-Conserving Hair Reflectance Model),植被的渲染(GPU Gems3, Vegetation Procedural Animation and Shading in Crysis),天空的渲染(Precomputed Atmospheric Scattering;GPU Gems 2, Accurate Atmospheric Scattering),雲彩的渲染(The Real-time Volumetric
Cloudscapes of Horizon: Zero Dawn);此外還有一些常用的後處理特效(CryENGINE 3 Graphics Gems - Crytek),例如SSAO(HBAO,Alchemy AO, Scalable AO,SSDO),DOF,HDR(HDR the Bungie way, Uncharted2 HDR Lighting),Volumetric Light(GPU Pro 5, Volumetric Light Effects in Killzone Shadow Fall;Frostbite PB and unified volumetrics),Motion Blur(Next Generation Post Processing in Call of Duty Advanced Warfare),FXAA,Temporal AA等,這部分比較雜,需要根據自身引擎的特點、需求以及機能條件做靈活的選取,沒有一個統一的方案。

其它部分就是一些細節的優化了,這部分細節更多,零零星星也有一些資料,暫時就不贅述了。

以上大概是我能想到的一些內容,等有空的時候可以再整理文章的引用和資料補全。


看到這個。來強答一番。

首先圖形API只是提供給你使用機器的一種手段。而引擎則是一系列複雜功能的集合。引擎會在一定程度上使用圖形API,但絕不局限於此。

個人愚見引擎未必要特別複雜特別專業,但要遵從於其提供的功能和服務。一般的,引擎的功能必有三:

1、渲染架構。

2、渲染資源管理。

3、用戶介面。

其他所有現有制式引擎帶有的功能,比如物理動畫熱更編程腳本等等,都已經是引擎之上的附加功能。

考慮好自身能力和引擎面向的目標,設計重點會有所不同。

隨便舉例,如果是專業用來驗證渲染和物理演算,那麼對渲染架構的要求則會比較苛刻,更多的是考慮怎樣簡單清晰的組織物理演算法,怎樣提高並行運算效率和渲染效率等。相對場景資源管理和易用性要求會有所降低。 如果是在固定圖形效果下,實現場景的轉換,多變,模型渲染,布料渲染等等,那麼則需要在資源管理,對象生命周期管理,內存使用,公共緩存使用上面多下一些功夫。 如果是為了做給新手用,那麼可能需要有良好的圖形界面簡單的腳本豐富的附加功能等等。

總的來說,遵從自己需要功能,和自身能力,選擇不同偏重點設計合理合適的引擎即可。並不是非要將所有現有的和存在paper中的圖形演算法一次實現一遍做一個龐大的集合。當然,如果題主的目標是跟Unreal4剛正面的話,那麼就隨意了。


沒有唯一的標準,服務於應用場景更為重要。舉個粒子,我做的第一個webgl引擎的時候為了學習3D渲染,就把介面設計得比較「麻煩」,但是能在業務代碼中清晰地看出場景樹是如何搭建起來的,解說和閱讀起來特別方便。這也是一種合理的設計呀。


推薦閱讀:

如何看待武漢大學軟體工程國家重點實驗室因評估未通過遭摘牌?
如何評價中國大學軟體課程中對於流行技術(如Git)的忽視?
某211大學軟體工程專業在讀女生,喜歡平面設計嚮往設計師生活狀態,是否應該考慮轉行?
有些軟體更新只是更新部分文件(資源、DLL),為什麼不採用增量更新,而要採取全量更新?在設計軟體更新的時候,增量更新和全量更新是如何考慮的?
軟體上線後出現了重大bug,要軟體測試工程師負主要責任還是要開發人員負主要責任?那麼項目經理呢?

TAG:3D | 軟體工程 | WebGL | 計算機圖形學 |