OpenGL 繪製二維圖形
void CStepinGLView::OnDraw(CDC* pDC)
{
CStepinGLDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此處為本機資料新增繪製程式碼
DrawCube();
SwapBuffers(wglGetCurrentDC());
}
好了,廢話就說到這。
1.繪製點
此段程式碼中:glGetFloatv(GL_POINT_SIZE_RANGE,fPointSize);void CStepinGLView::DrawScene(void) { glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0f,0.0f,0.0f); //顏色為紅色 //繪製點 GLfloat fPointSize[2]; glGetFloatv(GL_POINT_SIZE_RANGE,fPointSize); //獲取點的大小範圍 fPointSize[0]儲存點的大小最小值,1儲存最大值 glPointSize(fPointSize[1] / 2.0f); glBegin(GL_POINTS); glVertex2f(0.0f,0.0f); glVertex2f(0.5f,0.5f); glVertex2f(-0.5f,0.5f); glVertex2f(0.5f,-0.5f); glVertex2f(-0.5f,-0.5f); glEnd(); }
glGetFloatv第一個引數必須是OpenGL常量,第二個引數是一個數組的地址。函式按第一個引數的指示向第二個引數所指的地址傳輸資料。fPointSize[0]儲存點的大小的最小值,fPointSize[1]儲存點的大小的最大值。
執行截圖:
2.繪製直線和線型
void CStepinGLView::DrawLineStipple(void) { glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0f,0.0f,0.0f); //顏色為紅色 GLfloat fLineWidth[2]; glGetFloatv(GL_LINE_WIDTH_RANGE,fLineWidth); glLineWidth(fLineWidth[1] / 6.0f); glBegin(GL_LINES); glVertex2f(-0.8f,0.8f); glVertex2f(0.8f,0.8f); glEnd(); //glEnable(GL_LINE_STRIP); //第一次使用此型別,輸出都是直線 glEnable(GL_LINE_STIPPLE); //glEnable()啟用函式 ,此句執行後 執行畫虛線 glLineStipple(1,0x00FF); //設定直線的當前點畫模式 glBegin(GL_LINES); glVertex2f(-0.8f,0.4f); glVertex2f(0.8f,0.4f); glEnd(); glLineStipple(1,0x0F0F); //設定直線的當前點畫模式 glBegin(GL_LINES); glVertex2f(-0.8f,0.0f); glVertex2f(0.8f,0.0f); glEnd(); glLineStipple(2,0x0101); //設定直線的當前點畫模式 glBegin(GL_LINES); glVertex2f(-0.8f,-0.4f); glVertex2f(0.8f,-0.4f); glEnd(); glLineStipple(1,0x1C47); //設定直線的當前點畫模式 glBegin(GL_LINES); glVertex2f(-0.8f,-0.8f); glVertex2f(0.8f,-0.8f); glEnd(); glDisable(GL_LINE_STIPPLE); glFinish(); }
OpenGL不僅能畫實線,而且可以繪製點畫線(Stippled Lines)等其他型別的直線。
為了繪製點畫線,必須先自定義點畫線的線型,然後通過 glLineStipple() 函式讓OpenGL獲取所定義的線型。
線型是通過二進位制來描述的,1代表一個實點,0則表示在該畫素處不畫直線,即不填充畫素。
例如:
0000000011111111; //對應16進位制0x00FF,表示空白線和長折線
0000111100001111; //0x0F0F,表示空白線及短折線
0000000100000001; //0x0101,表示點
0001110001000111; //0x1c47,表示折線點折線
呼叫glLineStipple()函式,讓OpenGL知道已改變的線型。第一個引數資料型別為GLint,表示線型模式重複因子;第二個引數為GLushort,表示所定義的線型。重複因子說明了用二進位制表示的點的重複次數。如果重複因子是2,一個01010101的線型模式事實上被當成0011001100110011線型來處理。
為了對所定義的線型獲取OpenGL的支援,必須事先啟動改變線型的機制:
glEnable(GL_LINE_STIPPLE); //glEnable()啟用函式 ,此句執行後 執行畫虛線
要注意,當不再使用自定義線型時,將其關閉:
glDisable(GL_LINE_STIPPLE);
程式執行截圖:
3.繪製不閉合折線
void CStepinGLView::DrawLineStrip(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
GLfloat fLineWidth[2];
glGetFloatv(GL_LINE_WIDTH_RANGE,fLineWidth);
glLineWidth(fLineWidth[1] / 6.0f);
glBegin(GL_LINE_STRIP); //繪製不閉合折線
glVertex2f(-0.8f,0.6f);
glVertex2f(0.8f,0.6f);
glVertex2f(-0.8f,0.2f);
glVertex2f(0.8f,0.2f);
glEnd();
}
程式執行截圖:
4.繪製閉合折線
void CStepinGLView::DrawLineLoop(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
GLfloat fLineWidth[2];
glGetFloatv(GL_LINE_WIDTH_RANGE,fLineWidth);
glLineWidth(fLineWidth[1] / 6.0f);
glBegin(GL_LINE_LOOP); //繪製閉合折線
glVertex2f(-0.8f,0.6f);
glVertex2f(0.8f,0.6f);
glVertex2f(-0.8f,0.2f);
glVertex2f(0.8f,0.2f);
glVertex2f(-0.8f,0.0f);
glVertex2f(0.8f,0.0f);
glEnd();
}
程式執行截圖:
5.繪製多邊形
void CStepinGLView::DrawPolygons(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
glLineWidth(2.0f);
glPolygonMode(GL_FRONT,GL_LINE);
glPolygonMode(GL_BACK,GL_FILL);
glFrontFace(GL_CCW);
glBegin(GL_POLYGON);
glVertex2f(-0.3f,0.3f);
glVertex2f(-0.7f,-0.2f);
glVertex2f(-0.3f,-0.4f);
glVertex2f(0.4f,-0.4f);
glVertex2f(0.8f,-0.2f);
glVertex2f(0.4f,0.3f);
glEnd();
}
在OpenGL中,一個多邊形(polygon)至少有3個頂點。直線不能相交,多邊形應構成單連通的凸區域。
一個多邊形有前面和後面之分,並且前面和後面可以有不同的屬性。比如,可以指定一個多邊形的前面為紅色而後面為藍色。
一個多邊形的前面和後面是需要指定的,可以通過定義其頂點順序來確定。
如果頂點的排序順序是逆時針的,則該多邊形是前面的,如果頂點的排序屬性是順時針的,則該多邊形是後面的。
事實上,這是可以改變的。OpenGL提供了一個靈活的函式:
glFrontFace()。該函式引數只能是GL_CW或GL_CCW;
GL_CW表示按順時針順序定義的多邊形是前面的;
GL_CCW表示按逆時針順序定義的多邊形是前面的;
多邊形是封閉的線段構造的形狀,它與用GL_LINE_LOOP 繪製的閉合折線有本質的區別。一個多邊形可以進行填充,也可以不填充。這樣就需要對多邊形的繪製模式作出說明。可以採用:
glPolygonMode() :該函式有兩個引數;
第一個引數:GL_FRONT、GL_BACK、GL_FRONT_AND_BACK ,分別指多邊形前面、後面或前後兩面;
第二個引數:GL_POINT、GL_LINE、GL_FILL ,分別指 在多邊形的頂點畫點,畫多邊形框架,填充多邊形;
程式執行截圖:
6.繪製三角形
void CStepinGLView::DrawTriangles(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
//glTranslatef( -1.5f, 0.0f, -6.0f); //左移1.5單位,並移入螢幕6.0
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glLineWidth(1.0f);
glBegin(GL_TRIANGLES);
glVertex2f(-0.5f, 0.4f);
glVertex2f(-0.6f, -0.5f);
glVertex2f(0.5f, -0.5f);
glVertex2f(-0.5f, 0.8f);
glVertex2f(-0.5f, 0.6f);
glVertex2f(0.5f, 0.5f);
glEnd();
}
程式執行截圖:
7.繪製三角形片
void CStepinGLView::DrawTriangleStrip(void) //繪製三角形片
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(-0.8f,0.3f);
glVertex2f(-0.8f,-0.3f);
glVertex2f(-0.3f,-0.3f);
glVertex2f(0.0f,-0.3f);
glVertex2f(0.3f,0.5f);
glEnd();
}
採用頂點描述三角形時,前三個頂點描述了第一個三角形,第四個頂點可延伸出一個三角形。
在定義三角形片中,第一個三角形的頂點的排序順序是十分重要的,它決定了整個三角形片是前面還是後面的。
當glFrontFace()函式的引數採用GL_CCW時,第一個三角形按逆時針順序定義時,其前面是面向我們的。
三角形片中頂點被處理的順序,如下圖:
程式執行截圖:
8.繪製三角形扇
void CStepinGLView::DrawTriangleFan(void) //繪製三角形扇
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(-0.5f,-0.3f);
glVertex2f(0.3f,0.0f);
glVertex2f(0.3f,0.3f);
glVertex2f(0.4f,0.6f);
glVertex2f(-0.0f,0.6f);
glEnd();
}
三角形扇的繪製中,前三個頂點定義了第一個三角形,每增加一個頂點,便增加一個三角形;
程式執行截圖:
9.繪製四邊形
void CStepinGLView::DrawQuadrilaterala(void) //四邊形
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUADS);
glVertex2f(-0.6f,0.8f);
glVertex2f(-0.6f,-0.6f);
glVertex2f(0.5f,0.0f);
glVertex2f(0.6f,0.5f);
glEnd();
}
程式執行截圖:
10.繪製四邊形片
void CStepinGLView::DrawQuadStrip(void) //四邊形片
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUAD_STRIP);
glVertex2f(-0.8f,0.3f);
glVertex2f(-0.7f,0.6f);
glVertex2f(-0.6f,0.1f);
glVertex2f(-0.3f,0.6f);
glVertex2f(-0.1f,-0.2f);
glVertex2f(0.0f,0.6f);
glVertex2f(0.3f,-0.4f);
glVertex2f(0.6f,0.5f);
glEnd();
}
繪製示意圖:
程式執行截圖:
11.邊的可見性
void CStepinGLView::DrawNonConvex(void) //凹多邊形
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //顏色為紅色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_POLYGON);
glEdgeFlag(TRUE);
glVertex2f(-0.3f,0.3f);
glEdgeFlag(FALSE);
glVertex2f(-0.1f,-0.1f);
glEdgeFlag(TRUE);
glVertex2f(0.0f,-0.1f);
glVertex2f(0.0f,0.3f);
glEnd();
glBegin(GL_POLYGON);
glEdgeFlag(TRUE);
glVertex2f(-0.1f,-0.1f);
glVertex2f(-0.2f,-0.4f);
glEdgeFlag(FALSE);
glVertex2f(0.0f,-0.4f);
glVertex2f(0.0f,-0.1f);
glEnd();
glBegin(GL_POLYGON);
glEdgeFlag(FALSE);
glVertex2f(0.0f,-0.1f);
glEdgeFlag(TRUE);
glVertex2f(0.0f,-0.4f);
glVertex2f(0.4f,-0.4f);
glVertex2f(0.45f,0.1f);
glEnd();
}
要繪製如圖所示的凹多邊形,可以通過繪製兩個組合的四邊形。一個四邊形的頂點是(1,2,3,4),另一個四邊形的頂點是(3,4,5,6)。但是想產生左圖,就需要隱藏3---4這條邊。
OpenGL通過 glEdgeFlag() 函式來說明邊的可見性。
TRUE 表可見,FALSE 表不可見。
程式執行截圖:
12.由面建立三維形狀
void CStepinGLView::DrawCube(void) //繪製立方體
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //設定視窗為白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.2f,0.5f); //顏色為紅色
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glLineWidth(1.5f);
glColor3f(0.2f,0.5f,1.0f);
glPushMatrix();
glRotatef(70.0f,0.0f,1.0f,0.0f); //將盒子繞Y軸70度
glRotatef(55.0f,0.0f,0.0f,1.0f); //將盒子繞Z軸55度
glBegin(GL_POLYGON); //前面
glVertex3f(-0.5f,0.5f,0.5f);
glVertex3f(-0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,0.5f);
glVertex3f(0.5f,0.5f,0.5f);
glEnd();
//為了省事,我直接把前面的矩陣複製下來
//直接修改最後一位引數,結果繪製出的圖形不對
//原因:點的順序輸入不對,造成
glBegin(GL_POLYGON); //後面
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(0.5f,0.5f,-0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
glBegin(GL_POLYGON); //左面
glVertex3f(-0.5f,-0.5f,0.5f);
glVertex3f(-0.5f,0.5f,0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
glBegin(GL_POLYGON); //右面
glVertex3f(0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(0.5f,0.5f,-0.5f);
glVertex3f(0.5f,0.5f,0.5f);
glEnd();
glBegin(GL_POLYGON); //底面
glVertex3f(-0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
glBegin(GL_POLYGON); //頂面
glVertex3f(-0.5f,0.5f,0.5f);
glVertex3f(0.5f,0.5f,0.5f);
glVertex3f(0.5f,0.5f,-0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glEnd();
glPopMatrix();
}
請注意,從外部看,每個面都是前面的。因此,立方體的背面、左面、和底面的頂點順序必須是順時針的。
在用多邊形描述一個三維物體時,多邊形的前後面區分是十分重要的。如果一個面本來是前面的卻當成後面來處理很可能產生不良效果,特別是對其進行光照的時候。
程式執行截圖: