OpenGL 隱藏面消除及混合

在繪制3D場景的時(shí)候,我們需要決定哪些部分是對(duì)觀察者可見,或者哪些部分是對(duì)觀察者不可見的。對(duì)于不可見的部分,就不應(yīng)該渲染。這種情況叫做隱藏面消除(Hidden surface elimination)。

  • 正背面剔除(Face Culling)

    • 默認(rèn)情況下,按照逆時(shí)針頂點(diǎn)連接順序的三角形面為正面

    • 默認(rèn)情況下,按照順時(shí)針頂點(diǎn)連接順序的三角形面為背面

    • 開啟正背面剔除(默認(rèn)背面剔除)

      void glEnable(GL_CULL_FACE)
      
    • 關(guān)閉表面剔除(默認(rèn)背面剔除)

      void glDisable(GL_CULL_FACE) 
      
    • 選擇剔除那個(gè)面

      void glCullFace(GLenum mode)
      mode參數(shù)為: GL_FRONT, GL_BACK, GL_FRONT_AND_BACK, 默認(rèn)GL_BACK
      
    • 指定繞序那個(gè)為正面

      void glFrontFace(GLenum mode)
      mode的參數(shù)為: GL_CW, GL_CCW, 默認(rèn)值: GL_CCW
      
  • 深度緩沖區(qū)

    • 專門存儲(chǔ)每個(gè)像素點(diǎn)的深度值,深度值越大,則離攝像機(jī)越遠(yuǎn)。
    • 在不使用深度測試的時(shí)候,如果我們先繪制一個(gè)距離比較近的物體,再繪制距離較遠(yuǎn)的物體,則距離遠(yuǎn)的物體因?yàn)楹罄L制而把距離近的物體覆蓋掉。有了深度緩沖區(qū)后,繪制物體的順序就不那么重要的。只要存在深度緩沖區(qū),OpenGL都會(huì)把像素的深度值寫入到緩沖區(qū)中。除非調(diào)用glDepthMask(GL_FALSE)來禁止寫入。
  • 深度測試

    • 深度緩沖區(qū)(DepthBuffer)和顏色緩沖區(qū)(ColorBuffer)是對(duì)應(yīng)的。

    • 在決定是否繪制一個(gè)物體表面時(shí),首先要將表面對(duì)應(yīng)的像素深度值與當(dāng)前深度緩沖區(qū)中的值進(jìn)行比較。如果大于深度緩沖區(qū)中的值,則丟棄這部分,否則利用這個(gè)像素對(duì)應(yīng)的深度值和顏色值分別更新深度緩沖區(qū)和顏色緩沖區(qū),這個(gè)過程稱為深度測試。

    • 深度值一般由16位、24位、32位值表示。通常是24位,位數(shù)越高,深度精確度更好。

    • 開啟深度測試

      glEnable(GL_DEPTH_TEST)
      
    • 清除深度緩沖區(qū)(默認(rèn)值為1.0,表示最大的深度值,深度值的范圍為[0, 1]之間,值越小表示越靠近觀察者,值越大表示越遠(yuǎn)離觀察者)

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
      
    • 深度測試判斷模式

      glDepthFunc(GLEnum mode)
      
      枚舉值 描述
      GL_NEVER 總是不能通過測試
      GL_ALWAYS 總是通過測試
      GL_LESS 當(dāng)前深度值 < 存儲(chǔ)的深度值時(shí)通過
      GL_LEQUAL 當(dāng)前深度值 <= 存儲(chǔ)的深度值時(shí)通過
      GL_EQUAL 當(dāng)前深度值 = 存儲(chǔ)的深度值時(shí)通過
      GL_GEQUAL 當(dāng)前深度值 >= 存儲(chǔ)的深度值時(shí)通過
      GL_GREATER 當(dāng)前深度值 > 存儲(chǔ)的深度值時(shí)通過
      GL_NOTEQUAL 當(dāng)前深度值 != 存儲(chǔ)的深度值時(shí)通過
    • 打開/阻斷 深度緩沖區(qū)寫入

      glDepthMask(GLboolean flag)
      flag: GL_TRUE 開啟深度緩沖區(qū)寫入,GL_FALSE 關(guān)閉深度緩沖區(qū)寫入
      
  • ZFighting閃爍問題

    • 由于深度緩沖區(qū)精度的限制,對(duì)于深度值相差非常小的情況,OpenGL就可能出現(xiàn)不能正確判斷兩者的深度值,就會(huì)導(dǎo)致深度測試的結(jié)果不可預(yù)測,顯示出來的現(xiàn)象就是交錯(cuò)閃爍兩個(gè)畫面。

    • 啟用 Polygon Offset(多邊形偏移),讓深度值之間產(chǎn)生間隔。

      glEnable(GL_POLYGON_OFFSET_FILL)
      
      參數(shù)列表:
      GL_POLYGON_OFFSET_POINT  對(duì)應(yīng)光柵化模式:GL_POINT
      GL_POLYGON_OFFSET_LINE   對(duì)應(yīng)光柵化模式:GL_LINE
      GL_POLYGON_OFFSET_FILL   對(duì)應(yīng)光柵化模式:GL_FILL
      
    • 指定偏移量

      glPolygonOffset(GLFloat factor, GLFloat units)
      
      應(yīng)用到片段上總偏移計(jì)算方程式:
      Depth Offset = (Dz * factor) + (r * units)
      Dz: 深度值
      r: 使得深度緩沖區(qū)產(chǎn)生變化的最小值
      
      可以設(shè)置factor和units為-1,-1。
      
    • 關(guān)閉 Polygon Offset

      glDisable(GL_POLYGON_OFFSET_FILL)
      
  • 裁剪

    • 用于渲染時(shí)限制繪制區(qū)域。

    • 開啟裁剪

      glEnable(GL_SCISSOR_TEST)
      
    • 關(guān)閉裁剪

      glDisable(GL_SCISSOR_TEST)
      
    • 指定裁剪窗口

      void glScissor(GLint x, GLint y, GLsize width, GLsize height)
      
    • 窗口、視口、裁剪區(qū)域

      • 窗口:顯示界面
      • 視口:窗口中用來顯示圖形的一塊矩形區(qū)域,它可以和窗口等大,也可以比窗口大或者小。只有繪制在視口區(qū)域中的圖形才能被顯示,如果圖形有一部分超出視口區(qū)域,那么那一部分是看不到的。通過glViewPort()函數(shù)設(shè)置。
      • 裁剪區(qū)域(平行投影):視口矩形區(qū)域的最小最大x坐標(biāo)(left, right)和最小最大y坐標(biāo)(bottom, top),而不是窗口的最小最大x坐標(biāo)和y坐標(biāo)。通過glOrtho()函數(shù)設(shè)置,這個(gè)函數(shù)還需指定最近最遠(yuǎn)z坐標(biāo),形成一個(gè)立體的裁剪區(qū)域。
    • 混合

      • 開啟混合

        glEnable(GL_BLEND)
        
      • 組合顏色
        目標(biāo)顏色:已經(jīng)存儲(chǔ)在顏色緩存區(qū)的顏色值
        源顏色:作為當(dāng)前渲染命令結(jié)果進(jìn)入顏色緩存區(qū)的顏色值
        在默認(rèn)情況下,混合方程式如下:

        Cf = (Cs * S) + (Cd * D)
        Cf: 結(jié)果顏色
        Cs: 源顏色
        Cd: 目標(biāo)顏色
        S: 源混合因子
        D: 目標(biāo)混合因子
        
      • 設(shè)置混合因子

        glBlendFunc(GLenum S, GLenum D)
        S: 源混合因子
        D: 目標(biāo)混合因子
        
        枚舉值 RGB混合因子 AlPha混合因子
        GL_ZERO (0,0,0) 0
        GL_ONE (1,1,1) 1
        GL_SRC_COLOR (Rs,Gs,Bs) As
        GL_ONE_MINUS_SRC_COLOR (1,1,1)-(Rs,Gs,Bs) 1-As
        GL_DST_COLOR (Rd,Gd,Bd) Ad
        GL_ONE_MINUS_DST_COLOR (1,1,1)-(Rd,Gd,Bd) 1-Ad
        GL_SRC_ALPHA (As,As,As) As
        GL_ONE_MINUS_SRC_ALPHA (1,1,1)-(As,As,As) 1-As
        GL_DST_ALPHA (Ad,Ad,Ad) Ad
        GL_ONE_MINUS_DST_ALPHA (1,1,1)-(Ad,Ad,Ad) 1-Ad
        GL_CONSTANT_COLOR (Rc,Gc,Bc) Ac
        GL_ONE_MINUS_CONSTANT_COLOR (1,1,1)-(Rc,Gc,Bc) 1-Ac
        GL_CONSTANT_ALPHA (Ac,Ac,Ac) Ac
        GL_ONE_MINUS_CONSTANT_ALPHA (1,1,1)-(Ac,Ac,Ac) 1-Ac
        GL_SRC_ALPHA_SATURATE (f,f,f)*f=min(As,1-Ad) 1

        表中R、G、B、A分別表示紅、綠、藍(lán)、alpha
        下標(biāo)s、d,分別表示源、目標(biāo)
        表中c代表常量顏色(默認(rèn)黑色)

      • 改變混合方程式

        glBlendEquation(GLenum mode)
        
        枚舉值 RGB混合因子
        GL_FUNC_ADD Cf=(Cs * S) + (Cd * D)
        GL_FUNC_SUBTRACT Cf=(Cs * S) - (Cd * D)
        GL_FUNC_REVERSE_SUBTRACT Cf=(Cd * D) - (Cs * S)
        GL_MIN Cf=min(Cs,Cd)
        GL_MAX Cf=max(Cs,Cd)
      • 設(shè)置混合因子(RGB和Alpha分開設(shè)置)

        void glBlendFuncSeparate(GLenum strRGB, GLenum dstRGB, GLenum strAlpha, GLenum dstAlpha)
        
      • 設(shè)置常量混合顏色

        void glBlendColor(GLclampf red, GLclampf green, GLclamf blue, GLclampf alpha)
        
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容