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或范围之内。因此,灵活使用这些后缀,会给你编程带来很大的方便。
后缀 | 数据类型 | 最小值 | 最小值映射 | 最大值 | 最大值映射 |
b | 1字节整型数 | -128 | -1.0 | 127 | 1.0 |
s | 2字节整型数 | -32,768 | -1.0 | 32,767 | 1.0 |
i | 4字节整型数 | -2,147,483,648 | -1.0 | 2,147,483,647 | 1.0 |
ub | 1字节无符号整型数 | 0 | 0.0 | 255 | 1.0 |
us | 2字节无符号整型数 | 0 | 0.0 | 65,535 | 1.0 |
ui | 4字节无符号整型数 | 0 | 0.0 | 4,294,967,295 | 1.0 |
表9-1 整型颜色值到浮点数的转换 |
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 自定义调色板 |