OpenGL入門學習(三)

2021-05-17 16:08:30 字數 3854 閱讀 9595

在第二課中,我們學習了如何繪製幾何圖形,但大家如果多寫幾個程式,就會發現其實還是有些鬱悶之處。例如:點太小,難以看清楚;直線也太細,不舒服;或者想畫虛線,但不知道方法只能用許多短直線,甚至用點組合而成。

這些問題將在本課中被解決。

下面就點、直線、多邊形分別討論。

1、關於點

點的大小預設為1個畫素,但也可以改變之。改變的命令為glpointsize,其函式原型如下:

void glpointsize(glfloat size);

size必須大於0.0f,預設值為1.0f,單位為「畫素」。

注意:對於具體的opengl實現,點的大小都有個限度的,如果設定的size超過最大值,則設定可能會有問題。

例子:

void mydisplay(void)

2、關於直線

(1)直線可以指定寬度:

void gllinewidth(glfloat width);

其用法跟glpointsize類似。

(2)畫虛線。

首先,使用glenable(gl_line_stipple);來啟動虛線模式(使用gldisable(gl_line_stipple)可以關閉之)。

然後,使用gllinestipple來設定虛線的樣式。

void gllinestipple(glint factor, glushort pattern);

pattern是由1和0組成的長度為16的序列,從最低位開始看,如果為1,則直線上接下來應該畫的factor個點將被畫為實的;如果為0,則直線上接下來應該畫的factor個點將被畫為虛的。

以下是一些例子:

宣告:該來自www.opengl.org,該是《opengl程式設計指南》一書的附圖,由於該書的舊版(第一版,2023年)已經流傳於網路,我希望沒有觸及到版權問題。

示例**:

void mydisplay(void)

3、關於多邊形

多邊形的內容較多,我們將講述以下四個方面。

(1)多邊形的兩面以及繪製方式。

雖然我們目前還沒有真正的使用三維座標來畫圖,但是建立一些三維的概念還是必要的。

從三維的角度來看,乙個多邊形具有兩個面。每乙個面都可以設定不同的繪製方式:填充、只繪製邊緣輪廓線、只繪製頂點,其中「填充」是預設的方式。可以為兩個面分別設定不同的方式。

glpolygonmode(gl_front, gl_fill);            // 設定正面為填充方式

glpolygonmode(gl_back, gl_line);             // 設定反面為邊緣繪製方式

glpolygonmode(gl_front_and_back, gl_point); // 設定兩面均為頂點繪製方式

(2)反轉

一般約定為「頂點以逆時針順序出現在螢幕上的面」為「正面」,另乙個麵即成為「反面」。生活中常見的物體表面,通常都可以用這樣的「正面」和「反面」,「合理的」被表現出來(請找乙個比較透明的礦泉水瓶子,在正對你的一面沿逆時針畫乙個圓,並標明畫的方向,然後將背面轉為正面,畫乙個類似的圓,體會一下「正面」和「反面」。你會發現正對你的方向,瓶的外側是正面,而背對你的方向,瓶的內側才是正面。正對你的內側和背對你的外側則是反面。這樣一來,同樣屬於「瓶的外側」這個表面,但某些地方算是正面,某些地方卻算是反面了)。

但也有一些表面比較特殊。例如「麥比烏斯帶」(請自己google一下),可以全部使用「正面」或全部使用「背面」來表示。

可以通過glfrontface函式來交換「正面」和「反面」的概念。

glfrontface(gl_ccw);   // 設定ccw方向為「正面」,ccw即counterclockwise,逆時針

glfrontface(gl_cw);    // 設定cw方向為「正面」,cw即clockwise,順時針

下面是乙個示例程式,請用它替換第一課中的mydisplay函式,並將glfrontface(gl_ccw)修改為glfrontface(gl_cw),並觀察結果的變化。

void mydisplay(void)

(3)剔除多邊形表面

在三維空間中,乙個多邊形雖然有兩個面,但我們無法看見背面的那些多邊形,而一些多邊形雖然是正面的,但被其他多邊形所遮擋。如果將無法看見的多邊形和可見的多邊形同等對待,無疑會降低我們處理圖形的效率。在這種時候,可以將不必要的面剔除。

首先,使用glenable(gl_cull_face);來啟動剔除功能(使用gldisable(gl_cull_face)可以關閉之)

然後,使用glcullface來進行剔除。

glcullface的引數可以是gl_front,gl_back或者gl_front_and_back,分別表示剔除正面、剔除反面、剔除正反兩面的多邊形。

注意:剔除功能只影響多邊形,而對點和直線無影響。例如,使用glcullface(gl_front_and_back)後,所有的多邊形都將被剔除,所以看見的就只有點和直線。

(4)鏤空多邊形

直線可以被畫成虛線,而多邊形則可以進行鏤空。

首先,使用glenable(gl_polygon_stipple);來啟動鏤空模式(使用gldisable(gl_polygon_stipple)可以關閉之)。

然後,使用glpolygonstipple來設定鏤空的樣式。

void glpolygonstipple(const glubyte *mask);

其中的引數mask指向乙個長度為128位元組的空間,它表示了乙個32*32的矩形應該如何鏤空。其中:第乙個位元組表示了最左下方的從左到右(也可以是從右到左,這個可以修改)8個畫素是否鏤空(1表示不鏤空,顯示該畫素;0表示鏤空,顯示其後面的顏色),最後乙個位元組表示了最右上方的8個畫素是否鏤空。

但是,如果我們直接定義這個mask陣列,像這樣:

static glubyte mask[128] =

;

這樣一堆資料非常缺乏直觀性,我們需要很費勁的去分析,才會發現它表示的竟然是乙隻蒼蠅。

首先,用windows自帶的畫筆程式新建一副,取名為mask.bmp,注意儲存時,應該選擇「單色位圖」。在「圖象」->「屬性」對話方塊中,設定的高度和寬度均為32。

然後,就可以使用以下**來獲得這個mask陣列了。

static glubyte mask[128];

file *fp;

fp = fopen("mask.bmp", "rb");

if( !fp )

exit(0);

// 移動檔案指標到這個位置,使得再讀sizeof(mask)個位元組就會遇到檔案結束

// 注意-(int)sizeof(mask)雖然不是什麼好的寫法,但這裡它確實是正確有效的

// 如果直接寫-sizeof(mask)的話,因為sizeof取得的是乙個無符號數,取負號會有問題

if( fseek(fp, -(int)sizeof(mask), seek_end) )

exit(0);

// 讀取sizeof(mask)個位元組到mask

if( !fread(mask, sizeof(mask), 1, fp) )

exit(0);

fclose(fp);

說明:繪製虛線時可以設定factor因子,但多邊形的鏤空無法設定factor因子。請用滑鼠改變視窗的大小,觀察鏤空效果的變化情況。

#include

#include

void mydisplay(void)

小結

本課學習了繪製幾何圖形的一些細節。

點可以設定大小。

直線可以設定寬度;可以將直線畫成虛線。

多邊形的兩個面的繪製方法可以分別設定;在三維空間中,不可見的多邊形可以被剔除;可以將填充多邊形繪製成鏤空的樣式。

了解這些細節會使我們在一些圖象繪製中更加得心應手。

另外,把一些資料寫到程式之外的檔案中,並用專門的工具編輯之,有時可以顯得更方便。

OpenGL入門學習 三

出處 在第二課中,我們學習了如何繪製幾何圖形,但大家如果多寫幾個程式,就會發現其實還是有些鬱悶之處。例如 點太小,難以看清楚 直線也太細,不舒服 或者想畫虛線,但不知道方法只能用許多短直線,甚至用點組合而成。這些問題將在本課中被解決。下面就點 直線 多邊形分別討論。1 關於點 點的大小預設為1個畫素...

OpenGL入門學習筆記(三)

從三維的角度來看,乙個多邊形具有兩個面。每乙個面都可以設定不同的繪製方式 填充 只繪製邊緣輪廓線 只繪製頂點 其中 填充 是預設的方式。可以為兩個面分別設定不同的方式。glpolygonmode的原型是 void glpolygonmode glenum face,glenum mode 用於控制多...

OpenGL入門學習

include 太陽 地球和月亮 假設每個月都是30天 一年12個月,共是360天 static int day 200 day的變化 從0到359 void mydisplay void void myidle void int main int argc,char argv 3 關於垂直同步co...