對着色器代碼與紋理圖優化的一些體會

        在以前的項目中寫了這麼多着色器,以及最近看一些書籍,對着色器的優化有了一些自己的體會,在這裏總結一下。

        一.儘量將複雜的計算放在頂點着色器中計算:

        頂點着色器在渲染過程中對物體的每個頂點執行一次,片元着色器則對每一片元執行一次,也就是對頂點構成的面進行插值(也就是求出漸變的值),所以在繪製一個物體時頂點着色器繪製2千次,片元着色器可能就會執行幾萬次,這樣極大地提高了執行效率,但是視覺效果上肯定沒有沒有對每個片元進行操作來得好。

        二.在使用函數時的優化:

        這裏主要指的是三方面的優化

        1:重複計算的部分提前計算好並扒出來放着,從而簡化等式提高執行效率,比如說:p = sqrt(2*(X+1))可以改寫成1.414*sqrt(X+1)等。

                                                        

        2:儘量使用着色器內建函數,例如在比較大小時不需要自己寫判斷,直接使用使用max(a,b),在需要計算點乘時使用dot(a,b);這些函數大部分都是硬件實現的,開發時可以直接利用,能夠降低代碼的複雜度,優化計算速度。 這些函數在我另一篇文章裏有轉載:http://blog.csdn.net/srk19960903/article/details/74034721

                                                         

       3:編寫着色代碼的過程中,有時候需要進行一些簡單的計算,對於這些重複性較低的操作,而且計算的內容較爲簡單,開發過程中不應該將這種計算封裝成函數,直接用代碼計算即可。這樣能大大減少GPU函數調用與返回的消耗。

        三.關於discard:

        discard(丟棄片元)該方法的目的是當滿足某條件時將片元丟棄。該操作很耗費資源,其目的大部分也就是讓該片元不再顯示,所以當不需要該片元時直接將其alpha值設爲0或是不做任何處理就可以實現該目標。

        四.着色器中儘量使用順序結構替代分支結構

        着色器是在GPU中執行,GPU與CPU在硬件結構上有很大的差異,其執行分支語句的效率非常低。故在GPU中需要執行分支語句時往往需要想辦法用內建的函數計算出因子,再結合數學表達式來替代分支操作,下面給出一個實際操作的例子:

       1.直觀的易於編寫的用分支語句完成的代碼

       vec4projColor=texture(sTexture,vec2(s,t));

       if(a>0.9999){

                fragColor=colorA;

       }elseif(a<0.0001){

                fragColor=colorB;

       }else{

                fragColor=mix(colorB,colorA,smoothstep(0.0,1.0,projColor.r));

       }

     2.適合提高GPU執行效率的使用內建函數替代分支操作的代碼

     vec4 projColor=texture(sTexture,vec2(s,t));

     floata=step(0.9999,projColor.r);

     floatb=step(0.0001,projColor.r);

     floatc=1.0-sign(a);

     fragColor=a*colorA+(1.0-b)*colorB+b*c*mix(colorB,colorA,smoothstep(0.0,1.0,projColor.r));

        通過這個案例就可以體現出着色器優化的一個具體方法,不使用if語句轉而靈活的使用內建函數來使分支結構變爲順序結構,具體的方法是將條件分支中的“是”和“否”轉換成“1”和“0“”這兩個數字。通過內建函數step(a,b),當b<a是值爲0否則爲1,這樣就把分支沒有執行到的地方轉換成0的值順序執行下去了。

        五.紋理圖的優化

        1.紋理圖儘量使用2的n次方大小:這樣可以提高轉換效率,在一些情況下,不使用2的n次方大小的紋理圖可能會出現顯示不正確的情況,大部分情況下雖然能夠顯示正確,但是是因爲系統對其自動進行了轉換,影響了執行效率。

        2.將許多小的紋理拼成一個大的紋理:這樣驅動程序在加載紋理的時候,僅僅需要加載一次就可以了。例如,開發人體模型,可以將一個人的頭髮,臉,眼睛等組合爲一個紋理。

        3.在大場景貼圖:對其進行紋理採樣時要儘量使用mipmap,雖然這樣相對而言會佔用一些內存。但是,這樣會提高紋理採樣的效率,同時一般會得到更好的畫面效果。

        4.紋理採樣:進行紋理採樣時若最近點採樣就能滿足視覺效果的要求,就不要使用線性採樣。由於線性採樣算法比最近點採樣算法複雜很多,其執行效率要比最近點採樣低不少。(線性採樣需要將對每一個點進行插值計算)

        以上就是我自己開發經驗和閱讀一些書籍得到的關於着色器與紋理圖優化的知識,如有不對或是不準確的地方還望大家指正,共同進步。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章