日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL之基本图元

發布時間:2023/12/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL之基本图元 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文轉載自文章:http://www.cnblogs.com/gl5773477/p/4007350.html

因為文章較老,只需要注意圖元的繪制邏輯即可,在可編程的shader中,并沒有用到這樣的繪制方法。

在了解了一些基本圖元之后,要知道如何利用基本圖元來提高效率。比如當我畫一個扇形的時候,最好使用 ?GL_TRIANGLE_FAN?而不是GL_TRIANGLE?,因為這樣可以提高效率。


OpenGL的基本圖元有點(Point)、線段(Line)、多邊形(Ploygon)、三角形(Triangle)、四邊形(Quadrangle)。組成關系我想大部分人都能夠理解:

  ①無數個“點”的線性排列組成----“線段”

  ②多個“線段”可以圍成一個“多邊形”

  ③多個“多邊形”在三維空間中可以圍成“多面體”

有此,可以看出,點是最基本的圖元,其他的圖元都是由頂點組合構成的,因此我們從點開始介紹。

1、點

在OpenGL中,“點”稱為頂點(Vertex),通常用一個形如(x, y, z)的三維坐標值表示。

有時候會采用齊次坐標表示,就是一個形如(x, y, z, w)的四元組,可以這樣理解這個四元組,前面的(x,y,z)表示“點”所在的方向,而w表示在該方向上的距離比例,所以(x, y, z, w)表示的實際坐標值就是(x/w, y/w, z/w)坐標點。如果w為0,則表示方向為(x, y, z)的無窮遠點;如果w=10,表示取(x,y,z)的十分之一作為坐標點(x/10,y/10,z/10)。

?

一般情況 下,OpenGL 中的點將被畫成單個的像素。實際上點還可以更小,雖然它可能足夠小,但并不會是無窮小,一個像素內可以描繪多個點,取決于對點大小的設定,默認一個點的大小為一個像素。

當然我們也可以改變點的大小,函數原型為:

//size 必須大于 0.0f,默認值為 1.0f,單位為“像素”。 //對于具體的 OpenGL 實現,點的大小都有個限度的,如果設置的 size 超過最大值,則設置可能會有問題,一般情況是不在增大。 void glPointSize(GLfloat size);

代碼實現畫一個點,我們只需要在我們的繪圖函數中添加如下代碼即可:

void display(void) {glPointSize(5);//在繪制之前要設置要相關參數,這里設置點的大小為5像素 glBegin(GL_POINTS);{glVertex2f(0.0f, 0.0f); //OpenGl內的點是齊次坐標的四元組,缺省的z坐標為0.0f,w為1.0f,所以該點為(1, 2, 0, 1)glVertex2f(0.0f, 0.5f); //繪制的第二個點glVertex2f(0.5f, 0.25f); //繪制的第三個點 }glEnd();glFlush();//glFlush,保證前面的OpenGL命令立即執行(而不是讓它們在緩沖區中等待) }

需要注意的是:坐標的值默認是1.0為最大,即屏幕邊緣,所以如果大于1,則會超出屏幕,這時候除非改變觀察點,否則是看不到的。(0,0)表示在屏幕的中間,也就是坐標系原點。

OpenGL中繪制幾何圖元,必須使用 glBegain() 和 glEnd() 這一對函數,glBegin() 和 glEnd() 需要成對使用,兩者之間是繪圖語句。

glBegin()的參數就是需要繪制的圖元類型,它決定了在glBegin()和glEnd()之間繪圖的點將如何組織成目標圖元,如參數為“GL_POINTS”,表示每一個點都是獨立的,互不相連的,因此也就繪制出了一個個“點”。

2、線段

線段是由兩個頂點連接起來形成的圖元。線段間的連接方式有三種:

①獨立線段:圖元類型參數--GL_LINES

②線段間首尾相連但最終不閉合:折線,圖元類型參數--GL_LINE_STRIP

③線段間首尾相連最終封口閉合:圖形,圖元類型參數--GL_LINE_LOOP

對應的圖例:

?

線段代碼實例:

void display(void) {/*同樣用5個點,畫出不同類型的線段組合*///獨立線段,5個點能畫出2條線段 glBegin(GL_LINES);{glVertex2f(-0.8f, -0.5f); glVertex2f(-0.5f, -0.5f);glVertex2f(-0.8f, 0.0f); glVertex2f(-0.5f, 0.0f); glVertex2f(-0.8f, 0.5f); //最后的這個點沒有與之配對的點,無法連成線段,所以不會被畫出來,在獨立線段模式下被舍棄 }glEnd();//連續不閉合折線,5個點能畫出4條線段 glBegin(GL_LINE_STRIP);{glVertex2f(-0.3f, -0.5f); //起始點//后面的每一個點都會與前一個相連生成一條線段glVertex2f(-0.0f, -0.5f);glVertex2f(-0.3f, 0.0f); glVertex2f(-0.0f, 0.0f); glVertex2f(-0.3f, 0.5f);}glEnd();//連續閉合折線,5個點能畫出5條線段 glBegin(GL_LINE_LOOP);{glVertex2f(0.2f, -0.5f); //起始點//后面的每一個點都會與前一個相連生成一條線段glVertex2f(0.5f, -0.5f);glVertex2f(0.2f, 0.0f); glVertex2f(0.5f, 0.0f); //最后一個點不僅與前一個點相連,還與起始點相連,形成閉合glVertex2f(0.2f, 0.5f);}glEnd();glFlush();//保證前面的OpenGL命令立即執行(而不是讓它們在緩沖區中等待) }

程序運行示例圖:

同樣的,直線可以指定寬度:

void glLineWidth(GLfloat width); //width表示線寬,單位:像素

特殊的是線除了直線,還有虛線。可以用虛線連接兩個點。

在繪制虛線之前必須先啟動“虛線模式”:glEnable(GL_LINE_STIPPLE);

虛線有不同的類型,調節函數如下:

/*參數pattern是16位二進制數(0或1),如OxAAAA表示1010101010101010從低位開始,每一個二進制位代表一個像素, 1表示用當前顏色繪制一個像素,0表示當前不繪制,只移動一個像素位,中間留下一個像素的空白factor是用來調節二進制位0和1代表的像素個數,如果factor為2,則表示遇到二進制1的時候用當前顏色繪制兩個像素,0移動兩個像素不繪制 */ void glLineStipple(GLint factor,GLushort pattern);

代碼示例:

void display(void) {//開啟虛線模式 glEnable(GL_LINE_STIPPLE);//調節虛線類型參數glLineStipple(2,0xAAAA);//調節線寬glLineWidth(3);//繪制一條虛線 glBegin(GL_LINES);{glVertex2f(0,0);glVertex2f(0.5,0.5);}glEnd();glFlush();//保證前面的OpenGL命令立即執行(而不是讓它們在緩沖區中等待) }

程序運行示例:

3、多邊形

類似于點組合線段的方式,OpenGL定義的多邊形是由多個點連接成線段再圍成封閉區域。

多邊形有兩種:凸多邊形(指多邊形任意非相鄰的兩點的連線位于多邊形的內部)和凹多邊形,但OpenGL中規定的多邊形必須是凸多邊形

但有時需要繪制一些凹多邊形,通常解決的辦法是對它們進行分割,用多個三角形來組合替代。顯然,繪制這些三角形時,有些邊不應該進行繪制,否則,多邊形內部就會出現多余的線框。OpenGL提供的解決辦法是通過設置邊標志命令glEdgeFlag()來控制某些邊產生繪制,而另外一些邊不產生繪制,這里只需知道有這個工能,具體細節待遇到在研究,接下來看重點。

(1)連接方式

<1>按點的定義順序依次連接:圖元類型參數--GL_POLYGON

<2>從第1個點開始,每三個點一組畫一個三角形,三角形之間是獨立的:圖元類型參數--GL_TRIANGLES

<3>從第三個點開始,每點與前面的兩個點組合畫一個三角形,即線性連續三角形串:圖元類型參數--GL_TRIANGLE_STRIP

<4>從第三個點開始,每點與前一個點和第一個點組合畫一個三角形,即扇形連續三角形:圖元類型參數--GL_TRIANGLE_FAN

對應的圖例:

?

四邊形的繪制模式和三角形類似。

(2)多邊形的正反兩面

多邊形為什么會有正反面這一說法呢?舉個簡單的例子。

雖然多邊形是二維的,但是我們知道三維物體可以理解為多邊形圍成的,也就是說在三維空間物體上有二維多邊形的存在。

一張“正方形”紙片,如果極限的薄,我們可以認為是一個多邊形(正方形),那么紙仍然會存在兩面,紙的正反面。更具體一點,如果我們用同大小6張正方形的紙片圍成一個正方體,那么正方體的任何一個面都是一個多邊形,而且這個多邊形是有正反面,朝外的你能看到的部分是正面(假設),那么朝內的看不到的那部分就是反面。同樣的道理,OpenGL要區分多邊形的正反面。那么到底怎么定義正面或者反面呢?

有一個函數來定義:

glFrontFace(GL_CCW);//設置點序列逆時針方向圍成的多邊形為正面 glFrontFace(GL_CW); //設置點序列順時針方向圍成的多邊形為正面

設置這個的原因是,默認情況下,OpenGL繪制三維物體時兩面都會繪制,而實際的時候很多面我們是看不到的,如物體朝內方向的多邊形,還有一些物體間遮擋的情況導致有些多邊形是不可見的,因此為了提高性能,我們需要剔除這些不必要的繪制。

glEnable(GL_CULL_FACE); //來啟動剔除功能 glCullFace(); //參數可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK,表示剔除多邊形的哪種面,設定后該類型的多邊形不繪制

(3)繪制模式

常用的多邊形繪制模式有:填充式(默認)輪廓線式頂點式鏤空圖案填充式

前三種都是使用glPolygonMode()函數來指定模式,最后一種比較特殊。

void glPolygonMode(GLenum face,GLenum mode);//該函數要求說明是對多邊形哪一個面是定face設置模式

畫一個多邊形,設置不同的繪制模式,看一下效果:

代碼:

void myDisplay(void) {//設置點的大小,以便容易觀察glPointSize(5);//設置正面的繪制模式為:填充式,反面不設定則默認為填充式 glPolygonMode(GL_FRONT,GL_FILL);glBegin(GL_POLYGON);{glVertex2f(0,0);glVertex2f(0,0.3);glVertex2f(-0.3,0.3);glVertex2f(-0.3,0);}glEnd();//設置正面的繪制模式為:輪廓線式 glPolygonMode(GL_FRONT,GL_LINE);glBegin(GL_POLYGON);{glVertex2f(0.5,0);glVertex2f(0.5,0.3);glVertex2f(0.2,0.3);glVertex2f(0.2,0);}glEnd();//設置正面的繪制模式為:頂點式 glPolygonMode(GL_FRONT,GL_POINT);glBegin(GL_POLYGON);{glVertex2f(0.9,0);glVertex2f(0.9,0.3);glVertex2f(0.6,0.3);glVertex2f(0.6,0);}glEnd();glFlush(); }

示例圖:

關于最后一種鏤空圖案樣式,有點類似于線段中的虛線,這里只不過是針對多邊形內部區域進行像素點的繪制與否,來做鏤空效果。具體的細節還需查閱資料。

?


以上為基本圖元的知識講解,并給出了針對性的代碼實例,在此基礎之上會進一步學習更加復雜的圖形繪制。

總結

以上是生活随笔為你收集整理的OpenGL之基本图元的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。