學習了畫線的知識,我們可以使用GL_LINE_LOOP來畫閉合的多邊形。但是使用這種方式畫出來的只有線框,多邊形沒有填充顏色。OpenGL支持繪制實心的多邊形,並使用當前的顏色進行填充。
簡單的三角形,需要指定三個頂點。
1: glBegin(GL_TRIANGLES);
2: glVertex2f(0.0f, 0.0f); // V0
3: glVertex2f(25.0f, 25.0f); // V1
4: glVertex2f(50.0f, 0.0f); // V2
5: glVertex2f(-50.0f, 0.0f); // V3
6: glVertex2f(-75.0f, 50.0f); // V4
7: glVertex2f(-25.0f, 0.0f); // V5
8: glEnd();
9:
這兩個三角形會使用當前的顏色進行填充。
按照頂點指定的順序和方向組合稱為環繞。上圖的兩個多邊形是順時針環繞的。我們可以通過改變頂點的順序,從而改變環繞方向。我們把v4和v5的順序調換過來,則這個三角形的環繞方向為逆時針了。
OpenGL默認是逆時針環繞方向為正方向,即逆時針環繞的三角形為正面。上圖左邊的三角形,顯示的是正面,而右邊的顯示的是反面。我們也可以通過函數glFrontFace(GL_CW);來告訴OpenGL順時針環繞的多邊形是正面。環繞方向是多邊形一個非常有用的性質,可以用於消除不必要的面。
我們可以繪制多個三角形連起來形成多個面或者多邊形。使用GL_TRIANGLE_STRIP圖元,可以繪制一串相連的多邊形,來節省大量的時間。
由上圖可以看到,多邊形的邊的繪制順序並不是完全按照我們指定的頂點順序的。而是按照OpenGL指定的順序逆時針方向繪制的。
使用三角形帶而不是分別指定每個三角形的頂點的優勢有兩個:
除了三角形帶之外,我們還可以通過GL_TRIANGLE_FAN圖元,創建一組圍繞一個中心點的三角形扇。通過制定5個頂點我們就可以繪制3個三角形來形成三角形扇。用3個頂點指定一個三角形後,後續的頂點Vn與原點V0以及前面的一個頂點Vn-1形成一個三角形。
1: static void RenderScene()
2: {
3: //清除顏色緩沖區和深度緩沖區
4: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5:
6: GLfloat x, y, z, angle;
7: //用於顏色判斷
8: bool color;
9: glColor3f(1.0f, 1.0f, 0.0f);
10: //是否開啟深度緩沖
11: if (bDepth)
12: {
13: glEnable(GL_DEPTH_TEST);
14: }
15: else
16: {
17: glDisable(GL_DEPTH_TEST);
18: }
19: //是否開啟隱藏面消除
20: if (bCull)
21: {
22: glEnable(GL_CULL_FACE);
23: }
24: else
25: {
26: glDisable(GL_CULL_FACE);
27: }
28: //開啟線框模式
29: if (bOutLine)
30: {
31: glPolygonMode(GL_BACK, GL_LINE) ;
32: }
33: else
34: {
35: glPolygonMode(GL_BACK, GL_FILL);
36: }
37:
38:
39: glPushMatrix();
40: glRotatef(xRot, 1.0f, 0.0f, 0.0f);
41: glRotatef(yRot, 0.0f, 1.0f, 0.0f);
42: //畫椎體
43: glBegin(GL_TRIANGLE_FAN);
44: glVertex3f(0.0f, 0.0f, 70.0f);
45:
46: for (angle = 0.0f; angle <= (2 * GL_PI); angle += (GL_PI / 8))
47: {
48: x = 50.0f * sin(angle);
49: y = 50.0f * cos(angle);
50: color = !color;
51:
52: glVertex3f(x, y, 0.0f);
53: if(color)
54: glColor3f(1.0f, 0.0f, 0.0f);
55: else
56: glColor3f(0.0f, 1.0f, 1.0f);
57: }
58: glEnd();
59: //畫椎體的底面
60: glBegin(GL_TRIANGLE_FAN);
61: glVertex2f(0.0f, 0.0f);
62:
63: for (angle = 0.0f; angle <= (2 * GL_PI); angle += (GL_PI / 8))
64: {
65: x = 50.0f * sin(angle);
66: y = 50.0f * cos(angle);
67: color = !color;
68:
69: glVertex2f(x, y);
70:
71: if(color)
72: glColor3f(1.0f, 0.0f, 0.0f);
73: else
74: glColor3f(0.0f, 1.0f, 1.0f);
75: }
76: glEnd();
77:
78: glPopMatrix();
79: glutSwapBuffers();
80: }
81:
82: static void SetupRC()
83: {
84: glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
85: //設置環繞方向
86: glEnable(GL_CW);
87: //設置填充模式
88: glShadeModel(GL_FLAT);
89: //設置要消除的隱藏面,這裡設置為反面
90: glCullFace(GL_BACK);
91: }
使用紅青相間的方式來繪制一個錐體。
多邊形的填充模式有兩種一種是單調著色GL_FLAT,一種平滑著色GL_SMOOTH。
通過glShadeMode(GL_FLAT);和glShadeMode(GL_SMOOTH);來設置。單調著色以三角形的最後一個頂點的顏色來填充三角形。平滑著色則是用三個頂點的顏色值進行內插值運算,來填充三角形的顏色。
平滑著色效果如下:
如果沒有使用深度緩沖區,來進行深度測試。上面的椎體如何旋轉(通過方向鍵可以旋轉),都是把底面顯示了出來。因為底面我們是在後面畫的,最後一個繪制的物體出現在之前繪制的物體的前面。如果開啟了深度測試來解決問題。
深度測試:當一個像素被繪制時,它將被設置一個值(z值),以表示它和觀測者的距離。以後當這個位置要繪制新像素時,新像素的z值就會和舊像素的z值進行比較。如果新像素z值更高,則更靠近觀察者,則應該被繪制,反之被忽略。
啟用深度測試只須調用glEnable(GL_DEPTH_TEST);每次場景被渲染之前,應該清楚深度緩沖區,與清楚顏色緩沖區類似。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
在程序用使用右鍵點擊,彈出菜單,深度測試來切換深度測試。在繪制3D實體時,深度測試往往是必須的。
雖然啟用深度測試,可以消除隱藏面。但很多時候,我們清楚那些面是不需要繪制,應該被剔除的。例如:多邊形的背面不應該被顯示。如果我們告知OpenGL這個圖形面不需要被繪制,就不會把這個圖形發送給OpenGL驅動程序和硬件,可以提高性能。
啟用剔除面的功能。
//指定順時針環繞的面為正面
glFrontFace(GL_CW);
//開啟剔除面,剔除背面。
glEnable(GL_CULL_FACE);
錐體的底面面向錐體內部的是正面。要改變底面的正面,可以再繪制底面時設置glFrontFace(GL_CCW);
多邊形我們可以指定它的模式,要填充還是只畫線框或者只畫頂點。
通過glPolygonMode(GL_BACK, GL_LINE) ;設置多邊形的背面只畫線。
通過glPolygonMode(GL_BACK, GL_FILL) ;設置多邊形的背面為實體。
通過glPolygonMode(GL_BACK, GL_POINT) ;設置多邊形的背面只畫點。
源代碼:https://github.com/sweetdark/openglex/tree/master/triangle
OpenGL超級寶典 第4版 中文版PDF+英文版+源代碼 見 http://www.linuxidc.com/Linux/2013-10/91413.htm
OpenGL編程指南(原書第7版)中文掃描版PDF 下載 http://www.linuxidc.com/Linux/2012-08/67925.htm
OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm
Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm
OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm
Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm
如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm
更多《OpenGL超級寶典學習筆記》相關知識 見 http://www.linuxidc.com/search.aspx?where=nkey&keyword=34581