基于視錐體(平截體)的OpenGL ES性能優(yōu)化

教程

OpenGLES入門教程1-Tutorial01-GLKit
OpenGLES入門教程2-Tutorial02-shader入門
OpenGLES入門教程3-Tutorial03-三維變換
OpenGLES入門教程4-Tutorial04-GLKit進(jìn)階
OpenGLES進(jìn)階教程1-Tutorial05-地球月亮
OpenGLES進(jìn)階教程2-Tutorial06-光線
OpenGLES進(jìn)階教程3-Tutorial07-粒子效果
OpenGLES進(jìn)階教程4-Tutorial08-幀緩存
OpenGLES進(jìn)階教程5-Tutorial09-碰碰車
這一次的是性能優(yōu)化签赃。

概要

渲染的優(yōu)化不是僅僅提高渲染的速度躬厌,超過(guò)60Hz的渲染速度沒有任何意義拓诸,用戶永遠(yuǎn)看不到這些信息。同時(shí)在考慮用電消耗的情況下滔蝉,30Hz的刷新率能延長(zhǎng)電池的使用時(shí)間析蝴。
以下的渲染優(yōu)化策略總是管用的:

  • 減少I/O
  • 渲染更少的幾何對(duì)象
  • 減少內(nèi)存訪問

效果展示

核心思路

通過(guò)減少渲染的幾何對(duì)象禁漓,在不影響顯示效果的前提下是目,盡可能減少需要繪制的圖元。
在一個(gè)場(chǎng)景中年枕,很多物體是處于平截體外部炫欺,這些物體是用戶永遠(yuǎn)看不到的對(duì)象。

具體細(xì)節(jié)

a.測(cè)試點(diǎn)是否在平截體內(nèi)

計(jì)算眼睛到當(dāng)前測(cè)試點(diǎn)的向量熏兄,提取這個(gè)向量關(guān)于平截體X品洛、Y、Z軸的分量摩桶,分別進(jìn)行判斷桥状。


  • 1、計(jì)算眼睛到當(dāng)前測(cè)試點(diǎn)的向量硝清。
    // eye到point的向量
    const GLKVector3 eyeToPoint = GLKVector3Subtract(frustumPtr->eyePosition, point);
  • 2辅斟、測(cè)試Z軸分量,這個(gè)分量要在區(qū)間[nearDistance, farDistance]芦拿。如果是士飒,繼續(xù)步驟3挽霉。
    // z軸分量
    const GLfloat pointZComponent = GLKVector3DotProduct(eyeToPoint, frustumPtr->zUnitVector);
    
    if(pointZComponent > frustumPtr->farDistance || pointZComponent < frustumPtr->nearDistance)
    {
        result = AGLKFrustumOut;
    }
  • 3、Y軸分量要小于被測(cè)點(diǎn)所在的平截體高度变汪,高度的可以通過(guò)Z軸分量*視角/2的正切值計(jì)算。如果在區(qū)間內(nèi)蚁趁,繼續(xù)步驟4裙盾。
        // y軸分量
        const GLfloat pointYComponent =
        GLKVector3DotProduct(eyeToPoint,
                             frustumPtr->yUnitVector);
        const GLfloat frustumHeightAtZ = pointZComponent * frustumPtr->tangentOfHalfFieldOfView;
        
        if(pointYComponent > frustumHeightAtZ || pointYComponent < -frustumHeightAtZ)
        {
            result = AGLKFrustumOut;
        }
  • 4、X軸分量要小于被測(cè)點(diǎn)鎖在的平截體的寬度他嫡,寬度可以通過(guò)平截體高度值 * 寬高比番官。
          //X軸分量
            const GLfloat pointXComponent =
            GLKVector3DotProduct(eyeToPoint,
                                 frustumPtr->xUnitVector);
            const GLfloat frustumWidthAtZ = frustumHeightAtZ *
            frustumPtr->aspectRatio;
            
            if(pointXComponent > frustumWidthAtZ ||
               pointXComponent < -frustumWidthAtZ)
            {
                result = AGLKFrustumOut;
            }

b.判斷球體是否在平截體內(nèi)

測(cè)試球體會(huì)測(cè)試點(diǎn)更復(fù)雜,同樣是對(duì)比X/Y/Z軸分量钢属,在判斷的范圍加上半徑的距離徘熔。
但是,考慮下面的情況


按照上面的判斷淆党,球體是在平截體之外酷师,但是實(shí)際上是相交的。
解決方案

把半徑乘以特定的因子染乌。

如下圖山孔,考慮球體被外切情況,得出相應(yīng)的放大因子荷憋。


  • 1台颠、Y軸因子
sphereFactorY = 1.0f/cosf(halfFieldOfViewRad);
  • 2、X軸因子
    const GLfloat angleX = atanf(frustumPtr->tangentOfHalfFieldOfView * aspectRatio);
    frustumPtr->sphereFactorX = 1.0f/cosf(angleX);

擴(kuò)展

  • 場(chǎng)景圖(scene graph)輔助剔除
    用樹形數(shù)據(jù)結(jié)的幾何對(duì)象層次組織勒庄。樹形結(jié)構(gòu)有一個(gè)根元素串前。根元素是子元素的父,子元素可能是其他元素的父实蔽。參考Cocoa的視圖層次結(jié)構(gòu)荡碾,2DUIView實(shí)例的場(chǎng)景圖。同樣的概念也使用與3D對(duì)象的層次結(jié)構(gòu)局装。如果父元素在平截體外部玩荠,根據(jù)定義所有它的子元素也在平截體外部,沒有必要再單獨(dú)測(cè)試每個(gè)子元素贼邓。
    關(guān)鍵詞:Ochre 八叉樹阶冈。

  • 減少緩存復(fù)制
    為GPU提供一個(gè)頂點(diǎn)屬性緩存后,用CPU處理另一個(gè)塑径。在所有渲染指令發(fā)送完后女坑,通過(guò)glBindBuffer()函數(shù)來(lái)切換緩存。(蘋果公司官網(wǎng)有例子统舀,OpenGLESApplicationDesign.html)

  • 減少狀態(tài)變換
    OpenGL ES上下文存儲(chǔ)了大量的用于控制渲染運(yùn)算的信息匆骗。信息緩存可能在CPU控制的內(nèi)存劳景,也可能在GPU的寄存器。
    調(diào)用glEnable(GL_DEPTH_TEST)多次會(huì)浪費(fèi)時(shí)間更新上下文的狀態(tài)碉就,即使值是相同的盟广。

  • OES
    OES擴(kuò)展是OpenGL ES標(biāo)準(zhǔn)的維護(hù)者,提出的一個(gè)非標(biāo)準(zhǔn)的擴(kuò)展瓮钥。

思考

為什么FPS會(huì)在20FPS和30FPS之間擺動(dòng)筋量?
繪制 和 顯示 并不一樣。
通過(guò)CADisplayLink(hardware generated)碉熄,繪制的速率可能是60FPS桨武。
如果繪制的時(shí)間超過(guò)1/60s,理論上幀率最多為30FPS锈津。
想象一條1s的線段呀酸,分隔成60小段,每個(gè)小段的起點(diǎn)都可以作為繪制的起點(diǎn)琼梆。
如果繪制的時(shí)間超過(guò)1/60s性誉,那么繪制的終點(diǎn)會(huì)延伸到第二個(gè)小段。
這樣茎杂,一條1s的線段艾栋,最多有30個(gè)繪制的時(shí)間段忍法。

Since CADisplayLink is hardware generated the only thing you can do with it is divide the time, that's what the frameInterval is there to do.
frameInterval = 1 gets you 60 fps
frameInterval = 2 gets you 30 fps
frameInterval = 3 gets you 20 fps
I use a lot frameInterval = 5 for menus for example, it still gives me 12fps (about the minimum for reasonable simple animation) and the battery consumption reduces drastically.

你能得到FPS阅懦,但是它不代表真正的性能,每幀持續(xù)時(shí)間是一個(gè)更佳選擇掏击。FPS不能線性評(píng)判性能表現(xiàn)携冤。

For example, if your FPS goes from 30 to 20, then that's a pretty significant decrease in frame performance time (33 ms to 50 ms)
However if your FPS goes from 2000 to 400, that's a miniscule difference in real time (only 2ms difference).

最后悼粮,即使你自己通過(guò)自定義線程(不采用CADisplayLink),把繪制時(shí)間的空缺填補(bǔ)曾棕,實(shí)際上繪制的速率并不會(huì)變快扣猫。

總結(jié)

主要講解的是數(shù)學(xué)部分的知識(shí),OpenGL ES的部分沒有引入新的技術(shù)點(diǎn)翘地。
工作原因申尤,以后更新會(huì)慢一些。能看到這里衙耕,你也是喜歡技術(shù)的昧穿,謝謝支持。來(lái)一波關(guān)注和喜歡如何 -> 我會(huì)加油更新橙喘。
附上源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末时鸵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饰潜,老刑警劉巖初坠,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異彭雾,居然都是意外死亡碟刺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門薯酝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)半沽,“玉大人,你說(shuō)我怎么就攤上這事蜜托。” “怎么了霉赡?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵橄务,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我穴亏,道長(zhǎng)蜂挪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任嗓化,我火速辦了婚禮棠涮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刺覆。我一直安慰自己严肪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布谦屑。 她就那樣靜靜地躺著驳糯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪氢橙。 梳的紋絲不亂的頭發(fā)上酝枢,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音悍手,去河邊找鬼帘睦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坦康,可吹牛的內(nèi)容都是我干的竣付。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滞欠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼卑笨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起仑撞,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赤兴,失蹤者是張志新(化名)和其女友劉穎妖滔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桶良,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡座舍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陨帆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曲秉。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖疲牵,靈堂內(nèi)的尸體忽然破棺而出承二,到底是詐尸還是另有隱情,我是刑警寧澤纲爸,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布亥鸠,位于F島的核電站,受9級(jí)特大地震影響识啦,放射性物質(zhì)發(fā)生泄漏负蚊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一颓哮、第九天 我趴在偏房一處隱蔽的房頂上張望家妆。 院中可真熱鬧,春花似錦冕茅、人聲如沸伤极。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)塑荒。三九已至,卻和暖如春姜挺,著一層夾襖步出監(jiān)牢的瞬間齿税,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工炊豪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凌箕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓词渤,卻偏偏與公主長(zhǎng)得像牵舱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缺虐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容