使用OpenGL提供的标准几何图元对于多数的简单应用已经足够,但是遇到稍微复杂的应用就很吃力。例如,绘制虚线和点划线这样的图形就很难实现。不过OpenGL也提供了另外的方法,使得我们可以对点、线、面进行自定义,创造自己需要的几何图形。
1.1 点(Point)
对点的自定义函数是glPointSize,其原型为
void glPointSize(
GLfloat size
);
其中size表示光栅化后点的直径大小,缺省为1.0。
glPointSize函数指定的点的大小包括了走样点和反走样两种情况。当设置的点的大小超过1.0时,根据是否启用反走样具有不同的效果。前面已经讲过,启用点的反走样需要使用glEnable(GL_POINT_SMOOTH);如果禁用了反走样处理,或者说没有启用反走样处理,此时点的真正大小是将设置的值圆整到最近的整数。缺省状态是不启用反走样处理。当圆整结果为0时(例如设置的值为0.3),实际结果不会是0,而是1.0。
如果圆整的结果为奇数时,那么表示该像素点的像素片元(pixel fragment)的中心点(x, y)就是(xw+.5, yw+ .5),其中w下标表示窗口坐标。所有以(x, y)为中心的在圆整大小范围内的栅格组成的矩形区域全部构成该点。
当圆整的结果为偶数时,表示该点的像素片元的中心点(x, y)就是(xw+ .5, yw+ .5)。以(x, y)为中心的在圆整范围内的栅格组成的矩形区域就构成了该点。
当启用了反走样处理时,点光栅化产生的片元中心还是(xw, yw) ,但是形状却是圆形,直径就是当前点的大小。但是此时并不是所有的大小都支持,如果遇到了不支持的尺寸,则OpenGL会使用能够支持的最接近的尺寸来替代。1.0作为最基本的大小是是没有问题的,其他则要根据应用来决定。具体来说,使用glGetFloatv(GL_POINT_SIZE_RANGE, sizes)(sizes的定义是float sizes[2])函数和glGetFloatv(GL_POINT_SIZE_GRANULARTY, &step)(step的定义是float step)可用获得OpenGL在反走样的情况下对点的大小支持的范围以及大小增加的最小步长。在Windows系统中,OpenGL支持的点的大小范围是[0.5, 10.0],最小步长是0.125,超过10.0的大小均以10.0来处理。
下面我们来看一下不同大小的点在OpenGL中的表现。
int glInit()
{
//启用阴影平滑(Smooth Shading)。
glShadeModel(GL_SMOOTH);
//背景为白色
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
//设置深度缓冲
glClearDepth(1.0f);
//启动深度测试
glEnable(GL_DEPTH_TEST);
//深度测试的类型
glDepthFunc(GL_LEQUAL);
//进行透视修正
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE;
}
void glMain()
{
float diameter;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //加载单位矩阵
glTranslatef(-5.5f, 1.0f, -10.0f);
//点为黑色
glColor3f(0.0f, 0.0f, 0.0f);
//禁用点的反走样处理
glDisable(GL_BLEND);
glDisable(GL_POINT_SMOOTH);
//画15个大小不同的点
for(diameter=1.0; diameter<=15.0; diameter++)
{
//设置点的大小
glPointSize(diameter);
//向右平移0.5个单位
glTranslatef(0.5, 0, 0.0f);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 0.0f); //画点
glEnd();
}
//启用点的反走样处理
glEnable(GL_BLEND);
glEnable(GL_POINT_SMOOTH);
//向左平移7.5个单位和上一行点对齐
glTranslatef(-7.5, -1.0, 0.0);
//画20个大小不同的点
for(diameter=1.0; diameter<=11.0; diameter+=0.5)
{
//设置点的大小
glPointSize(diameter);
glTranslatef(0.5, 0.0, 0.0f);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
}
SwapBuffers(g_hDC);//交换前后缓冲区
}
程序运行后,效果如图10-1所示,可以看到两行排列的点,逐渐增大。不论点的大小,未经过反走样处理的点都是一个矩形,而经过反走样处理的点则是一个圆点。因此,反走样处理的效果在复杂图元效果中更加明显。同时可以看到,走样点的大小是随着设置的值的大小变化,而反走样点的大小当超过10.0时就不再增大了。