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 的参数值,绘制不同颜色的矩形。
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0f, 1.0f, 1.0f);
glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
glFlush();
}
注意:glColor 系列函数,在参数类型不同时,表示“最大”颜色的值也不同。
采用 f 和 d 做后缀的函数,以 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 自带的,不必另外安装,但
它已经过时,这里仅仅是体验一下,大家不必深入。
#include <windows.h>
#include <GL/gl.h>
#include <GL/glaux.h>
#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glaux.lib")
#include <math.h>
const GLdouble Pi = 3.1415926536;
void myDisplay(void)
{
int i;
for(i=0; i<8; ++i)
auxSetOneColor(i, (float)(i&0x04), (float)(i&0x02), (float)(i&0x01));
glShadeModel(GL_FLAT);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0.0f, 0.0f);
for(i=0; i<=8; ++i)
{
glIndexi(i);
glVertex2f(cos(i*Pi/4), sin(i*Pi/4));
}
glEnd();
glFlush();
}
int main(void)
{
auxInitDisplayMode(AUX_SINGLE|AUX_INDEX);
auxInitPosition(0, 0, 400, 400);
auxInitWindow(L"");
myDisplay();
Sleep(10 * 1000);
return 0;
}
其它部分大家都可以不管,只看 myDisplay 函数就可以了。首先,使用 auxSetOneColor 设置颜色表中的一
格。循环八次就可以设置八格。
glShadeModel 等下再讲,这里不提。
然后在循环中用 glVertex设置顶点,同时用 glIndexi 改变顶点代表的颜色。
最终得到的效果是八个相同形状、不同颜色的三角形。
索引颜色虽然讲得多了点。索引颜色的主要优势是占用空间小(每个像素不必单独保存自己的颜色,只用
很少的二进制位就可以代表其颜色在颜色表中的位置) ,花费系统资源少,图形运算速度快,但它编程稍稍
显得不是那么方便,并且画面效果也会比 RGB 颜色差一些。“星际争霸”可能代表了 256 色的颜色表的画面
效果,虽然它在一台很烂的 PC 上也可以运行很流畅,但以目前的眼光来看,其画面效果就显得不足了。
目前的 PC 机性能已经足够在各种场合下使用 RGB 颜色,因此 PC 程序开发中,使用索引颜色已经不是主
流。当然,一些小型设备例如 GBA、手机等,索引颜色还是有它的用武之地。
3、指定清除屏幕用的颜色
我们写:glClear(GL_COLOR_BUFFER_BIT);意思是把屏幕上的颜色清空。
但实际上什么才叫“空”呢?在宇宙中,黑色代表了“空”;在一张白纸上,白色代表了“空”;在信封上,信
封的颜色才是“空”。
OpenGL 用下面的函数来定义清楚屏幕后屏幕所拥有的颜色。
在 RGB 模式下,使用 glClearColor 来指定“空”的颜色,它需要四个参数,其参数的意义跟 glColor4f 相似。
在索引颜色模式下,使用 glClearIndex来指定“空”的颜色所在的索引,它需要一个参数,其意义跟 glIndexi
相似。
void myDisplay(void)
{
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
呵,这个还真简单~
4、指定着色模型
OpenGL 允许为同一多边形的不同顶点指定不同的颜色。例如:
#include <math.h>
const GLdouble Pi = 3.1415926536;
void myDisplay(void)
{
int i;
// glShadeModel(GL_FLAT);
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(0.0f, 0.0f);
for(i=0; i<=8; ++i)
{
glColor3f(i&0x04, i&0x02, i&0x01);
glVertex2f(cos(i*Pi/4), sin(i*Pi/4));
}
glEnd();
glFlush();
}
在默认情况下,OpenGL 会计算两点顶点之间的其它点,并为它们填上“合适”的颜色,使相邻的点的颜色值
都比较接近。如果使用的是 RGB 模式,看起来就具有渐变的效果。如果是使用颜色索引模式,则其相邻点
的索引值是接近的,如果将颜色表中接近的项设置成接近的颜色,则看起来也是渐变的效果。但如果颜色
表中接近的项颜色却差距很大,则看起来可能是很奇怪的效果。
使用 glShadeModel 函数可以关闭这种计算,如果顶点的颜色不同,则将顶点之间的其它点全部设置为与某
一个点相同。 (直线以后指定的点的颜色为准,而多边形将以任意顶点的颜色为准,由实现决定。 )为了避
免这个不确定性,尽量在多边形中使用同一种颜色。
glShadeModel 的使用方法:
glShadeModel(GL_SMOOTH); // 平滑方式,这也是默认方式
glShadeModel(GL_FLAT); // 单色方式
小结:
本课学习了如何设置颜色。其中 RGB 颜色方式是目前 PC 机上的常用方式。
可以设置 glClear 清除后屏幕所剩的颜色。
可以设置颜色填充方式:平滑方式或单色方式