OpenGL學(xué)習(xí)18——面剔除

面剔除(Face culling)

  • OpenGL會(huì)檢查所有面片,渲染那些面向視角的面片而丟棄那些背向的,減少片元著色器的調(diào)用次數(shù)。而這正是面剔除(face culling) 所做的。

1. 旋轉(zhuǎn)順序(Winding order)

  • 當(dāng)我們定義三角形頂點(diǎn)集合時(shí)我們按特定的旋轉(zhuǎn)順序進(jìn)行定義——順時(shí)針或逆時(shí)針。如下圖所示:(圖片取自書(shū)中
    三角形旋轉(zhuǎn)順序
  • 如上圖所示,我們首先確定頂點(diǎn)1,根據(jù)頂點(diǎn)2或3的選擇定義了三角形的旋轉(zhuǎn)順序,如下代碼所示:
float vertices[] = {
    // 順時(shí)針
    vertices[0],   // 頂點(diǎn)1
    vertices[1],   // 頂點(diǎn)2
    vertices[2],   // 頂點(diǎn)3
    // 逆時(shí)針
    vertices[0],   // 頂點(diǎn)1
    vertices[2],   // 頂點(diǎn)3
    vertices[1],   // 頂點(diǎn)2
}
  • 從上可知,三角形基元的三個(gè)頂點(diǎn)包含了旋轉(zhuǎn)順序信息,OpenGL可以使用該信息在渲染基元時(shí)確定三角形是正向還是背向。默認(rèn)情況下,使用逆時(shí)針定義的三角形處理時(shí)被確定為正向的。
  • 實(shí)際的旋轉(zhuǎn)順序是在光柵化階段進(jìn)行計(jì)算的,那時(shí)頂點(diǎn)著色器已經(jīng)運(yùn)行完畢,頂點(diǎn)是以觀察者的視角進(jìn)行查看的。這時(shí),那些面向觀察者的三角形的旋轉(zhuǎn)順序剛好是正向的,而立方體背面的三角形的旋轉(zhuǎn)順序則被反轉(zhuǎn),變?yōu)楸诚虻?。如下圖所示:(圖片取自書(shū)中
    視角下的三角形面片

2. 面剔除

  • 從上一小節(jié)我們知道,如果三角形基元被渲染為背向三角形,OpenGL能夠丟棄這些三角形基元。因此,我們首先將立方體的頂點(diǎn)數(shù)據(jù)按逆時(shí)針旋轉(zhuǎn)順序進(jìn)行定義。
float cubeVertices[] = {
    // 背面
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,  // 左下
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,  // 右上
     0.5f, -0.5f, -0.5f,  1.0f, 0.0f,  // 右下
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,  // 右上
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,  // 左下
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,  // 左上
    // 正面
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    // 左面
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    // 右面
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    // 下面
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
     0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
     0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    // 上面
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 0.0f
};
  • 其次,我們啟用面剔除。注意:面剔除只針對(duì)封閉圖形如立方體才有意義。
glEnable(GL_CULL_FACE);
  • OpenGL同時(shí)允許我們使用glCullFace函數(shù)設(shè)定剔除的面片類(lèi)型。
// 參數(shù)
// GL_BACK: 剔除背向面片(默認(rèn))
// GL_FRONT: 剔除正向面片
// GL_FRONT_AND_BACK: 剔除正向和背向面片
glCullFace(GL_FRONT);
  • OpenGL還允許我們使用glFrontFace函數(shù)將哪種旋轉(zhuǎn)順序設(shè)定為正向的。
// 參數(shù)
// GL_CCW: 逆時(shí)針為正向
// GL_CW:  順時(shí)針為正向
glFrontFace(GL_CCW);
  • 作一個(gè)簡(jiǎn)單測(cè)試,我們讓OpenGL剔除背面,但是把順時(shí)針的旋轉(zhuǎn)順序設(shè)定為正向。
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
  • 渲染效果(需要進(jìn)行一定旋轉(zhuǎn),讓視角處于上平面上方)。


    剔除正向面片
  • 上面的渲染與下面的代碼效果是一樣的,即相當(dāng)于剔除正向視角的基元。
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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