图元的颜色属性

图元有两种颜色的存储方式:颜色模型和颜色表

颜色模型,就是把颜色直接存储到帧缓存中,在显示时直接显示出颜色。
颜色表,则是在帧缓存中存储一个颜色的索引,显示时显示索引的颜色。
相比于颜色模型,颜色表更加节省空间(一般需要的颜色数目不多),而且更改某种特定颜色更为容易。

颜色模型

颜色模型已经比较熟悉了(以前用的glColor3d),这里就不多赘述。
值得一提的是,类似于顶点数组,我们也有颜色数组

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(nColorComponents, dataType, offset, colorArray);

其中,nColorComponents代表3个颜色分量还是4个颜色分量(有α值)。其余用法和顶点数组类似。

当我们把颜色和顶点存放到一个数组里,我们就形成了交错数组。可以先后调用(之前要激活)

glVertexPointer(nColorComponents, dataType, offset, vertexArray);
glColorPointer(nColorComponents, dataType, offset, colorArray);

来达到一个点一个颜色的目的。

当然,更加简化的写法是(自动激活)

glInterleavedArrays(GL_C3F_V3F, 0, hueAndPt);

第一个参数指定颜色和坐标的三元素浮点描述,最后给出数组。

颜色表

颜色表是建立每个帧的索引。在某些场合可能有用。
与顶点数组类似,颜色表也有索引数组:

glIndexPointer(type, stride, colorIndex);

一个索引数组的示例,但是并不成功。。留着以后再来解决。(注意GLUT_INDEX)

#include<Windows.h>
#include<GL/glut.h>

void displayIndex()
{
    glClear(GL_COLOR_BUFFER_BIT);

    //颜色也不是索引预期的颜色emmm
    glIndexi(48);
    glBegin(GL_QUADS);
    {
        glVertex2i(300, 300);
        glVertex2i(400, 300);
        glVertex2i(400, 400);
        glVertex2i(300, 400);
    }
    glEnd();
    glFlush();
}


int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_INDEX);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Color function");

    //将颜色存入指定索引中
    glutSetColor(16, 1.0, 1.0, 1.0);
    glutSetColor(32, 1.0, 0.0, 0.0);
    glutSetColor(48, 0.0, 0.0, 1.0);

    //然而并没有什么用。。
    glClearIndex(16);

    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 800.0, 0.0, 600.0);

    glutDisplayFunc(displayIndex);

    glutMainLoop();
}

颜色渐变

一直在问α值有什么用。。就在这里用。。
此时各种glColor3d要改为glColor4d,表明每种颜色的aplha值。
每个帧的颜色不再单纯是被新的颜色所覆盖,而是每次覆盖颜色与之前颜色的某种方式的加权平均。具体方式由glBlenderFunc给出。

#include<Windows.h>
#include<GL/glut.h>
#include<cmath>
const double PI = acos(-1.0);

void drawCircle(int x, int y, int radius)
{
    glBegin(GL_POLYGON);
    {
        for (int i = 0; i < 360; ++i)
        {
            double theta = PI * i / 180.0;
            glVertex2d(x + radius * cos(theta), y + radius * sin(theta));
        }
    }
    glEnd();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
    glColor4d(1.0, 0.0, 0.0, 1.0);
    drawCircle(300, 300, 200);
    glColor4d(0.0, 1.0, 0.0, 1.0);
    drawCircle(500, 300, 200);
    glColor4d(0.0, 0.0, 1.0, 1.0);
    drawCircle(400, 473, 200);
    glFlush();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
    glutInitWindowSize(800, 600);
    glutCreateWindow("blend");
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0.0, 800.0, 0.0, 600.0);
    glutDisplayFunc(display);
    glutMainLoop();
}