1. 程式人生 > >OpenGL基礎圖形程式設計(九)OpenGL顏色

OpenGL基礎圖形程式設計(九)OpenGL顏色

九、OpenGL顏色

  幾乎所有OpenGL應用目的都是在螢幕視窗內繪製彩色圖形,所以顏色在OpenGL程式設計中佔有很重要的地位。這裡的顏色與繪畫中的顏色概念不一樣,它屬於RGB顏色空間,只在監視器螢幕上顯示。另外,螢幕視窗座標是以象素為單位,因此組成圖形的每個象素都有自己的顏色,而這種顏色值是通過對一系列OpenGL函式命令的處理最終計算出來的。本章將講述計算機顏色的概念以及OpenGL的顏色模式、顏色定義和兩種模式應用場合等內容,若掌握好顏色的應用,你就能走進繽紛絢麗的色彩世界,從中享受無窮的樂趣。

9.1、計算機顏色

9.1.1 顏色生成原理

  計算機顏色不同於繪畫或印刷中的顏色,顯示於計算機螢幕上每一個點的顏色都是由監視器內部的電子槍激發的三束不同顏色的光(紅、綠、藍)混合而成,因此,計算機顏色通 常用R(
Red)、G(Green)、B(Blue)三個值來表示,這三個值又稱為顏色分量。顏色生成原理 示意圖見圖9-1所示。

圖9-1 計算機顏色生成原理

9.1.2 RGB色立體RGB Color Cube
  所有監視器螢幕的顏色都屬於RGB顏色空間,如果用一個立方體形象地表示RGB顏色組成關係,那麼就稱這個立方體為RGB色立體,如圖9-2所示。

圖9-2 RGB色立體

  在圖中,R、G、B三值的範圍都是從0.0到1.0。如果某顏色分量越大,則表示對應的顏色分量越亮,也就是它在此點所貢獻的顏色成分越多;反之,則越暗或越少。當R、G、B三個值都為0.0時,此點顏色為黑色(Black);當三者都為1.0時,此點顏色為白色(

White);當三個顏色分量值相等時,表示三者貢獻一樣,因此呈現灰色(Grey),在圖中表現為從黑色頂點到白色頂點的那條對角線;當R=1.0、G=1.0、B=0.0時,此點顏色為黃色(Yellow);同理,R=1.0、G=0.0、B=1.0時為洋紅色,也叫品色(Magenta);R=0.0、G=1.0、B=1.0時為青色(Cyan)。

9.2、顏色模式
  OpenGL顏色模式一共有兩個:RGB(RGBA)模式和顏色表模式。在RGB模式下,所有的顏色定義全用R、G、B三個值來表示,有時也加上 Alpha值(與透明度有關),即RGBA模式。在顏色表模式下,每一個象素的顏色是用顏色表中的某個顏色索引值表示,而這個索引值指向了相應的R、G、 B值。這樣的一個表成為顏色對映(
Color Map)。

9.2.1 RGBA模式RGBA Mode
  在RGBA模式下,可以用glColor*()來定義當前顏色。其函式形式為:
    void glColor3{b s i f d ub us ui}(TYPE r,TYPE g,TYPE b);
  void glColor4{b s i f d ub us ui}(TYPE r,TYPE g,TYPE b,TYPE a);
  void glColor3{b s i f d ub us ui}v(TYPE *v);
  void glColor4{b s i f d ub us ui}v(TYPE *v);
  設定當前R、G、B和A值。這個函式有3和4兩種方式,在前一種方式下,a值預設為1.0,後一種Alpha值由使用者自己設定,範圍從0.0到1.0。同樣,它也可用指標傳遞引數。另外,函式的第二個字尾的不同使用,其相應的引數值及範圍不同,見下表9-1所示。雖然這些引數值不同,但實際上 OpenGL已自動將它們對映在0.0到1.0或-1.0或範圍之內。因此,靈活使用這些字尾,會給你程式設計帶來很大的方便。


9.2.2 顏色表模式Color_Index Mode
  在顏色表方式下,可以呼叫glIndex*()函式從顏色表中選取當前顏色。其函式形式為:
void glIndex{sifd}(TYPE c);
void glIndex{sifd}v(TYPE *c);
  設定當前顏色索引值,即調色盤號。若值大於顏色位面數時則取模。

9.2.3 兩種模式應用場合
  在大多情況下,採用RGBA模式比顏色表模式的要多,尤其許多效果處理,如陰影、光照、霧、反走樣、混合等,採用RGBA模式效果會更好些;另外,紋理對映只能在RGBA模式下進行。下面提供幾種運用顏色表模式的情況(僅供參考):
  1)若原來應用程式採用的是顏色表模式則轉到OpenGL上來時最好仍保持這種模式,便於移植。
  2)若所用顏色不在預設提供的顏色許可範圍之內,則採用顏色表模式。

  3)在其它許多特殊處理,如顏色動畫,採用這種模式會出現奇異的效果。

9.3、顏色應用舉例
  顏色是一個極具吸引力的應用,在前面幾章中已經逐步介紹了RGBA模式的應用方式,這裡就不再多述。下面著重說一下顏色表模式的應用方法,請看例程:
例9-1 顏色表應用例程cindex.c
#include "glos.h"
  #include <GL/gl.h>
  #include <GL/glaux.h>

  void myinit(void);
  void InitPalette(void);
  void DrawColorFans(void);
  void CALLBACK myReshape(GLsizei w,GLsizei h);
  void CALLBACK display(void);

  void myinit(void)
  {
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glShadeModel(GL_FLAT);
  }

  void InitPalette(void)
  {
    GLint j;
    static GLfloat rgb[][3]={
      {1.0,0.0,0.0},{1.0,0.0,0.5},{1.0,0.0,1.0},{0.0,0.0,1.0},
      {0.0,1.0,1.0},{0.0,1.0,0.0},{1.0,1.0,0.0},{1.0,0.5,0.0}};

    for(j=0;j<8;j++)
      auxSetOneColor(j+1,rgb[j][0],rgb[j][1],rgb[j][2]);
  }

  void CALLBACK myReshape(GLsizei w,GLsizei h)
  {
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if(w<=h)
      glOrtho(-12.0,12.0,-12.0*(GLfloat)h/(GLfloat)w, 12.0*(GLfloat)h/(GLfloat)w,-30.0,30.0);
    else
      glOrtho(-12.0*(GLfloat)h/(GLfloat)w, 12.0*(GLfloat)h/(GLfloat)w,-12.0,12.0,-30.0,30.0); 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
  }

  void CALLBACK display(void)
  {
    InitPalette();
    DrawColorFans();
    glFlush();
  }

  void DrawColorFans(void)
  {
    GLint n;
    GLfloat pp[8][2]={
      {7.0,-7.0},{0.0,-10.0},{-7.0,-7.0},{-10.0,0.0},
      {-7.0,7.0}, {0.0,10.0},{7.0,7.0},{10.0,0.0}};

    /* draw some filled_fan_triangles */
    glBegin(GL_TRIANGLE_FAN);
      glVertex2f(0.0,0.0);
      glVertex2f(10.0,0.0);
      for(n=0;n<8;n++)
      {
        glIndexi(n+1);
        glVertex2fv(pp[n]);
      }
    glEnd();
  }

  void main(void)
  {
    auxInitDisplayMode(AUX_SINGLE|AUX_INDEX);
    auxInitPosition(0,0,500,500);
    auxInitWindow("Color Index");
    myinit();
    auxReshapeFunc(myReshape);
    auxMainLoop(display);
  }
  這個程式執行結果是在螢幕上顯示八個連成扇形的不同顏色的三角形,每個三角形的顏色定義採用顏色表模式。其中,呼叫了輔助庫函式auxSetOneColor()來裝載顏色對映表,即調色盤。因為將某個顏色裝載到顏色查詢表(color lookup table)中的過程必須依賴視窗系統,而OpenGL函式與視窗系統無關,所以這裡就呼叫輔助庫的函式來完成這個過程,然後才呼叫OpenGL自己的函式glIndex()設定當前的顏色號。

圖9-3 自定義調色盤