除了直线的宽度可以根据需要进行改变外,直线的线型也可以改变。glLineStipple就可以提供不同于常规的连续线段的中心线、虚线、点划线等等。其函数原型如下
void glLineStipple(
GLint factor,
GLushort pattern
);
其中factor 是比例因子,它表示在线型模式中,每一位的放大倍数。例如,factor为3,那么线型模式中的每一位要重复3次,然后在继续下一位。factor的取值范围是[1, 256],缺省值是1。pattern 是一个16位的整数,它表示线型模式,当某一位为0时,表示不画线,为1时画线,但是处理是从最底位开始的,颜色为当前颜色。缺省值为0xFFFF,即连续线。 例如pattern为0x40FF时,表示的画线如下图10-3所示。
禁用和启用线型模式设置可以使用glEnable(GL_LINE_STIPPLE) 和glDisable(GL_LINE_STIPPLE),当禁用线型模式时,使用glLineStipple设置的直线均按照连续线处理,这也是OpenGL的缺省处理。
下面我们来举例说明常用的几种直线线型的构造和使用。
BOOL bAntialiasing = FALSE; //是否进行反走样处理
BOOL bAntiPress = FALSE; //是否按了F1键
void Line3f(GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat);
int PatternMode = 0; //线型模式
int Pattern[]= //定义了6种线型
{
//点线 1000100010001000, 表示实际画线的点,反序后转换成16进制就是0x1111
//. . . . . . . . . . . . . .
0x1111,
//点划线 1111111111100100
//____ . ____ . _____ . _____. _____
0x27FF,
//中心线 1111111111001100
//_____ _ _____ _ _____ _ _____ _ _____
0x33FF,
//虚线 1111110011111100
//____ ____ ____ ____ ____ ____ ____
0x3F3F,
//双点划线 1111111100100100
// ____ . . ____ . . ____ . . ____ . . ____
0x24FF,
//三点划线 111111110101010
// ____ . . ____ . . ____ . . ____ . . ____
0x55FF
};
为了更换各种线型,增加了按键选择,代码在WndProc()里面。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_ACTIVATE:
{
if (!HIWORD(wParam))
{
g_bActive=TRUE;
}
else
{
g_bActive=FALSE;
}
return 0;
} // 监视窗口激活消息
case WM_SIZE:
{
glSceneResize(LOWORD(lParam),HIWORD(lParam));
return 0;
}
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
return 0;
case VK_SPACE: //当按空格键时,改变线型
PatternMode ++;
if(PatternMode == 6)
PatternMode = 0;
return 0;
case VK_F1: //F1键确定是否反走样处理
bAntialiasing = !bAntialiasing;
bAntiPress = TRUE;
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
glInit()基本没有特殊的处理,下面是glMain()的具体实现。
void glMain()
{
static float angle = 0.0;
float alpha;
float PI=3.1415926;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //加载单位矩阵
glTranslatef(0.0f, 0.0f, -25.0f);
glRotatef(angle, 0.0, 1.0, 0.0); //绕Y轴旋转
//启用线型设置
glEnable(GL_LINE_STIPPLE);
//线段颜色为黑色
glColor3f(0.0f, 0.0f, 0.0f);
//根据是否按了F1键和当前的反走样处理状态来设置是否启用反走样处理
if(bAntialiasing && bAntiPress)
{
//启用反走样处理
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
bAntiPress = FALSE;
}
else if(!bAntialiasing && bAntiPress)
{
//禁用反走样处理
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
bAntiPress = FALSE;
}
//缩放因子为2,看起来效果明显一些
glLineStipple(2, Pattern[PatternMode]);
for(alpha = 0; alpha<360; alpha+=10)
{
Line3f(5.0*cos(PI*alpha/180), 5.0, 5.0*sin(PI*alpha/180),
5.0*cos(PI*alpha/180), -5.0, 5.0*sin(PI*alpha/180));
}
angle+=0.5;
SwapBuffers(g_hDC);
}
其中Line3f是一个自定义函数,其功能就是绘制一条三维直线。
void Line3f(GLfloat fromX, GLfloat fromY, GLfloat fromZ,
GLfloat toX, GLfloat toY, GLfloat toZ)
{
glBegin(GL_LINES);
glVertex3f(fromX, fromY, fromZ);
glVertex3f(toX, toY, toZ);
glEnd();
}
程序运行后,可以看到一个由点线构成的圆柱面围绕Y轴旋转。按空格键后线型改变,不停的按空格键,线型将会一直循环改变,重复6种线型。按F1键后,所有的线型均以反走样形式出现。效果如图10-4所示。由于反走样处理需要额外的资源开销,反走样处理后程序的运行速度有所下降。