OpenGL 程式設計/GLStart/Tut3
基本圖形是你可以輕鬆繪製的基本形狀。它可以是三角形、正方形,甚至是一個點。在本課中,我們將學習如何繪製一些基本圖形,包括:點、三角形和不同的多邊形。
在 OpenGL 中進行繪製的最簡單方法是使用即時模式。為此,你使用 glBegin() 函式,它接受一個引數“模式”,即你想要繪製的物件型別。
以下是可能的模式及其含義的列表
| GL_POINTS | 在螢幕上繪製點。每個指定的頂點都是一個點。 |
|---|---|
| GL_LINES | 在螢幕上繪製線條。每兩個指定的頂點組成一條線。 |
| GL_LINE_STRIP | 在螢幕上繪製連線的線條。每個指定的頂點在指定的第一個和第二個頂點之後都會連線。 |
| GL_LINE_LOOP | 在螢幕上繪製連線的線條。最後一個指定的頂點與第一個指定的頂點相連。 |
| GL_TRIANGLES | 在螢幕上繪製三角形。每三個指定的頂點組成一個三角形。 |
| GL_TRIANGLE_STRIP | 在螢幕上繪製連線的三角形。在指定的前三個頂點之後,每個指定的頂點都會建立一個三角形。 |
| GL_TRIANGLE_FAN | 像 GL_TRIANGLE_STRIP 一樣繪製連線的三角形,但以扇形形狀繪製三角形。 |
| GL_QUADS | 在螢幕上繪製四邊形(四邊形)。每四個指定的頂點組成一個四邊形。 |
| GL_QUAD_STRIP | 在螢幕上繪製連線的四邊形。在指定的第一個四個頂點之後,每兩個指定的頂點都會組成一個連線的四邊形。 |
| GL_POLYGON | 在螢幕上繪製多邊形。多邊形可以由任意數量的邊組成。 |
當你完成繪製特定基本圖形的所有頂點後,在下一行放置 glEnd() 函式,該函式結束該基本圖形的繪製。
讓我們用最簡單的模式 GL_POINTS 做一個例子。在使用 OpenGL 繪製點時,點的預設大小為 1 畫素寬和高。當你執行程式時,這將非常難以看到。要編輯要繪製的點的大小,可以使用 glPointSize() 函式,它接受一個引數,即你想要的點的大小。
現在在 Render() 函式中,在你編寫 glBegin() 程式碼之前,我們將設定點的大小為 10 畫素。
glPointSize(10.0f);
之後,任何點的繪製都將以 10 畫素寬和高繪製。現在用 GL_POINTS 模式引數編寫 glBegin() 函式。然後在此之後,使用 glVertex3f() 函式指定要使用的頂點。對於這個例子,我們希望螢幕的右上角 (1.0,1.0,0.0) 和左下角 (-1.0,-1.0,0.0) 有一個點。繪製完這兩個點後,確保使用 glEnd() 函式結束繪製。
glBegin(GL_POINTS); //starts drawing of points
glVertex3f(1.0f,1.0f,0.0f);//upper-right corner
glVertex3f(-1.0f,-1.0f,0.0f);//lower-left corner
glEnd();//end drawing of points
以下是你的參考的整個渲染函式以及示例輸出。本教程此部分的完整程式碼可以在可下載檔案中找到。這個例子叫做“points”
void Render()
{
//clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();//load identity matrix
glTranslatef(0.0f,0.0f,-4.0f);//move forward 4 units
glColor3f(0.0f,0.0f,1.0f); //blue color
glPointSize(10.0f);//set point size to 10 pixels
glBegin(GL_POINTS); //starts drawing of points
glVertex3f(1.0f,1.0f,0.0f);//upper-right corner
glVertex3f(-1.0f,-1.0f,0.0f);//lower-left corner
glEnd();//end drawing of points
}
我想要涵蓋 glBegin() 函式中的每一種模式,但這會佔用太多時間和空間。因此,我將涵蓋高階模式,並在需要時最有可能涵蓋其他模式。
線段環至少需要兩個頂點。之後指定的每個頂點都與之前指定的頂點和第一個指定的頂點相連。因此,如果我們在視窗左側、視窗右側、頂部和底部放置一個頂點,我們將得到一個旋轉的正方形。
讓我們在 OpenGL 中完成這個圖。首先,我們使用 glBegin() 函式並傳遞 GL_LINE_LOOP 引數,告訴 OpenGL 我們要開始繪製線段環。然後,我們傳遞四個頂點來建立旋轉的正方形。第一個頂點位於視窗左側 (-1.0f,0.0f,0.0f),第二個頂點位於視窗底部 (0.0f,-1.0f,0.0f),第三個頂點位於視窗右側 (1.0f,0.0f,0.0f),第四個也是最後一個頂點位於視窗頂部 (0.0f,1.0f,0.0f)。然後,我們確保放入 glEnd() 以告訴 OpenGL 我們已經完成繪製線段環。
glBegin(GL_LINE_LOOP);//start drawing a line loop
glVertex3f(-1.0f,0.0f,0.0f);//left of window
glVertex3f(0.0f,-1.0f,0.0f);//bottom of window
glVertex3f(1.0f,0.0f,0.0f);//right of window
glVertex3f(0.0f,1.0f,0.0f);//top of window
glEnd();//end drawing of line loop
以下是完整的 Render() 函式以及示例輸出。在本章的可下載檔案中查詢名為“lineLoop”的專案檔案。
void Render()
{
//clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();//load identity matrix
glTranslatef(0.0f,0.0f,-4.0f);//move forward 4 units
glColor3f(0.0f,0.0f,1.0f); //blue color
glBegin(GL_LINE_LOOP);//start drawing a line loop
glVertex3f(-1.0f,0.0f,0.0f);//left of window
glVertex3f(0.0f,-1.0f,0.0f);//bottom of window
glVertex3f(1.0f,0.0f,0.0f);//right of window
glVertex3f(0.0f,1.0f,0.0f);//top of window
glEnd();//end drawing of line loop
}
三角形由三個頂點組成。對於這個例子,我們將使用常規的 GL_TRIANGLES 模式來繪製兩個並排的三角形。
首先,我們要在左側繪製一個三角形。因此,我們需要在左側繪製三個頂點來表示一個三角形,並在視窗右側繪製三個頂點來表示第二個三角形。請注意,你不需要兩個 glBegin() 函式來繪製兩個三角形。由於 GL_TRIANGLES 是複數(意味著單詞末尾沒有“S”),它可以在一個 glBegin() 和 glEnd() 函式呼叫之間處理多個三角形。
請注意,我在圖的右下角寫下了頂點的座標。以下是繪製這兩個三角形的程式碼。
glBegin(GL_TRIANGLES);//start drawing triangles
glVertex3f(-1.0f,-0.1f,0.0f);//triangle one first vertex
glVertex3f(-0.5f,-0.25f,0.0f);//triangle one second vertex
glVertex3f(-0.75f,0.25f,0.0f);//triangle one third vertex
//drawing a new triangle
glVertex3f(0.5f,-0.25f,0.0f);//triangle two first vertex
glVertex3f(1.0f,-0.25f,0.0f);//triangle two second vertex
glVertex3f(0.75f,0.25f,0.0f);//triangle two third vertex
glEnd();//end drawing of triangles
以下是此例子的完整 Render() 函式以及示例輸出。要檢視完整程式碼,請參見可下載檔案中的“triangle”專案資料夾。
void Render()
{
//clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();//load identity matrix
glTranslatef(0.0f,0.0f,-4.0f);//move forward 4 units
glColor3f(0.0f,0.0f,1.0f); //blue color
glBegin(GL_TRIANGLES);//start drawing triangles
glVertex3f(-1.0f,-0.25f,0.0f);//triangle one first vertex
glVertex3f(-0.5f,-0.25f,0.0f);//triangle one second vertex
glVertex3f(-0.75f,0.25f,0.0f);//triangle one third vertex
//drawing a new triangle
glVertex3f(0.5f,-0.25f,0.0f);//triangle two first vertex
glVertex3f(1.0f,-0.25f,0.0f);//triangle two second vertex
glVertex3f(0.75f,0.25f,0.0f);//triangle two third vertex
glEnd();//end drawing of triangles
}
多邊形由至少三個頂點組成,這些頂點連線在一起形成一個形狀。在這個例子中,我們將使用 GL_POLYGON 模式來繪製一個六邊形。
GL_POLYGON 模式允許你繪製任意數量邊形的形狀。由於 GL_POLYGON 是一個單數詞(意味著單詞末尾沒有“S”),你只能在一個 glBegin() 和 glEnd() 函式呼叫之間繪製一個多邊形。另外,你指定的最後一個頂點會自動連線到第一個指定的頂點。當然,由於多邊形是一個封閉的形狀,就像三角形一樣,形狀將用你指定的顏色填充(目前為藍色)。以下是我們的六邊形的圖。
(注意:這不能用於 凹多邊形)
以下是繪製這個多邊形的程式碼
glBegin(GL_POLYGON);//begin drawing of polygon
glVertex3f(-0.5f,0.5f,0.0f);//first vertex
glVertex3f(0.5f,0.5f,0.0f);//second vertex
glVertex3f(1.0f,0.0f,0.0f);//third vertex
glVertex3f(0.5f,-0.5f,0.0f);//fourth vertex
glVertex3f(-0.5f,-0.5f,0.0f);//fifth vertex
glVertex3f(-1.0f,0.0f,0.0f);//sixth vertex
glEnd();//end drawing of polygon
以下是完整的 Render() 函式以及示例輸出。在包含的可下載檔案中查詢“polygon”專案資料夾中的完整程式碼。
void Render()
{
//clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();//load identity matrix
glTranslatef(0.0f,0.0f,-4.0f);//move forward 4 units
glColor3f(0.0f,0.0f,1.0f); //blue color
glBegin(GL_POLYGON);//begin drawing of polygon
glVertex3f(-0.5f,0.5f,0.0f);//first vertex
glVertex3f(0.5f,0.5f,0.0f);//second vertex
glVertex3f(1.0f,0.0f,0.0f);//third vertex
glVertex3f(0.5f,-0.5f,0.0f);//fourth vertex
glVertex3f(-0.5f,-0.5f,0.0f);//fifth vertex
glVertex3f(-1.0f,0.0f,0.0f);//sixth vertex
glEnd();//end drawing of polygon
}
使用 OpenGL 即時模式有一些缺點。例如,頂點資料必須在繪製時動態傳輸到圖形記憶體。這可以透過使用顯示列表來改進。顯示列表本質上是採用 glBegin()/glEnd() 命令序列並以有效的方式將其儲存在圖形卡側。
(待辦事項:稍後詳細說明,請參閱 [1] 以獲取一些資訊 - glGenLists(), glNewList(), glEndList(), glCallList(), glDeleteLists())
顯示列表也有一些缺點。一旦編譯,顯示列表就是靜態的,無法更改。此外,由多個基本圖形共享的頂點在繪製時仍然需要多次表示和變換。這非常低效。
頂點陣列和頂點緩衝區解決了這些問題。思路很簡單,就是使用陣列儲存頂點資料。使用 glDrawArrays(),可以使用這些頂點繪製基本圖形。
為了在影片記憶體中儲存資料,可以使用頂點緩衝區(glGenBuffer()、glBindBuffer()、glBufferData()、glDeleteBuffers())。 頂點緩衝區存在兩種型別。
- GL_ARRAY_BUFFER 用於儲存實際的頂點資料。
- GL_ELEMENT_ARRAY_BUFFER 用於儲存指向儲存在獨立的 GL_ARRAY_BUFFER 中的頂點的索引,從而允許在多個圖元中重用頂點。
(待辦事項:稍後詳細說明,舉例)




