OpenGL(四)之顏色篇


本次學習的是顏色的選擇。終於要走出黑白的世界了~~


OpenGL支持兩種顏色模式:一種是RGBA,一種是顏色索引模式
無論哪種顏色模式,計算機都必須為每一個像素保存一些數據。不同的是,RGBA模式中,數據直接就代表了顏色;而顏色索引模式中,數據代表的是一個索引,要得到真正的顏色,還必須去查索引表。

1. RGBA顏色
RGBA模式中,每一個像素會保存以下數據:R值(紅色分量)、G值(綠色分量)、B值(藍色分量)和A值(alpha分量)。其中紅、綠、藍三種顏色相組合,就可以得到我們所需要的各種顏色,而alpha不直接影響顏色,它將留待以后介紹。
在RGBA模式下選擇顏色是十分簡單的事情,只需要一個函數就可以搞定。
glColor*系列函數可以用於設置顏色,其中三個參數的版本可以指定R、G、B的值,而A值采用默認;四個參數的版本可以分別指定R、G、B、A的值。例如:
void glColor3f(GLfloat red, GLfloat green, GLfloat blue);
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
(還記得嗎?3f表示有三個浮點參數~請看第二課中關於glVertex*函數的敘述。)
將浮點數作為參數,其中0.0表示不使用該種顏色,而1.0表示將該種顏色用到最多。例如:
glColor3f(1.0f, 0.0f, 0.0f);    表示不使用綠、藍色,而將紅色使用最多,於是得到最純凈的紅色。
glColor3f(0.0f, 1.0f, 1.0f);    表示使用綠、藍色到最多,而不使用紅色。混合的效果就是淺藍色。
glColor3f(0.5f, 0.5f, 0.5f);    表示各種顏色使用一半,效果為灰色。
注意:浮點數可以精確到小數點后若干位,這並不表示計算機就可以顯示如此多種顏色。實際上,計算機可以顯示的顏色種數將由硬件決定。如果OpenGL找不到精確的顏色,會進行類似“四舍五入”的處理。

大家可以通過改變下面代碼中glColor3f的參數值,繪制不同顏色的矩形。

1 void myDisplay(void)
2 {
3      glClear(GL_COLOR_BUFFER_BIT);
4      glColor3f(0.0f, 1.0f, 1.0f);
5      glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
6      glFlush();
7 }


效果:


注意:glColor系列函數,在參數類型不同時,表示“最大”顏色的值也不同。
采用fd做后綴的函數,以1.0表示最大的使用。
采用b做后綴的函數,以127表示最大的使用。
采用ub做后綴的函數,以255表示最大的使用。
采用s做后綴的函數,以32767表示最大的使用。
采用us做后綴的函數,以65535表示最大的使用。
這些規則看似麻煩,但熟悉后實際使用中不會有什么障礙。

2、索引顏色
在索引顏色模式中,OpenGL需要一個顏色表。這個表就相當於畫家的調色板:雖然可以調出很多種顏色,但同時存在於調色板上的顏色種數將不會超過調色板的格數。試將顏色表的每一項想象成調色板上的一個格子:它保存了一種顏色。
在使用索引顏色模式畫圖時,我說“我把第i種顏色設置為某某”,其實就相當於將調色板的第i格調為某某顏色。“我需要第k種顏色來畫圖”,那么就用畫筆去蘸一下第k格調色板。
顏色表的大小是很有限的,一般在256~4096之間,且總是2的整數次冪。在使用索引顏色方式進行繪圖時,總是先設置顏色表,然后選擇顏色。

2.1、選擇顏色
使用glIndex*系列函數可以在顏色表中選擇顏色。其中最常用的可能是glIndexi,它的參數是一個整形。
void glIndexi(GLint c);
是的,這的確很簡單。

2.2、設置顏色表
OpenGL 並直接沒有提供設置顏色表的方法,因此設置顏色表需要使用操作系統的支持。我們所用的Windows和其他大多數圖形操作系統都具有這個功能,但所使用的 函數卻不相同。正如我沒有講述如何自己寫代碼在Windows下建立一個窗口,這里我也不會講述如何在Windows下設置顏色表。
GLUT工具 包提供了設置顏色表的函數glutSetColor,但我測試始終有問題。現在為了讓大家體驗一下索引顏色,我向大家介紹另一個OpenGL工具包: aux。這個工具包是VisualStudio自帶的,不必另外安裝,但它已經過時,這里僅僅是體驗一下,大家不必深入。

 1 #include <windows.h>
 2 #include <GL/glut.h>    
 3 #include <GL/glaux.h>
 4 
 5 #pragma comment (lib, "opengl32.lib")
 6 #pragma comment (lib, "glaux.lib")
 7 
 8 #include <math.h>
 9 const GLdouble Pi = 3.1415926536;
10 void myDisplay(void)
11 {
12      int i;
13      for(i=0; i<8; ++i)
14          auxSetOneColor(i, (float)(i&0x04), (float)(i&0x02), (float)(i&0x01));
15      glShadeModel(GL_FLAT);
16      glClear(GL_COLOR_BUFFER_BIT);
17      glBegin(GL_TRIANGLE_FAN);
18      glVertex2f(0.0f, 0.0f);
19      for(i=0; i<=8; ++i)
20      {
21          glIndexi(i);
22          glVertex2f(cos(i*Pi/4), sin(i*Pi/4));
23      }
24      glEnd();
25      glFlush();
26 }
27 
28 int main(void)
29 {
30      auxInitDisplayMode(AUX_SINGLE|AUX_INDEX);
31      auxInitPosition(0, 0, 400, 400);
32      auxInitWindow(L"");
33      myDisplay();
34      Sleep(10 * 1000);
35      return 0;
36 }

 

效果:

其它部分大家都可以不管,只看myDisplay函數就可以了。首先,使用auxSetOneColor設置顏色表中的一格。循環八次就可以設置八格。
glShadeModel等下再講,這里不提。
然后在循環中用glVertex設置頂點,同時用glIndexi改變頂點代表的顏色。
最終得到的效果是八個相同形狀、不同顏色的三角形。

索 引顏色雖然講得多了點。索引顏色的主要優勢是占用空間小(每個像素不必單獨保存自己的顏色,只用很少的二進制位就可以代表其顏色在顏色表中的位置),花費 系統資源少,圖形運算速度快,但它編程稍稍顯得不是那么方便,並且畫面效果也會比RGB顏色差一些。“星際爭霸”可能代表了256色的顏色表的畫面效果, 雖然它在一台很爛的PC上也可以運行很流暢,但以目前的眼光來看,其畫面效果就顯得不足了。
目前的PC機性能已經足夠在各種場合下使用RGB顏色,因此PC程序開發中,使用索引顏色已經不是主流。當然,一些小型設備例如GBA、手機等,索引顏色還是有它的用武之地。


3、指定清除屏幕用的顏色
我們寫:glClear(GL_COLOR_BUFFER_BIT);意思是把屏幕上的顏色清空。
但實際上什么才叫“空”呢?在宇宙中,黑色代表了“空”;在一張白紙上,白色代表了“空”;在信封上,信封的顏色才是“空”。
OpenGL用下面的函數來定義清楚屏幕后屏幕所擁有的顏色。
在RGB模式下,使用glClearColor來指定“空”的顏色,它需要四個參數,其參數的意義跟glColor4f相似。
在索引顏色模式下,使用glClearIndex來指定“空”的顏色所在的索引,它需要一個參數,其意義跟glIndexi相似。

1 void myDisplay(void)
2 {
3      glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
4      glClear(GL_COLOR_BUFFER_BIT);
5      glFlush();
6 }

效果:


呵,這個還真簡單~


4、指定着色模型
OpenGL允許為同一多邊形的不同頂點指定不同的顏色。例如:

 1 #include <math.h>
 2 const GLdouble Pi = 3.1415926536;
 3 void myDisplay(void)
 4 {
 5      int i;
 6      // glShadeModel(GL_FLAT);
 7      glClear(GL_COLOR_BUFFER_BIT);
 8      glBegin(GL_TRIANGLE_FAN);
 9      glColor3f(1.0f, 1.0f, 1.0f);
10      glVertex2f(0.0f, 0.0f);
11      for(i=0; i<=8; ++i)
12      {
13          glColor3f(i&0x04, i&0x02, i&0x01);
14          glVertex2f(cos(i*Pi/4), sin(i*Pi/4));
15      }
16      glEnd();
17      glFlush();
18 }

效果:


在 默認情況下,OpenGL會計算兩點頂點之間的其它點,並為它們填上“合適”的顏色,使相鄰的點的顏色值都比較接近。如果使用的是RGB模式,看起來就具 有漸變的效果。如果是使用顏色索引模式,則其相鄰點的索引值是接近的,如果將顏色表中接近的項設置成接近的顏色,則看起來也是漸變的效果。但如果顏色表中 接近的項顏色卻差距很大,則看起來可能是很奇怪的效果。
使用glShadeModel函數可以關閉這種計算,如果頂點的顏色不同,則將頂點之間的其它點全部設置為與某一個點相同。(直線以后指定的點的顏色為准,而多邊形將以任意頂點的顏色為准,由實現決定。)為了避免這個不確定性,盡量在多邊形中使用同一種顏色。
glShadeModel的使用方法:
glShadeModel(GL_SMOOTH);    // 平滑方式,這也是默認方式
glShadeModel(GL_FLAT);      // 單色方式

 

對於上面的代碼運用帶色模式效果如下:

 


小結:
本課學習了如何設置顏色。其中RGB顏色方式是目前PC機上的常用方式。
可以設置glClear清除后屏幕所剩的顏色。
可以設置顏色填充方式:平滑方式或單色方式。

=====================    第四課 完    =====================
=====================TO BE CONTINUED=====================


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM