Chapter4 颜色模式
无论哪种颜色模式,计算机都必须为每一个像素保存一些数据。不同的是,RGBA模式中,数据直接就代表了颜色;而颜色索引模式中,数据代表的是一个索引,要得到真正的颜色,还必须去查索引表。
4.1 RGBA模式
无论哪种颜色模式,计算机都必须为每一个像素保存一些数据。不同的是,RGBA模式中,数据直接就代表了颜色;而颜色索引模式中,数据代表的是一个索引,要得到真正的颜色,还必须去查索引表。
在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);
使用如下:
glColor3f(1.0f, 0.0f, 0.0f); // 表示不使用绿、蓝色,而将红色使用最多,于是得到最纯净的红色。
glColor3f(0.0f, 1.0f, 1.0f); // 表示使用绿、蓝色到最多,而不使用红色。混合的效果就是浅蓝色。
glColor3f(0.5f, 0.5f, 0.5f); // 表示各种颜色使用一半,效果为灰色。
示例代码:
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();
}
![image-20211229204104356](https://gitee.com/howard-jiahao/pic-bed/raw/master/img/image-20211229204104356.png)
注意:glColor系列函数,在参数类型不同时,表示“最大”颜色的值也不同。
采用f和d做后缀的函数,以1.0表示最大的使用。如果大于1的,与1没有区别。
采用b做后缀的函数,以127表示最大的使用。
采用ub做后缀的函数,以255表示最大的使用。
采用s做后缀的函数,以32767表示最大的使用。
采用us做后缀的函数,以65535表示最大的使用。
4.2 颜色索引模式
在索引颜色模式中,OpenGL需要一个颜色表。这个表就相当于画家的调色板:虽然可以调出很多种颜色,但同时存在于调色板上的颜色种数将不会超过调色板的格数。试将颜色表的每一项想象成调色板上的一个格子:它保存了一种颜色。
在使用索引颜色模式画图时,我说“我把第i种颜色设置为某某”,其实就相当于将调色板的第i格调为某某颜色。“我需要第k种颜色来画图”,那么就用画笔去蘸一下第k格调色板。
使用glIndex*
系列函数可以在颜色表中选择颜色。其中最常用的可能是glIndexi
,它的参数是一个整形。
void glIndexi(GLint c);
要使用索引颜色,需要另一个OpenGL工具包:aux(glaux)。
#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;
}
![image-20211229212541434](https://gitee.com/howard-jiahao/pic-bed/raw/master/img/image-20211229212541434.png)
若出现报错:LNK2019无法解析的外部符号 _sscanf,该符号在函数 _GetRegistrySysColors@8
项目属性->链接器->输入->附加依赖项中添加依赖项 legacy_stdio_definitions.lib
详情可见https://blog.csdn.net/qq_34911636/article/details/87096500
4.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);
glBegin(GL_LINE_LOOP);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.5f);
glVertex2f(0.5f, 0.5f);
glEnd();
glFlush();
}
glclear是用来清空屏幕的颜色,但是清空为什么颜色可以自己指定,可以用glClearColor来指定,这里注意需要先设置清空的颜色,然后再清空,如果反了就没有效果。
4.4 指定着色模型
在默认情况下,OpenGL会计算两点顶点之间的其它点,并为它们填上“合适”的颜色,使相邻的点的颜色值都比较接近。
-
如果使用的是RGB模式,看起来就具有渐变的效果。
-
如果是使用颜色索引模式,则其相邻点的索引值是接近的,如果将颜色表中接近的项设置成接近的颜色,则看起来也是渐变的效果。
#include <math.h>
#include <GL/glut.h>
const GLdouble Pi = 3.1415926536;
void myDisplay(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLE_FAN);
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();
}
使用glShadeModel
函数可以关闭这种计算,如果顶点的颜色不同,则将顶点之间的其它点全部设置为与某一个点相同。(直线以后指定的点的颜色为准,而多边形将以任意顶点的颜色为准,由实现决定。)为了避免这个不确定性,尽量在多边形中使用同一种颜色。
glShadeModel
的使用方法:
glShadeModel(GL_SMOOTH);
// 平滑方式,这也是默认方式glShadeModel(GL_FLAT);
// 单色方式