寫在前面
在繪制封閉類型的幾何對象時,開啟背面剔除功能能夠提高渲染性能。本節簡要介紹下背面剔除,示例程序可以在我的github下載。
什么是背面剔除
當我們觀察場景中對象時,一般只能以一定角度來觀察,那么對象的某些面我們是看不到的,例如你觀察一個立方體,最多只能同時看到3個面,有時只能看到1個面,而我們繪制時如果不采取剔除背面的措施,則要繪制6個面,其中包括一些,我們根本看不到的面。對於立方體這個面較少的幾何對象,性能開銷不明顯,但是對於復雜的模型,開啟背面剔除則能明顯改善渲染性能。 背面剔除,就是早點丟棄對觀察者來說是背面的片元的一種方法。
背面剔除的使用
上面提到,要早點丟棄對觀察者來說是背面的片元,那么現在的問題是如何確定哪個面是背面的問題? OpenGL中使用頂點繞序(winding order)來確定。所謂繞序就是當幾何對象細分為三角形時,三角形頂點相對於中心的定義順序,具體如下圖所示(來自opengl wiki):
左邊的圖中指定頂點的順序是順時針的,右邊是逆時針的。
以三角面指向觀察者的方向為大拇指指向,其余手指逆時針繞着大拇指,如果手指的繞向和三角面頂點繞向一致,則這個面為正面,否則為背面。
在OpenGL中,我們指定逆時針和順時針的三角形頂點如下:
GLfloat vertices[] = {
// Clockwise vertices[0], // vertex 1 vertices[1], // vertex 2 vertices[2], // vertex 3 // Counter-clockwise vertices[0], // vertex 1 vertices[2], // vertex 3 vertices[1] // vertex 2 };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
需要注意的是,三角形的正面還是背面這個是根據觀察者的觀察方向,而變動的。例如下面的圖中(來自www.learnopengl.com):
左側的三角形頂點順序為1->2->3,右側的三角形頂點順序為1->2->3。當觀察者在右側時,則右邊的三角形方向為逆時針方向為正面,而左側的三角形為順時針則為背面;當觀察者轉到左側時,左側的三角形為逆時針繞序判定為正面,而右側的三角形為順時針繞序判定為背面。可以看出正面和背面是由三角形的頂點定義順序和觀察者的觀察方向共同決定的,而且隨着觀察方向的改變,正面和背面將會跟着改變。
在OpenGL中開啟背面剔除需要使用:
glEnable(GL_CULL_FACE);
- 1
同時OpenGL提供了函數glCullFace來供用戶選擇剔除哪個面:
API void glCullFace(GLenum mode);
mode參數為 GL_FRONT, GL_BACK, GL_FRONT_AND_BACK 3個枚舉類型。默認為GL_BACK.
以及glFrontFace函數用來根據繞序指定哪個為正面:
API void glFrontFace(GLenum mode);
mode參數為GL_CW ,GL_CCW。默認值是GL_CCW。
如果要剔除正面,代碼:
glCullFace(GL_BACK);
glFrontFace(GL_CW);
- 1
- 2
和下面的代碼等價:
glCullFace(GL_FRONT);
- 1
首先我們來對比下使用背面剔除和未使用背面剔除時,穿過立方體內部,我們看到的景象。下圖是沒有開啟背面剔除時:
可以看到,穿過內部時,看到了立方體后面的部分。當開啟了背面剔除時,穿過內部時,看不到立方體的背面:
當我們剔除正面時,觀察者的位置,決定了哪是正面,當觀察者處於立方體正面時,剔除正面看到效果:
當觀察者移動到可以看到立方體三個面時,判定正面,頂面和右側面為正面,則剔除正面后的效果為:
最后的說明
在使用背面剔除時需要注意,在指定物體表面的頂點時,頂點的順序需要定義為正向的逆時針順序。啟用背面剔除一般而言總能改善渲染性能,但是具體是否開啟背面剔除還是要根據應用場景而定。當渲染某些非封閉類型幾何對象,例如一顆草的模型時,則不需要開啟背面剔除。