opengl/webgl的性能優化是一個永遠的話題,涉及到的東西也不少,這裏對本身瞭解到的性能優化作個總結。web
1. 避免在shader中作邏輯判斷,好比if else。性能優化
有的人可能會很疑惑,爲什麼要這樣?這和GPU的基本調度有關係,GPU的基本調度單位叫作wavefront, 就是指一組徹底相同的計算指令,在GPU的幾個計算單元中並行執行,每個指令的輸入數據不一樣而已。這樣並行度很高,能夠極大程度提升性能。可是一旦引入if else,就會把wavefront破壞掉,好比如今有10個計算單元在併發執行,可是碰到if,在5個計算單元中爲true, 在5個計算單元中爲false, 這樣會形成新的計算指令,那麼以前的並行運算將沒法繼續。新的計算指令須要排隊等待執行,或者新的指令要轉移到新的計算單元上,這個過程涉及到數據的複製轉移,會比較耗時,會嚴重破壞並行度。併發
可是有些場景下,shader中徹底不用邏輯判斷又不行,那該如何呢?能夠考慮使用shader的內置函數,好比step函數,案例以下:函數
float a;性能
if(b >1){測試
a = 1;優化
}else{webgl
a = 0.5;線程
}orm
能夠優化爲:
float a;
float temp = step(b, 1);
a = temp * 0.5 + (1 - temp);
2. 減小三角形數量
較少三角形的數量大致上能夠從如下幾個角度入手:
(1). 空間分割技術:包括八叉樹,四叉樹作空間分割,將不在當前可視區域物體剔除掉
(2). 遮擋檢測技術:視錐體範圍內,有些物體會被前面的物體遮擋,這些被遮擋的物體實際上是不須要渲染的。遮擋查詢有多種技術方案實現,好比經過擴撲性,硬件遮擋查詢。擴撲性比較麻煩,我這裏推薦硬件遮擋查詢技術,實現起來相對比較容易。
(3). LOD技術:根據物體距離攝像頭的距離,動態調節物體三角形的數量。
(4). 圖元類型的優化:使用GL_TRIANGLE_FAN或者GL_TRIANGLE_STRIP替代GL_TRIANGLES,由於這樣能夠重用頂點,減小三角形的數量。
(5). 使用頂點索引的方法作渲染:使用glDrawElements替代glDrawArrays,由於前者經過索引的方式能夠減小三角形的數量。
3. 紋理的優化
(1). 紋理的長寬最好是2的冪。
(2). 紋理壓縮:紋理壓縮在opengl es 3.0和webgl 2.0上有比較好的支持,經壓縮後的紋理能夠減小圖形數據,節省寬帶。常見的壓縮格式爲ETC,Khronos公司提供有ETC格式壓縮的免費壓縮包,在opengl/webgl程序中使用glCompressedTexImage2D函數加載被壓縮的紋理。
(3). 紋理的上傳:傳統的紋理上傳比較耗時,能夠考慮使用兩個PBO上傳紋理,性能會有較大的提高。
(4). 紋理的合成:若是有不少個小的紋理,每個紋理單獨加載,效率比較低下。能夠考慮將多個小紋理合成到一個紋理上,僅僅加載一次,而後在程序中使用的時候,使用不一樣的紋理座標範圍來加載不一樣的紋理。
4. 減小系統內存向GPU內存傳送數據的次數
具體能夠從以下方面入手:
(1). 儘量使用VBO/VAO
(2). 在opengl es 3.0/webgl 2.0上能夠使用Transform Feedback, 該方案能夠使用GPU作通用運算,把計算的結果存入VBO中,在後期的渲染流程中使用該VBO做爲輸入。
(3). 批次合併:好比一個最小包圍體內有多個物體,能夠將這些物體的三角形合併在一塊兒,一次性的發送到GPU。
(4). 使用instance: 若是要渲染多個重複的物體,能夠使用instance特性。
5. 針對在複雜計算的優化:
(1). 使用延遲着色:針對在片斷着色器中有複雜計算,而且不少頂點不能經過深度測試的場景,延遲着色能夠很大程度上提升渲染性能。
(2). 開啓多個渲染線程: 每一個渲染線程的viewPort設置爲屏幕的一個區域,能夠充分利用CPU和GPU