日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Win32 OpenGL編程(3) 基本圖元(點(diǎn),直線,多邊

系統(tǒng) 2396 0

Win32 OpenGL 編程 ( 3 ) 基本圖元(點(diǎn),直線,多邊形)的繪制

write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie

討論新聞組及文件

一、 提要

在前面兩篇相關(guān)文章

Win32 OpenGL 編程(1)Win32下的OpenGL編程必須步驟

Win32 OpenGL編程(2) 尋找缺失的OpenGL函數(shù)

中,我們已經(jīng)建立了一個(gè)較為全面的 Win32 OpenGL 編程環(huán)境及一個(gè)簡(jiǎn)單的框架,并且,實(shí)際上掌握了 OpenGL Windows 下與 Win32 窗口交互的方法,在此基礎(chǔ)上,總算是可以正式進(jìn)行一些 OpenGL 相關(guān)知識(shí)的學(xué)習(xí),前面的那些也就算是熱身。本文的目的是將 OpenGL 中基本圖元(點(diǎn),線,多邊形)的繪制大概的講解一遍,最后可以組合的使用這些技術(shù)用 OpenGL 完成較為復(fù)雜的 2D 圖形。

二、 基本圖元相關(guān)概念

首先講講相關(guān)的概念,在 OpenGL 中,即使是復(fù)雜的圖形,實(shí)際上也是由一些非常基本的圖元組成,即點(diǎn),直線,多邊形,多邊形中用的較多的又是三角形和矩形。在數(shù)學(xué)中,兩點(diǎn)確定一條直線,三點(diǎn)確定一個(gè)三角形和一個(gè)面,同一個(gè)面上的四個(gè)點(diǎn)確定一個(gè)四邊形。。。。。。在 OpenGL 中也大致的利用此方式來(lái)確定直線和多邊形,也就是說(shuō),當(dāng)你想畫一個(gè)直線或者一個(gè)多邊形的時(shí)候,只需要告訴 OpenGL 能確定此直線或者多邊形的點(diǎn)即可。用參考 2 中的描述是:“在 OpenGL 中,所有的幾何物體最終都描述成一組有序的頂點(diǎn)”。有此基本的概念后就可以看下面的例子了。

三、 OpenGL Hello World 示例分析

這里的 Hello World 程序指的是一個(gè)利用 OpenGL 完成的矩形繪制程序,相對(duì)于在系列文章 1 中的 Win32 OpenGL 編程框架,簡(jiǎn)化了很多東西,只剩下最最基本的 OpenGL 元素,但也是一個(gè)完善的 OpenGL 示例了。此示例顯示的是一個(gè)白色的矩形,運(yùn)行效果如附圖 1 ,完整代碼見我博客代碼的 2009-10-12/SimpleRectangle 工程,具體下載及查看方法見本文最后的說(shuō)明。

此示例 OpenGL 相關(guān)的主要就是兩部分。

//OpenGL 初始化開始

void SceneInit ( int w , int h )

{

}

// 這里進(jìn)行所有的繪圖工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glBegin ( GL_QUADS );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glFlush ();

}

我們下面從 OpenGL 的角度來(lái)分析此程序。作為 HelloWorld 級(jí)的程序,我簡(jiǎn)化了很多東西,首先 OpenGL 的初始化省略了,用的都是 OpenGL 的默認(rèn)值,具體有哪些,后面一步一步說(shuō)。以下是按步驟說(shuō)明每個(gè) OpenGL 函數(shù)。

1. glClear

OpenGL 參考手冊(cè) :

glClear takes a single argument that is the bitwise OR of several values indicating which buffer is to be cleared.

GL_COLOR_BUFFER_BIT Indicates the buffers currently enabled for color writing.

作用是清除顏色緩沖區(qū)。類似于我們使用一塊新申請(qǐng)的內(nèi)存時(shí)先用 memset/ZeroMemory 去清零一下,用這樣的 Clear 操作為我們需要使用的顏色緩沖區(qū) (Color Buffer) 清零一下。假如沒有這樣的操作,以前留在顯存 / 內(nèi)存 ( 不確定 ) 中的值會(huì)影響我們的操作,并且,這樣的問(wèn)題往往是非常難以調(diào)試和發(fā)現(xiàn)的,這一點(diǎn)大家可以嘗試一下。

2. glBegin glEnd

OpenGL 參考手冊(cè) :

glBegin, glEnd - delimit the vertices of a primitive or a group of like primitives

OpenGL 代碼的主體部分是:

glBegin ( GL_QUADS );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glBegin glEnd 很明顯是一對(duì), 標(biāo)志著一組 OpenGL 操作的開始和結(jié)束。 并且在參數(shù)中告訴了 OpenGL 下面的操作是針對(duì)什么圖形進(jìn)行的,此例中 GL_QUADS 是表示四邊形。事實(shí)上還有很多其他的參數(shù)來(lái)表示各類圖形,在《 OpenGL Programming Guide 》的 此頁(yè) Figure 2-7 : Geometric Primitive Types 一圖形象的說(shuō)明了各個(gè)參數(shù)的作用。

3. glVertex *

glVertex3f 就是在 基本圖元相關(guān)概念 一節(jié)提到的 OpenGL 中確定頂點(diǎn)的函數(shù)。簡(jiǎn)而言之,上面的 4 glVertex3f 確定了矩形的 4 個(gè)頂點(diǎn)。(注意順序)然后, OpenGL 就會(huì)自動(dòng)根據(jù) glBegin 指定的參數(shù)去完成相關(guān)的繪制任務(wù)了, 此例中 GL_QUADS 是表示四邊形,所以最后的效果是一個(gè)矩形,實(shí)際的其他參數(shù)讀者可以自己嘗試一下。

4. OpenGL 默認(rèn)坐標(biāo)系

我們?cè)倏匆幌? glVertex* 指定頂點(diǎn)的代碼:

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

為什么上述就指定了一個(gè)矩形的四個(gè)頂點(diǎn)呢?需要說(shuō)明的是,在 OpenGL 中默認(rèn)坐標(biāo)體系與 Windows 中常用的不同, Windows 中常用的坐標(biāo)體系(僅 2D )是用戶區(qū)的左上角為坐標(biāo)原點(diǎn),即 (0.0,0.0) 點(diǎn),右為坐標(biāo)軸的 X 軸正方向,下為 Y 軸正方向, OpenGL 中的坐標(biāo)軸( 3D )默認(rèn)以客戶區(qū)中心點(diǎn)為坐標(biāo)原點(diǎn)( 0.0,0.0,0.0 ),右為坐標(biāo)軸的 X 軸正方向,上為 Y 軸正方向,垂直指出屏幕的方向?yàn)? Z 軸正方向。長(zhǎng)度定義是將客戶區(qū)范圍為按單位長(zhǎng)度定義,即整個(gè)客戶區(qū)恰好是 (-1,-1) (左下)到 (1,1) (右上)。附圖 2 是一個(gè)上述示例程序附上 OpenGL 的平面坐標(biāo)系的圖,也可以作為 OpenGL 默認(rèn)坐標(biāo)系的參考圖。

5. OpenGL 函數(shù)命名

這里順面介紹一下 OpenGL 函數(shù)的命名規(guī)范,因?yàn)? C 語(yǔ)言天生的弱點(diǎn)及豐富的數(shù)據(jù)類型,在 OpenGL 中凡是牽涉到與參數(shù)數(shù)量和數(shù)據(jù)類型相關(guān)的函數(shù),一般的命名方式都是 xxxx[n][t]

xxxx 表示函數(shù)的意義, [t] 用于表示此函數(shù)對(duì)應(yīng)的類型。一般用單個(gè)的字母表示參數(shù)的類型, s 表示 16 位整數(shù)( OpenGL 中將這個(gè)類型定義為 GLshort ), i 表示 32 位整數(shù)( OpenGL 中將這個(gè)類型定義為 GLint GLsizei ), f 表示 32 位浮點(diǎn)數(shù)( OpenGL 中將這個(gè)類型定義為 GLfloat ), d 表示 64 位浮點(diǎn)數(shù)( OpenGL 中將這個(gè)類型定義為 GLdouble )。此例中使用的是 32 位浮點(diǎn)數(shù),所以是 f 。這是 C 語(yǔ)言沒有函數(shù)重載機(jī)制的天生弱點(diǎn)導(dǎo)致的扭曲應(yīng)對(duì)方案。(用 C++ 就不需要這么麻煩了)

然后是數(shù)字,因?yàn)橥瑯拥脑颍? C 語(yǔ)言中一個(gè)同樣意義的函數(shù)不能同時(shí)有不同個(gè)數(shù)的參數(shù),所以 OpenGL 用一個(gè)數(shù)字來(lái)表示參數(shù)的個(gè)數(shù),此例中是 3 ,表示以 3 個(gè)參數(shù)(即點(diǎn)的 X,Y,Z 坐標(biāo))來(lái)表示頂點(diǎn)。(事實(shí)上還有 glVertex2* glVertex4*

比如此例中,用如下代碼效果是一樣的:

glVertex2f (-0.5, -0.5);

glVertex2f (0.5, -0.5);

glVertex2f (0.5, 0.5) ;

glVertex2f (-0.5, 0.5);

glVertex2f 中, Z 軸默認(rèn)為 0.

這里我依照參考 2 的用法,以 * 作為通配符來(lái)表示一組函數(shù), * 既可以表示代表參數(shù)數(shù)量的數(shù)字也可以表示代表類型的字母。

6. glFlush

OpenGL 參考手冊(cè) :

glFlush - force execution of GL commands in finite time

說(shuō)白了就是強(qiáng)制執(zhí)行已經(jīng)指定的 OpenGL 命令,與 fflush 命名類似作用也類似。

7. 小結(jié)

以上的 5 個(gè) OpenGL 函數(shù)就構(gòu)成了一個(gè)基本的 OpenGL 程序(不包括模板中使用的那些),由 glClear 清空顏色緩沖區(qū)獲得干凈的環(huán)境,由 glBegin 指定開始一組頂點(diǎn)操作的開始,并確認(rèn)繪制圖形,由 glVertex* 指定頂點(diǎn),由 glEnd 表示操作結(jié)束,由 glFlush 強(qiáng)制開始繪圖。運(yùn)行效果如附圖 1

四、 基本圖元

事實(shí)上,上一節(jié)已經(jīng)包含了所有的知識(shí),各個(gè)圖元在 OpenGL 中繪制方式的不同僅僅在于 glBegin 的參數(shù)不同而已,這里將基本圖元簡(jiǎn)單介紹一下。

1. 點(diǎn)

點(diǎn)是最常用的圖元之一了,而且所有的圖像都可以看做是由點(diǎn)構(gòu)成的,事實(shí)上屏幕也就是由一個(gè)一個(gè)像素點(diǎn)構(gòu)成了圖像:)

畫點(diǎn)的方式是使用 GL_POINTS 為參數(shù)調(diào)用 glBegin 。那么,每一個(gè) glVertex* 指定頂點(diǎn)就會(huì)繪制成一個(gè)單獨(dú)的點(diǎn)。點(diǎn)的默認(rèn)大小為 1 個(gè)像素,可以通過(guò) glPointSize 函數(shù)來(lái)改變點(diǎn)的大小,在點(diǎn)比較大并且沒有開啟抗鋸齒時(shí),是按照一個(gè)正方形來(lái)繪制的。比如上例中,僅僅將 GL_QUADS 換成 GL_POINTS ,將是繪制上述矩形的 4 個(gè)頂點(diǎn),為了截圖效果顯著,調(diào)用 glPointSize 將點(diǎn)的大小改為 20 。如下代碼:

// 這里進(jìn)行所有的繪圖工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glPointSize (20);

glBegin ( GL_POINTS );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glFlush ();

}

效果如附圖 3 所示。

光是點(diǎn)也可以做很多有趣的應(yīng)用, Windows 的屏保模擬星空即是其一,事實(shí)上,在原來(lái)學(xué)習(xí)簡(jiǎn)單的圖形編程時(shí),我用多種語(yǔ)言嘗試了用點(diǎn)做一些有意思的東西。見簡(jiǎn)單圖形編程學(xué)習(xí)系列:

簡(jiǎn)單圖形編程的學(xué)習(xí)( 2 --- 點(diǎn) (Qt 實(shí)現(xiàn) )

簡(jiǎn)單圖形編程的學(xué)習(xí)( 2 --- 點(diǎn) (Windows GDI 實(shí)現(xiàn) )

簡(jiǎn)單圖形編程的學(xué)習(xí)( 2 --- 點(diǎn) (small basic 實(shí)現(xiàn) )

其中點(diǎn)與文字結(jié)合形成的那個(gè)星空文字效果我是印象深刻,我一直將其作為“簡(jiǎn)單的編程技術(shù) + 創(chuàng)意”也能很強(qiáng)大的例子。

2. 直線

直線也是很基礎(chǔ)的東西了,但是 OpenGL 中的直線與數(shù)學(xué)概念上有些區(qū)別,不知道外國(guó)的那些專家在命名時(shí)為啥亂了,其實(shí) OpenGL 中的直線與數(shù)學(xué)中的線段概念一致,有兩個(gè)端點(diǎn)確認(rèn)長(zhǎng)度。事實(shí)上,在 OpenGL 繪制中,指定的也就是線段的兩個(gè)端點(diǎn)。用 GL_LINES 調(diào)用 glBegin 時(shí),表示繪制的是直線。默認(rèn)情況下寬度為一個(gè)像素,同樣, OpenGL 也提供了函數(shù) glLineWidth 用以改變直線的寬度。比如上例中,僅僅將 GL_QUADS 換成 GL_LINES 將是兩條平行的直線,并用 glLineWidth 將直線寬度改為 5 ,如下代碼:

// 這里進(jìn)行所有的繪圖工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glLineWidth (5);

glBegin ( GL_LINES );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glFlush ();

}

運(yùn)行效果如附圖 4 所示。

直線的應(yīng)用也是非常廣泛的,還記得 Windows 的屏保中的變幻線嗎?千變?nèi)f變,無(wú)論多么絢爛的效果,其實(shí)也僅僅是一條條變化的線段而已。

3. 多邊形

其實(shí)可以將多邊形看成是從點(diǎn)到線到面的一種擴(kuò)展,這里的面自然也是有范圍的,那么就成了多邊形了,在繪制圖形中用的最多的是三角形,因?yàn)槿切慰隙ㄔ谕粋€(gè)面上,這樣可以簡(jiǎn)化很多計(jì)算的處理。 GL_TRIANGLES 調(diào)用 glBegin 表示開始繪制三角形。然后還有 GL_QUADS 表示四邊形(上例中的用法), GL_POLYGON 表示多邊形(必須是凸的)。

4. 小結(jié)

其實(shí)除了上面講到的那些參數(shù),還有一些額外的參數(shù),比如 GL_LINE_STRIP,GL_TRIANGLES_STRIP 等,表示繪制的時(shí)候繪制一些列連續(xù)的圖形,這些參數(shù)用文字解釋起來(lái)不夠形象,還是推薦參考 OpenGL Programming Guide 》的 此頁(yè) Figure 2-7 : Geometric Primitive Types 一圖,此圖形象的展示了各個(gè)參數(shù)時(shí)對(duì)點(diǎn)的解釋方式和順序。在此圖的下面,還有個(gè)表總結(jié)了一下各個(gè)參數(shù)的作用。

在一個(gè) glBegin glEnd 對(duì)中可以連續(xù)的制定多個(gè)頂點(diǎn),甚至超出你指定的圖形的數(shù)目,比如繪制三角形時(shí)可以指定 6 個(gè)點(diǎn),那么此時(shí),將會(huì)繪制兩個(gè)三角形而不是一個(gè),這樣而當(dāng)指定 4 5 個(gè)點(diǎn)時(shí)用 GL_TRIANGLES 參數(shù)時(shí)將會(huì)丟棄,用 GL_TRIANGLE_STRIP 參數(shù)時(shí)將會(huì)連續(xù)繪制兩個(gè)三角形,具體的解釋方法也是要看 glBegin 參數(shù)的,建議還是參考上述圖片。

五、 參考資料

1. OpenGL Reference Manual 》, OpenGL 參考手冊(cè)

2. OpenGL 編程指南》(《 OpenGL Programming Guide 》), Dave Shreiner Mason Woo Jackie Neider Tom Davis 著,徐波譯,機(jī)械工業(yè)出版社

3. Nehe OpenGL Tutorials 》, Nehe 著,在 http://nehe.gamedev.net/ 上可以找到教程及相關(guān)的代碼下載,(有 PDF 版本教程下載) Nehe 自己還做了一個(gè)面向?qū)ο蟮目蚣埽鳛檠菔境绦騺?lái)說(shuō),這樣的框架非常合適。也有 中文版 ,各取所需吧。

4. OpenGL 入門學(xué)習(xí)》 eastcowboy 著,這是我在網(wǎng)上找到的一個(gè)比較好的教程,較為完善,而且非常通俗。這是第一篇的地址: http://bbs.pfan.cn/post-184355.html

六、 系列其他文章

1. Win32 OpenGL 編程(1)Win32下的OpenGL編程必須步驟

2. Win32 OpenGL編程(2) 尋找缺失的OpenGL函數(shù)

七、 最后說(shuō)明

本文中所有代碼(如果有的話)都能用 Mercurial Google Code 中下載。

文章以博文發(fā)表的日期分目錄存放,下載地址見:

http://code.google.com/p/jtianling/source/checkout?repo=blog-sample-code

或者直接使用 Mercurial 克隆下列庫(kù):

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial 使用方法見《 分布式的,新一代 版本控制系統(tǒng) Mercurial 的介紹及簡(jiǎn)要入門

八、 附圖

1. 1 SimpleRectangle

Win32 OpenGL編程(3) 基本圖元(點(diǎn),直線,多邊形)的繪制

圖2 SimpleRectangle with coordinate

Win32 OpenGL編程(3) 基本圖元(點(diǎn),直線,多邊形)的繪制

圖3 SimplePoints

Win32 OpenGL編程(3) 基本圖元(點(diǎn),直線,多邊形)的繪制

圖4 SimpleLines

Win32 OpenGL編程(3) 基本圖元(點(diǎn),直線,多邊形)的繪制

write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie

Win32 OpenGL編程(3) 基本圖元(點(diǎn),直線,多邊形)的繪制


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 闽清县| 清镇市| 北京市| 宁波市| 沁阳市| 瓦房店市| 奉贤区| 宜春市| 宜宾县| 兖州市| 清苑县| 阿拉善右旗| 桦南县| 小金县| 塔河县| 天津市| 定边县| 镇原县| 舞阳县| 西安市| 太和县| 盐池县| 扶绥县| 汉沽区| 额济纳旗| 类乌齐县| 景泰县| 增城市| 漳浦县| 谷城县| 凌云县| 新乡县| 阳西县| 竹溪县| 赤壁市| 鄂托克前旗| 白玉县| 庆元县| 承德县| 武强县| 海盐县|