OpenGL超级宝典学习笔记——空间绘图画点
3D概念
- 像素,计算机显示器中的最小元素。
- 3D画布,把可视区域看成一个3维的画布,可以用OpenGL命令在上面进行绘图。例如:glOrtho可以设置一个长方体的可视区域。谨记第二章说的:glOrtho是对之前的矩阵进行运算,所以一般都会在此函数之前调用glMatrixMode(GL_PROJECTION); glLoadIdentity();
3D空间中的顶点
我们可以通过glVertex这个函数来设置多个参数多个类型的点。例如:glVertex2f(0.0f, 1.0f); glVertex3f(1.0f, 0.5f, 0.0f);
在图形学中点不仅仅是一个点, OpenGL如何解释一个点,决定了根据这个点画出的几何图元。这里的点一般是图元中的顶点,比如矩形的顶点,曲线的顶点,线段的端点等。我们可以通过glBegin(GLenum mode); glEnd(); 来说明这两个函数之间顶点应当如何被解释。glBegin,glEnd像似{} 在此区域内的点将被解释。例如:
//画点 glBegin(GL_POINTS); glVertex2f(3.0f, 4.0f); glVertex2f(5.0f, 8.0f); glEnd() //画线,偶数2n个点画成 n条直线 2n+1奇数个的话,最后一个将被忽略 glBegin(GL_LINES); glVertex2f(3.0f, 4.0f); glVertex2f(5.0f, 8.0f); glVertex2f(7.0f, 12.0f);//此点将被忽略 glEnd();
绘制图形
我们知道如何在OpenGL中指定一个点,并且告诉OpenGL如何对它进行操作。顶点的几何定义不仅仅是空间中的一个点,而是两条直线或曲线的交点。这就是图元的本质。
图元是顶点的集合,它们构成了在屏幕上所绘制的形状。
例子:
用简单的三角方法绘制一些点,使它们绕着z轴呈现螺旋状。
#include #include #include static GLfloat GL_PI = 3.14159f; //绘制场景 static void RenderSences() { GLfloat z = -50.0f; //清空画布 glClear(GL_COLOR_BUFFER_BIT); //设置画图使用的颜色 glColor3f(1.0f, 0.0f, 0.0f); //保存矩阵 glPushMatrix(); //旋转, 如果不旋转,那些不同层次的点都重叠在一起,看不出3D效果了。 glRotatef(200.0f, 1.0f, 0.0f, 0.0f); glRotatef(120.5f, 0.0f, 1.0f, 0.0f); //获取点的大小的范围,以及增长的步长 GLfloat size[2]; GLfloat sizeStep; glGetFloatv(GL_POINT_SIZE_RANGE, size); glGetFloatv(GL_POINT_SIZE_GRANULARITY, &sizeStep); GLfloat curStep = size[0]; for (GLfloat a = 0.0; a < GL_PI * 3.0f; a += 0.1f) { GLfloat x = 50.0f * cos(a); GLfloat y = 50.0f * sin(a); //设置点的大小 glPointSize(curStep); curStep += sizeStep; //设置顶点 glBegin(GL_POINTS); glVertex3f(x, y, z); glEnd(); //调整z值 z += 0.5f; } glPopMatrix(); glFlush(); } void ChangeSize(GLsizei w, GLsizei h) { GLfloat nRange = 100.0f; if (h == 0) { h = 1; } //设置视口 glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //设置可视区域 GLfloat aspect = (GLfloat)w / (GLfloat)h; if (w <= h) { glOrtho(-nRange, nRange, -nRange/aspect, nRange/aspect, -nRange, nRange); } else { glOrtho(-nRange*aspect, nRange*aspect, -nRange, nRange, -nRange, nRange); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } //初始化工作 static void SetupRC() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); } //创建窗口 static void CreateWindow() { glutInitWindowSize(200, 200); glutCreateWindow( "3d Points"); } int main( int args, char **argv) { glutInit(&args, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(200, 200); glutCreateWindow( "draw points"); SetupRC(); glutDisplayFunc(RenderSences); glutReshapeFunc(ChangeSize); glutMainLoop(); return 0; }
点的大小如果不指定的画,默认是1。点的大小的设置是存在限制的,不同的实现限制不同。可以通过
glGetFloatv(GL_POINT_SIZE_RANGE, size);
获得点的大小的范围,size[0]为最小值,size[1]为最大值。
通过 glGetFloatv(GL_POINT_SIZE_GRANULARITY, &sizeStep); 获得点大小之间的最小间隔。
PS:点和其他的几何图元不同,点不受透视除法的影响,即点离观察点近或远并不影响点最终投影到2d屏幕上的大小。另外点总是正方形的元素。为了获得圆点,必须在抗锯齿模式下绘制点。
另外需要注意的是glPointSize必须在glBegin和glEnd之外调用,并不是所有的函数在glBegin和glEnd之间调用都是合法的。 glPointSize所指定的点的大小并不是以像素为单位的,而是一个圆的近似直径,这个圆包含了这个点所使用的像素。