OpenGL筆記2.2 鏤空

來源:互聯網
上載者:User

標籤:blog   http   io   color   ar   os   使用   sp   檔案   

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

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

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

1、關於點

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

void glPointSize(GLfloat size);

size必須大於0.0f,預設值為1.0f,單位為“像素”。

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

例子:

void myDisplay(void)

{

     glClear(GL_COLOR_BUFFER_BIT);

     glPointSize(5.0f);

     glBegin(GL_POINTS);

         glVertex2f(0.0f, 0.0f);

         glVertex2f(0.5f, 0.5f);

     glEnd();

     glFlush();

}

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個點將被畫為虛的。

以下是一些例子:

範例程式碼:

void myDisplay(void)

{

     glClear(GL_COLOR_BUFFER_BIT);

     glEnable(GL_LINE_STIPPLE);

     glLineStipple(2, 0x0F0F);

     glLineWidth(10.0f);

     glBegin(GL_LINES);

         glVertex2f(0.0f, 0.0f);

         glVertex2f(0.5f, 0.5f);

     glEnd();

     glFlush();

}

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)

{

     glClear(GL_COLOR_BUFFER_BIT);

     glPolygonMode(GL_FRONT, GL_FILL); // 設定正面為填充模式

     glPolygonMode(GL_BACK, GL_LINE);   // 設定反面為線形模式

     glFrontFace(GL_CCW);               // 設定逆時針方向為正面

     glBegin(GL_POLYGON);               // 按逆時針繪製一個正方形,在左下方

         glVertex2f(-0.5f, -0.5f);

         glVertex2f(0.0f, -0.5f);

         glVertex2f(0.0f, 0.0f);

         glVertex2f(-0.5f, 0.0f);

     glEnd();

     glBegin(GL_POLYGON);               // 按順時針繪製一個正方形,在右上方

         glVertex2f(0.0f, 0.0f);

         glVertex2f(0.0f, 0.5f);

         glVertex2f(0.5f, 0.5f);

         glVertex2f(0.5f, 0.0f);

     glEnd();

     glFlush();

}

(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] =

{

     0x00, 0x00, 0x00, 0x00,    //   這是最下面的一行

     0x00, 0x00, 0x00, 0x00,

     0x03, 0x80, 0x01, 0xC0,    //   麻

     0x06, 0xC0, 0x03, 0x60,    //   煩

     0x04, 0x60, 0x06, 0x20,    //   的

     0x04, 0x30, 0x0C, 0x20,    //   初

     0x04, 0x18, 0x18, 0x20,    //   始

     0x04, 0x0C, 0x30, 0x20,    //   化

     0x04, 0x06, 0x60, 0x20,    //   ,

     0x44, 0x03, 0xC0, 0x22,    //   不

     0x44, 0x01, 0x80, 0x22,    //   建

     0x44, 0x01, 0x80, 0x22,    //   議

     0x44, 0x01, 0x80, 0x22,    //   使

     0x44, 0x01, 0x80, 0x22,    //   用

     0x44, 0x01, 0x80, 0x22,

     0x44, 0x01, 0x80, 0x22,

     0x66, 0x01, 0x80, 0x66,

     0x33, 0x01, 0x80, 0xCC,

     0x19, 0x81, 0x81, 0x98,

     0x0C, 0xC1, 0x83, 0x30,

     0x07, 0xE1, 0x87, 0xE0,

     0x03, 0x3F, 0xFC, 0xC0,

     0x03, 0x31, 0x8C, 0xC0,

     0x03, 0x3F, 0xFC, 0xC0,

     0x06, 0x64, 0x26, 0x60,

     0x0C, 0xCC, 0x33, 0x30,

     0x18, 0xCC, 0x33, 0x18,

     0x10, 0xC4, 0x23, 0x08,

     0x10, 0x63, 0xC6, 0x08,

     0x10, 0x30, 0x0C, 0x08,

     0x10, 0x18, 0x18, 0x08,

     0x10, 0x00, 0x00, 0x08    // 這是最上面的一行

};

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

如果將這樣的資料儲存成圖片,並用專門的工具進行編輯,顯然會方便很多。下面介紹如何做到這一點。

首先,用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);

好的,現在請自己編輯一個圖片作為mask,並用上述方法取得Mask數組,運行後觀察效果。

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

#include <stdio.h>

#include <stdlib.h>

void myDisplay(void)

{

     static GLubyte Mask[128];

     FILE *fp;

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

     if( !fp )

         exit(0);

     if( fseek(fp, -(int)sizeof(Mask), SEEK_END) )

         exit(0);

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

         exit(0);

     fclose(fp);

     glClear(GL_COLOR_BUFFER_BIT);

     glEnable(GL_POLYGON_STIPPLE);

     glPolygonStipple(Mask);

     glRectf(-0.5f, -0.5f, 0.0f, 0.0f);   // 在左下方繪製一個有鏤空效果的正方形

     glDisable(GL_POLYGON_STIPPLE);

     glRectf(0.0f, 0.0f, 0.5f, 0.5f);     // 在右上方繪製一個無鏤空效果的正方形

     glFlush();

}

小結

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

點可以設定大小。

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

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

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

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

=====================    第三課 完    =====================

=====================TO BE CONTINUED=====================

OpenGL筆記2.2 鏤空

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.