Qt下的OpenGL 编程(3)绘制平面几何体
生活随笔
收集整理的這篇文章主要介紹了
Qt下的OpenGL 编程(3)绘制平面几何体
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、 提要 之前的一篇教程已經搭建好了Qt下的OpenGL的編程環境,幾天要來學習的就是OpenGL的2D繪圖。 2D作為繪圖的基礎,還是很值得去好好學習,比如迪卡爾坐標,透視設置等等,而所謂的3D,也只是在2D的基礎上加上了Z軸。 這篇教程主要包括基本2D圖元的繪制,著色,旋轉。 二、必須要了解的幾個函數 gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar); 這個函數指定了觀察的視景體在世界坐標系中的具體大小,一般而言,其中的參數aspect應該與窗口的寬高比大小相同。 fovy,視野角度,用過照相機的話就很好理解了,數值越小,相當于將鏡頭拉得越近,數值越大,鏡頭越廣,鏡頭里的東西就越小。 aspect,這個好理解,就是實際窗口的縱橫比,即x/y。 zNear,這個呢,表示你近處,的裁面。 zFar表示遠處的裁面。 glLoadIdentity(); 這個函數類似于一個復位操作: 1.X坐標軸從左至右,Y坐標軸從下至上,Z坐標軸從里至外。 2.OpenGL屏幕中心的坐標值是X和Y軸上的0.0f點。 3.中心左面的坐標值是負值,右面是正值。 移向屏幕頂端是正值,移向屏幕底端是負值。 移入屏幕深處是負值,移出屏幕則是正值。 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 這個函數設置清除屏幕時所用的顏色,色彩值的范圍從0.0f到1.0f。0.0f代表最黑的情況,1.0f就是最亮的情況。glClearColor 后的第一個參數是Red Intensity(紅色分量),第二個是綠色,第三個是藍色。最大值也是1.0f,代表特定顏色分量的最亮情況。最后一個參數是Alpha值。 glTranslatef(x, y, z)沿著 X, Y 和 Z 軸移動。根據前面的次序,下面的代碼沿著X軸左移1.5個單位,Y軸不動(0.0f),最后移入屏幕6.0f個單位。注意在glTranslatef(x, y, z)中當您移動的時候,您并不是相對屏幕中心移動,而是相對與當前所在的屏幕位置。 glVertex *glVertex3f 就是確定頂點的函數,三個參數是點 的空間坐標。
三.圖形的繪制 在上一篇教程中已經繪制了一個正方形,相信大家都不會感到陌生。 先來分析上一篇的繪圖代碼: //繪制一個正方形 glBegin( GL_QUADS ); glVertex3f( -1.0, 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 0.0 ); glVertex3f( -1.0, -1.0, 0.0 ); glEnd();
glBegin 與 glEnd 很明顯是一對, 標志著一組 OpenGL 操作的開始和結束。 并且在參數中告訴了 OpenGL 下面的操作是針對什么圖形進行的,此例中 GL_QUADS 是表示四邊形。 通過傳遞給glBegin不同的參數,我們可以完成各種不同的圖形繪制,點,線,三角形,矩形,不規則多邊形... 簡而言之,上面的 4 句 glVertex3f 確定了矩形的 4 個頂點。(注意順序)然后, OpenGL 就會自動根據 glBegin 指定的參數去完成相關的繪制任務了。 下面我們在屏幕上繪制一個三角形和一個圓形,還有一個多邊形。 修改nehewidget.cpp的paintGL()就可以了。 void NeHeWidget::paintGL() { // 清除屏幕和深度緩存 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); //移到屏幕的左半部分,并且將視圖推入屏幕背后足夠的距離以便我們可以看見全部的場景 glTranslatef(-2.0f,0.0f,-5.0f); //設置顏色 glColor3f( 1.0, 1.0, 1.0 ); //繪制一個三角形 glBegin(GL_TRIANGLES); // 繪制三角形 glVertex3f( 0.0f, 1.0f, 0.0f); // 上頂點 glVertex3f(-1.0f,-1.0f, 0.0f); // 左下 glVertex3f( 1.0f,-1.0f, 0.0f); // 右下 glEnd(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); //繪制圓形 GLint iCirclePoints = 50; glBegin (GL_TRIANGLE_FAN ); for (int i = 0; i < 50; ++i ) { double dAngle = 2 * PI * i / iCirclePoints ; glVertex3f (cos (dAngle ), sin (dAngle ), 0.0); } glEnd (); //繪制多邊形 glLoadIdentity(); glTranslatef(2.0f,0.0f,-5.0f); glBegin(GL_POLYGON); glVertex3f( 0.0f, 0.5f, 0.0f); glVertex3f(-0.5f,-0.5f, 0.0f); glVertex3f( 0.0f,-1.5f, 0.0f); glVertex3f( 0.5f,-0.5f, 0.0f); glEnd(); }
繪制三角和多邊形非常簡單,就是將對應的參數傳給glBegin(),然后給出坐標,glEnd()之后就會繪制。繪制圓形的方法就是將整個圓周分成50份,然后利用三角函數循環計算圓周上的點的值,GL_TRIANGLE_FAN 是指連續地繪制三角形。三角形和多邊形的繪制就比較簡單了,就是在glBegin()和glEnd()之間插入相應的頂點坐標就可以了,可以去參考紅寶書里第二章的內容。 四. 著色 關于著色,其實我們上面已經用到一個函數,就是glColor3f( 1.0, 1.0, 1.0 );原理也是通過設置三個參數,得到想要的顏色,然后用來繪制圖形。注意,這里的著色是對于頂點的,也就是說你可以在繪制每個頂點之前設置繪制的顏色,然后它們之間的區域會很平滑的過渡。 繼續修改代碼。 void NeHeWidget::paintGL() { // 清除屏幕和深度緩存 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); //移到屏幕的左半部分,并且將視圖推入屏幕背后足夠的距離以便我們可以看見全部的場景 glTranslatef(-2.0f,0.0f,-5.0f); //繪制一個三角形 glBegin(GL_TRIANGLES); // 繪制三角形 glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); // 上頂點 glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // 左下 glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); // 右下 glEnd(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); //繪制圓形 GLint iCirclePoints = 50; glBegin (GL_TRIANGLE_FAN ); for (int i = 0; i < 50; ++i ) { glColor3f (0.0/i, 1.0/i, 1.0/i); double dAngle = 2 * PI * i / iCirclePoints ; glVertex3f (cos (dAngle ), sin (dAngle ), 0.0); } glEnd (); //繪制多邊形 glLoadIdentity(); glTranslatef(2.0f,0.0f,-5.0f); glColor3f( 1.0, 0.5, 0.0 ); glBegin(GL_POLYGON); glVertex3f( 0.0f, 0.5f, 0.0f); // 上頂點 glVertex3f(-0.5f,-0.5f, 0.0f); glVertex3f( 0.0f,-1.5f, 0.0f);// 左下 glVertex3f( 0.5f,-0.5f, 0.0f); // 右下 glEnd(); } 對于三角形,glEnd()出現后,三角形將被填充。但是因為每個頂點有不同的顏色,因此看起來顏色從每個角噴出,并剛好在三角形的中心匯合,三種顏色相互混合。這就是平滑著色。 對于圓形,就是利用循環逐漸改變頂點的顏色,最后得到這種漸變的效果。 對于多邊形,因為在glBegin()之前將顏色已經設置好,而在后面也沒有改變,所以最后所有頂點都設置成了同一種顏色。 五.旋轉 旋轉其實已經屬于3維的內容了,但實現起來其實非常簡單。我們將在NeHeWidget類中增加三個變量來控制這三個對象的旋轉。它們是浮點類型的變量,使得我們能夠非常精確地旋轉對象。新變量中叫做rTri的用來旋轉三角形,rCir旋轉圓形,rPoly 旋轉多邊邊形。 旋轉所用到的函數是glRotatef( Angle, Xvector, Yvector, Zvector ), 它負責讓對象繞某個軸旋轉。這個函數有很多用處。 Angle 通常是個變量代表對象轉過的角度。Xvector,Yvector和Zvector三個參數則共同決定旋轉軸的方向。比如( 1, 0, 0 )所描述的矢量經過X坐標軸的1個單位處并且方向向右。( -1, 0, 0 )所描述的矢量經過X坐標軸的1個單位處,但方向向左。 關于旋轉的方向的確定,我們可以這樣來理解:( Xvector, Yvector, Zvector)表示空間中的一個向量,用右手的大拇指指向這個向量,其他四指抓握的方向就是旋轉的方向。 繼續修改代碼. 頭文件中添加相應的變量: protected: GLfloat rTri; GLfloat rCir; GLfloat rPoly; 在構造函數中初始化 NeHeWidget::NeHeWidget(QWidget *parent) : QGLWidget(parent) { //初始化旋轉量 rTri = 0; rCir = 0; rPoly=0; void NeHeWidget::paintGL() { // 清除屏幕和深度緩存 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); //移到屏幕的左半部分,并且將視圖推入屏幕背后足夠的距離以便我們可以看見全部的場景 glTranslatef(-2.0f,0.0f,-5.0f); //對三角形進行旋轉 glRotatef( rTri, 1.0, 0.0, 0.0 ); //繪制一個三角形 glBegin(GL_TRIANGLES); // 繪制三角形 glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); // 上頂點 glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // 左下 glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); // 右下 glEnd(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); glRotatef( rCir, 0.0, 1.0, 0.0 ); //繪制圓形 GLint iCirclePoints = 50; glBegin (GL_TRIANGLE_FAN ); for (int i = 0; i < 50; ++i ) { glColor3f (0.0/i, 1.0/i, 1.0/i); double dAngle = 2 * PI * i / iCirclePoints ; glVertex3f (cos (dAngle ), sin (dAngle ), 0.0); } glEnd (); //繪制多邊形 glLoadIdentity(); glTranslatef(2.0f,0.0f,-5.0f); glRotatef( rPoly, 0.0, 1.0, 1.0 ); glColor3f( 1.0, 0.5, 0.0 ); glBegin(GL_POLYGON); glVertex3f( 0.0f, 0.5f, 0.0f); // 上頂點 glVertex3f(-0.5f,-0.5f, 0.0f); glVertex3f( 0.0f,-1.5f, 0.0f);// 左下 glVertex3f( 0.5f,-0.5f, 0.0f); // 右下 glEnd(); //每重新繪制一遍窗口就改變一次旋轉量。 rTri += 1.5; rCir -= 1.5; rPoly+=2; } 編譯運行之后不斷按F2改變窗口就可以觀察到相應的變化了,這里我通過設定不同的旋轉向量來讓三個圖形按照不同的方向來旋轉。 注意一點:在適當的位置調用glLoadIdentity()重置坐標,不然在后面圖形的繪制的時候就是基于之前變換過的坐標了。 今天就到這。 參考資料
三.圖形的繪制 在上一篇教程中已經繪制了一個正方形,相信大家都不會感到陌生。 先來分析上一篇的繪圖代碼: //繪制一個正方形 glBegin( GL_QUADS ); glVertex3f( -1.0, 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 0.0 ); glVertex3f( -1.0, -1.0, 0.0 ); glEnd();
glBegin 與 glEnd 很明顯是一對, 標志著一組 OpenGL 操作的開始和結束。 并且在參數中告訴了 OpenGL 下面的操作是針對什么圖形進行的,此例中 GL_QUADS 是表示四邊形。 通過傳遞給glBegin不同的參數,我們可以完成各種不同的圖形繪制,點,線,三角形,矩形,不規則多邊形... 簡而言之,上面的 4 句 glVertex3f 確定了矩形的 4 個頂點。(注意順序)然后, OpenGL 就會自動根據 glBegin 指定的參數去完成相關的繪制任務了。 下面我們在屏幕上繪制一個三角形和一個圓形,還有一個多邊形。 修改nehewidget.cpp的paintGL()就可以了。 void NeHeWidget::paintGL() { // 清除屏幕和深度緩存 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); //移到屏幕的左半部分,并且將視圖推入屏幕背后足夠的距離以便我們可以看見全部的場景 glTranslatef(-2.0f,0.0f,-5.0f); //設置顏色 glColor3f( 1.0, 1.0, 1.0 ); //繪制一個三角形 glBegin(GL_TRIANGLES); // 繪制三角形 glVertex3f( 0.0f, 1.0f, 0.0f); // 上頂點 glVertex3f(-1.0f,-1.0f, 0.0f); // 左下 glVertex3f( 1.0f,-1.0f, 0.0f); // 右下 glEnd(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); //繪制圓形 GLint iCirclePoints = 50; glBegin (GL_TRIANGLE_FAN ); for (int i = 0; i < 50; ++i ) { double dAngle = 2 * PI * i / iCirclePoints ; glVertex3f (cos (dAngle ), sin (dAngle ), 0.0); } glEnd (); //繪制多邊形 glLoadIdentity(); glTranslatef(2.0f,0.0f,-5.0f); glBegin(GL_POLYGON); glVertex3f( 0.0f, 0.5f, 0.0f); glVertex3f(-0.5f,-0.5f, 0.0f); glVertex3f( 0.0f,-1.5f, 0.0f); glVertex3f( 0.5f,-0.5f, 0.0f); glEnd(); }
繪制三角和多邊形非常簡單,就是將對應的參數傳給glBegin(),然后給出坐標,glEnd()之后就會繪制。繪制圓形的方法就是將整個圓周分成50份,然后利用三角函數循環計算圓周上的點的值,GL_TRIANGLE_FAN 是指連續地繪制三角形。三角形和多邊形的繪制就比較簡單了,就是在glBegin()和glEnd()之間插入相應的頂點坐標就可以了,可以去參考紅寶書里第二章的內容。 四. 著色 關于著色,其實我們上面已經用到一個函數,就是glColor3f( 1.0, 1.0, 1.0 );原理也是通過設置三個參數,得到想要的顏色,然后用來繪制圖形。注意,這里的著色是對于頂點的,也就是說你可以在繪制每個頂點之前設置繪制的顏色,然后它們之間的區域會很平滑的過渡。 繼續修改代碼。 void NeHeWidget::paintGL() { // 清除屏幕和深度緩存 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); //移到屏幕的左半部分,并且將視圖推入屏幕背后足夠的距離以便我們可以看見全部的場景 glTranslatef(-2.0f,0.0f,-5.0f); //繪制一個三角形 glBegin(GL_TRIANGLES); // 繪制三角形 glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); // 上頂點 glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // 左下 glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); // 右下 glEnd(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); //繪制圓形 GLint iCirclePoints = 50; glBegin (GL_TRIANGLE_FAN ); for (int i = 0; i < 50; ++i ) { glColor3f (0.0/i, 1.0/i, 1.0/i); double dAngle = 2 * PI * i / iCirclePoints ; glVertex3f (cos (dAngle ), sin (dAngle ), 0.0); } glEnd (); //繪制多邊形 glLoadIdentity(); glTranslatef(2.0f,0.0f,-5.0f); glColor3f( 1.0, 0.5, 0.0 ); glBegin(GL_POLYGON); glVertex3f( 0.0f, 0.5f, 0.0f); // 上頂點 glVertex3f(-0.5f,-0.5f, 0.0f); glVertex3f( 0.0f,-1.5f, 0.0f);// 左下 glVertex3f( 0.5f,-0.5f, 0.0f); // 右下 glEnd(); } 對于三角形,glEnd()出現后,三角形將被填充。但是因為每個頂點有不同的顏色,因此看起來顏色從每個角噴出,并剛好在三角形的中心匯合,三種顏色相互混合。這就是平滑著色。 對于圓形,就是利用循環逐漸改變頂點的顏色,最后得到這種漸變的效果。 對于多邊形,因為在glBegin()之前將顏色已經設置好,而在后面也沒有改變,所以最后所有頂點都設置成了同一種顏色。 五.旋轉 旋轉其實已經屬于3維的內容了,但實現起來其實非常簡單。我們將在NeHeWidget類中增加三個變量來控制這三個對象的旋轉。它們是浮點類型的變量,使得我們能夠非常精確地旋轉對象。新變量中叫做rTri的用來旋轉三角形,rCir旋轉圓形,rPoly 旋轉多邊邊形。 旋轉所用到的函數是glRotatef( Angle, Xvector, Yvector, Zvector ), 它負責讓對象繞某個軸旋轉。這個函數有很多用處。 Angle 通常是個變量代表對象轉過的角度。Xvector,Yvector和Zvector三個參數則共同決定旋轉軸的方向。比如( 1, 0, 0 )所描述的矢量經過X坐標軸的1個單位處并且方向向右。( -1, 0, 0 )所描述的矢量經過X坐標軸的1個單位處,但方向向左。 關于旋轉的方向的確定,我們可以這樣來理解:( Xvector, Yvector, Zvector)表示空間中的一個向量,用右手的大拇指指向這個向量,其他四指抓握的方向就是旋轉的方向。 繼續修改代碼. 頭文件中添加相應的變量: protected: GLfloat rTri; GLfloat rCir; GLfloat rPoly; 在構造函數中初始化 NeHeWidget::NeHeWidget(QWidget *parent) : QGLWidget(parent) { //初始化旋轉量 rTri = 0; rCir = 0; rPoly=0; void NeHeWidget::paintGL() { // 清除屏幕和深度緩存 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); //移到屏幕的左半部分,并且將視圖推入屏幕背后足夠的距離以便我們可以看見全部的場景 glTranslatef(-2.0f,0.0f,-5.0f); //對三角形進行旋轉 glRotatef( rTri, 1.0, 0.0, 0.0 ); //繪制一個三角形 glBegin(GL_TRIANGLES); // 繪制三角形 glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); // 上頂點 glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // 左下 glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); // 右下 glEnd(); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); glRotatef( rCir, 0.0, 1.0, 0.0 ); //繪制圓形 GLint iCirclePoints = 50; glBegin (GL_TRIANGLE_FAN ); for (int i = 0; i < 50; ++i ) { glColor3f (0.0/i, 1.0/i, 1.0/i); double dAngle = 2 * PI * i / iCirclePoints ; glVertex3f (cos (dAngle ), sin (dAngle ), 0.0); } glEnd (); //繪制多邊形 glLoadIdentity(); glTranslatef(2.0f,0.0f,-5.0f); glRotatef( rPoly, 0.0, 1.0, 1.0 ); glColor3f( 1.0, 0.5, 0.0 ); glBegin(GL_POLYGON); glVertex3f( 0.0f, 0.5f, 0.0f); // 上頂點 glVertex3f(-0.5f,-0.5f, 0.0f); glVertex3f( 0.0f,-1.5f, 0.0f);// 左下 glVertex3f( 0.5f,-0.5f, 0.0f); // 右下 glEnd(); //每重新繪制一遍窗口就改變一次旋轉量。 rTri += 1.5; rCir -= 1.5; rPoly+=2; } 編譯運行之后不斷按F2改變窗口就可以觀察到相應的變化了,這里我通過設定不同的旋轉向量來讓三個圖形按照不同的方向來旋轉。 注意一點:在適當的位置調用glLoadIdentity()重置坐標,不然在后面圖形的繪制的時候就是基于之前變換過的坐標了。 今天就到這。 參考資料
1.??????《?OpenGL Reference Manual?》,?OpenGL?參考手冊
2.??????《?OpenGL?編程指南》(《?OpenGL Programming Guide?》),?Dave Shreiner?,?Mason Woo?,?Jackie Neider?,?Tom Davis?著,徐波譯,機械工業出版社
3. ? ? ? ? 《win32 OpenGL編程 》 ? 一個大牛的博客 ? ??http://blog.csdn.net/vagrxie/article/category/628716/3分享到:?
轉載于:https://blog.51cto.com/8672742/1368431
總結
以上是生活随笔為你收集整理的Qt下的OpenGL 编程(3)绘制平面几何体的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios开发图形绘制
- 下一篇: 【android】【git】Androi