void CStepinGLView::OnDraw(CDC* pDC)
{
CStepinGLDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
DrawCube();
SwapBuffers(wglGetCurrentDC());
}
好了,废话就说到这。
1.绘制点
void CStepinGLView::DrawScene(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
//绘制点
GLfloat fPointSize[2];
glGetFloatv(GL_POINT_SIZE_RANGE,fPointSize); //获取点的大小范围 fPointSize[0]储存点的大小最小值,1存储最大值
glPointSize(fPointSize[1] / 2.0f);
glBegin(GL_POINTS);
glVertex2f(0.0f,0.0f);
glVertex2f(0.5f,0.5f);
glVertex2f(-0.5f,0.5f);
glVertex2f(0.5f,-0.5f);
glVertex2f(-0.5f,-0.5f);
glEnd();
}
此段代码中:
glGetFloatv(GL_POINT_SIZE_RANGE,fPointSize);
glGetFloatv第一个参数必须是OpenGL常量,第二个参数是一个数组的地址。函数按第一个参数的指示向第二个参数所指的地址传输数据。fPointSize[0]存储点的大小的最小值,fPointSize[1]存储点的大小的最大值。
运行截图:
2.绘制直线和线型
void CStepinGLView::DrawLineStipple(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
GLfloat fLineWidth[2];
glGetFloatv(GL_LINE_WIDTH_RANGE,fLineWidth);
glLineWidth(fLineWidth[1] / 6.0f);
glBegin(GL_LINES);
glVertex2f(-0.8f,0.8f);
glVertex2f(0.8f,0.8f);
glEnd();
//glEnable(GL_LINE_STRIP); //第一次使用此类型,输出都是直线
glEnable(GL_LINE_STIPPLE); //glEnable()启用函数 ,此句执行后 执行画虚线
glLineStipple(1,0x00FF); //设置直线的当前点画模式
glBegin(GL_LINES);
glVertex2f(-0.8f,0.4f);
glVertex2f(0.8f,0.4f);
glEnd();
glLineStipple(1,0x0F0F); //设置直线的当前点画模式
glBegin(GL_LINES);
glVertex2f(-0.8f,0.0f);
glVertex2f(0.8f,0.0f);
glEnd();
glLineStipple(2,0x0101); //设置直线的当前点画模式
glBegin(GL_LINES);
glVertex2f(-0.8f,-0.4f);
glVertex2f(0.8f,-0.4f);
glEnd();
glLineStipple(1,0x1C47); //设置直线的当前点画模式
glBegin(GL_LINES);
glVertex2f(-0.8f,-0.8f);
glVertex2f(0.8f,-0.8f);
glEnd();
glDisable(GL_LINE_STIPPLE);
glFinish();
}
OpenGL不仅能画实线,而且可以绘制点画线(Stippled Lines)等其他类型的直线。
为了绘制点画线,必须先自定义点画线的线型,然后通过 glLineStipple() 函数让OpenGL获取所定义的线型。
线型是通过二进制来描述的,1代表一个实点,0则表示在该像素处不画直线,即不填充像素。
例如:
0000000011111111; //对应16进制0x00FF,表示空白线和长折线
0000111100001111; //0x0F0F,表示空白线及短折线
0000000100000001; //0x0101,表示点
0001110001000111; //0x1c47,表示折线点折线
调用glLineStipple()函数,让OpenGL知道已改变的线型。第一个参数数据类型为GLint,表示线型模式重复因子;第二个参数为GLushort,表示所定义的线型。重复因子说明了用二进制表示的点的重复次数。如果重复因子是2,一个01010101的线型模式事实上被当成0011001100110011线型来处理。
为了对所定义的线型获取OpenGL的支持,必须事先启动改变线型的机制:
glEnable(GL_LINE_STIPPLE); //glEnable()启用函数 ,此句执行后 执行画虚线
要注意,当不再使用自定义线型时,将其关闭:
glDisable(GL_LINE_STIPPLE);
程序运行截图:
3.绘制不闭合折线
void CStepinGLView::DrawLineStrip(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
GLfloat fLineWidth[2];
glGetFloatv(GL_LINE_WIDTH_RANGE,fLineWidth);
glLineWidth(fLineWidth[1] / 6.0f);
glBegin(GL_LINE_STRIP); //绘制不闭合折线
glVertex2f(-0.8f,0.6f);
glVertex2f(0.8f,0.6f);
glVertex2f(-0.8f,0.2f);
glVertex2f(0.8f,0.2f);
glEnd();
}
程序运行截图:
4.绘制闭合折线
void CStepinGLView::DrawLineLoop(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
GLfloat fLineWidth[2];
glGetFloatv(GL_LINE_WIDTH_RANGE,fLineWidth);
glLineWidth(fLineWidth[1] / 6.0f);
glBegin(GL_LINE_LOOP); //绘制闭合折线
glVertex2f(-0.8f,0.6f);
glVertex2f(0.8f,0.6f);
glVertex2f(-0.8f,0.2f);
glVertex2f(0.8f,0.2f);
glVertex2f(-0.8f,0.0f);
glVertex2f(0.8f,0.0f);
glEnd();
}
程序运行截图:
5.绘制多边形
void CStepinGLView::DrawPolygons(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
glLineWidth(2.0f);
glPolygonMode(GL_FRONT,GL_LINE);
glPolygonMode(GL_BACK,GL_FILL);
glFrontFace(GL_CCW);
glBegin(GL_POLYGON);
glVertex2f(-0.3f,0.3f);
glVertex2f(-0.7f,-0.2f);
glVertex2f(-0.3f,-0.4f);
glVertex2f(0.4f,-0.4f);
glVertex2f(0.8f,-0.2f);
glVertex2f(0.4f,0.3f);
glEnd();
}
在OpenGL中,一个多边形(polygon)至少有3个顶点。直线不能相交,多边形应构成单连通的凸区域。
一个多边形有前面和后面之分,并且前面和后面可以有不同的属性。比如,可以指定一个多边形的前面为红色而后面为蓝色。
一个多边形的前面和后面是需要指定的,可以通过定义其顶点顺序来确定。
如果顶点的排序顺序是逆时针的,则该多边形是前面的,如果顶点的排序属性是顺时针的,则该多边形是后面的。
事实上,这是可以改变的。OpenGL提供了一个灵活的函数:
glFrontFace()。该函数参数只能是GL_CW或GL_CCW;
GL_CW表示按顺时针顺序定义的多边形是前面的;
GL_CCW表示按逆时针顺序定义的多边形是前面的;
多边形是封闭的线段构造的形状,它与用GL_LINE_LOOP 绘制的闭合折线有本质的区别。一个多边形可以进行填充,也可以不填充。这样就需要对多边形的绘制模式作出说明。可以采用:
glPolygonMode() :该函数有两个参数;
第一个参数:GL_FRONT、GL_BACK、GL_FRONT_AND_BACK ,分别指多边形前面、后面或前后两面;
第二个参数:GL_POINT、GL_LINE、GL_FILL ,分别指 在多边形的顶点画点,画多边形框架,填充多边形;
程序运行截图:
6.绘制三角形
void CStepinGLView::DrawTriangles(void)
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
//glTranslatef( -1.5f, 0.0f, -6.0f); //左移1.5单位,并移入屏幕6.0
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glLineWidth(1.0f);
glBegin(GL_TRIANGLES);
glVertex2f(-0.5f, 0.4f);
glVertex2f(-0.6f, -0.5f);
glVertex2f(0.5f, -0.5f);
glVertex2f(-0.5f, 0.8f);
glVertex2f(-0.5f, 0.6f);
glVertex2f(0.5f, 0.5f);
glEnd();
}
7.绘制三角形片
void CStepinGLView::DrawTriangleStrip(void) //绘制三角形片
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(-0.8f,0.3f);
glVertex2f(-0.8f,-0.3f);
glVertex2f(-0.3f,-0.3f);
glVertex2f(0.0f,-0.3f);
glVertex2f(0.3f,0.5f);
glEnd();
}
在定义三角形片中,第一个三角形的顶点的排序顺序是十分重要的,它决定了整个三角形片是前面还是后面的。
当glFrontFace()函数的参数采用GL_CCW时,第一个三角形按逆时针顺序定义时,其前面是面向我们的。
三角形片中顶点被处理的顺序,如下图:
程序运行截图:
8.绘制三角形扇
void CStepinGLView::DrawTriangleFan(void) //绘制三角形扇
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_TRIANGLE_FAN);
glVertex2f(-0.5f,-0.3f);
glVertex2f(0.3f,0.0f);
glVertex2f(0.3f,0.3f);
glVertex2f(0.4f,0.6f);
glVertex2f(-0.0f,0.6f);
glEnd();
}
程序运行截图:
9.绘制四边形
void CStepinGLView::DrawQuadrilaterala(void) //四边形
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUADS);
glVertex2f(-0.6f,0.8f);
glVertex2f(-0.6f,-0.6f);
glVertex2f(0.5f,0.0f);
glVertex2f(0.6f,0.5f);
glEnd();
}
程序运行截图:
10.绘制四边形片
void CStepinGLView::DrawQuadStrip(void) //四边形片
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_QUAD_STRIP);
glVertex2f(-0.8f,0.3f);
glVertex2f(-0.7f,0.6f);
glVertex2f(-0.6f,0.1f);
glVertex2f(-0.3f,0.6f);
glVertex2f(-0.1f,-0.2f);
glVertex2f(0.0f,0.6f);
glVertex2f(0.3f,-0.4f);
glVertex2f(0.6f,0.5f);
glEnd();
}
绘制示意图:
程序运行截图:
11.边的可见性
void CStepinGLView::DrawNonConvex(void) //凹多边形
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f); //颜色为红色
glLineWidth(1.0f);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_POLYGON);
glEdgeFlag(TRUE);
glVertex2f(-0.3f,0.3f);
glEdgeFlag(FALSE);
glVertex2f(-0.1f,-0.1f);
glEdgeFlag(TRUE);
glVertex2f(0.0f,-0.1f);
glVertex2f(0.0f,0.3f);
glEnd();
glBegin(GL_POLYGON);
glEdgeFlag(TRUE);
glVertex2f(-0.1f,-0.1f);
glVertex2f(-0.2f,-0.4f);
glEdgeFlag(FALSE);
glVertex2f(0.0f,-0.4f);
glVertex2f(0.0f,-0.1f);
glEnd();
glBegin(GL_POLYGON);
glEdgeFlag(FALSE);
glVertex2f(0.0f,-0.1f);
glEdgeFlag(TRUE);
glVertex2f(0.0f,-0.4f);
glVertex2f(0.4f,-0.4f);
glVertex2f(0.45f,0.1f);
glEnd();
}
OpenGL通过 glEdgeFlag() 函数来说明边的可见性。
TRUE 表可见,FALSE 表不可见。
程序运行截图:
12.由面创建三维形状
void CStepinGLView::DrawCube(void) //绘制立方体
{
glClearColor(1.0f,1.0f,1.0f,0.0f); //设置窗口为白色1. 1. 1. 黑色0. 0. 0.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.2f,0.5f); //颜色为红色
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glLineWidth(1.5f);
glColor3f(0.2f,0.5f,1.0f);
glPushMatrix();
glRotatef(70.0f,0.0f,1.0f,0.0f); //将盒子绕Y轴70度
glRotatef(55.0f,0.0f,0.0f,1.0f); //将盒子绕Z轴55度
glBegin(GL_POLYGON); //前面
glVertex3f(-0.5f,0.5f,0.5f);
glVertex3f(-0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,0.5f);
glVertex3f(0.5f,0.5f,0.5f);
glEnd();
//为了省事,我直接把前面的矩阵复制下来
//直接修改最后一位参数,结果绘制出的图形不对
//原因:点的顺序输入不对,造成
glBegin(GL_POLYGON); //后面
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(0.5f,0.5f,-0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
glBegin(GL_POLYGON); //左面
glVertex3f(-0.5f,-0.5f,0.5f);
glVertex3f(-0.5f,0.5f,0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
glBegin(GL_POLYGON); //右面
glVertex3f(0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(0.5f,0.5f,-0.5f);
glVertex3f(0.5f,0.5f,0.5f);
glEnd();
glBegin(GL_POLYGON); //底面
glVertex3f(-0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,0.5f);
glVertex3f(0.5f,-0.5f,-0.5f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
glBegin(GL_POLYGON); //顶面
glVertex3f(-0.5f,0.5f,0.5f);
glVertex3f(0.5f,0.5f,0.5f);
glVertex3f(0.5f,0.5f,-0.5f);
glVertex3f(-0.5f,0.5f,-0.5f);
glEnd();
glPopMatrix();
}
在用多边形描述一个三维物体时,多边形的前后面区分是十分重要的。如果一个面本来是前面的却当成后面来处理很可能产生不良效果,特别是对其进行光照的时候。
程序运行截图: