随笔 - 56, 文章 - 0, 评论 - 0, 引用 - 0
数据加载中……

OpenGL红宝书之随笔

一、窗口管理
    GLUT用5个函数执行初始化窗口所需要到任务:
    1、glutInit(int *argc,char** argv)对GLUT进行初始化,并处理所有命令行参数。glutInit()应该在调用任何其他GLUT函数之前被调用。
    2、glutInitDisplayMode(unsigned int mode)指定使用RGBA还是颜色索引模式。还可以指定使用单缓冲还是双缓冲。最后,可以使用这个函数来表示希望窗口拥有相关联到深度、模板、多重采样和/或累积缓冲区。例如,如果需要一个双缓冲、RGBA颜色模式以及一个深度缓冲区到窗口,可以调用glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)。
    3、glutInitWindowPosition(int x,int y)指定了窗口左上角到屏幕位置。
    4、glutInitWindowSize(int width,int size)指定了窗口的大小(以像素为单位)。
    5、int glutCreateWindow(char* string)创建了一个带有OpenGL渲染环境的窗口。这个函数为新窗口返回一个唯一到标识符。注意:在调用glutMainLoop()函数之前,这个窗口并没有被显示。
   
二、显示回调函数
    glutDisplayFunc(void(*func)(void))是所看到到第一个也是最为重要的事件回调函数。每当GLUT确定一个窗口的内容需要重新显示时,通过glutDisplayFunc()所注册的那个回调函数就会被执行。因此,应该把重绘场景所需要的所有代码都放在这个显示回调函数里。
    如果程序修改了窗口的内容,有时候必须调用glutPostRedisplay(),后者将提示glutMainLoop()在它的下一个时机调用已注册的显示回调函数。
   
三、运行程序
    最后,必须被调用glutMainLoop()。所有已经创建的窗口将在此显示,对那些窗口到渲染也开始生效。事件处理开始启动,已注册到显示回调函数被触发。一旦进入循环,它就永远不会退出。
   
四、处理输入事件
    可以使用下面这些函数注册回调函数,当指定的事件发生时,这些函数便会被调用:
    glutReshapeFunc(void(*func)int w,int h))表示当窗口的大小发生改变时应该采取什么行动。
    glutKeyboardFunc(void(*func)(unsigned char key,int x,int y))和glutMouseFunc(void(*func)(int button,int state,int x,int y))允许把键盘上的一个键或者鼠标上的一个按钮与一个函数相关联,当这个键或按钮被按下或释放时,这个函数就会被调用。
    glutMotionFunc(void(*func)(int x,int y))注册了一个函数,当一个鼠标按钮被按下时移动鼠标时,这个函数就会被调用。
   
五、管理后台进程
    可以在glutIdleFunc(void(*func)(void))函数中指定一个函数,如果不存在其他尚未处理到事件(例如,当事件循环处于空闲的时候),就执行这个函数。这个函数接受一个函数指针作为它的唯一参数。如果传递NULL(0),就相当于禁用这个函数。
   
六、绘制三维物体
    GLUT包含了几个函数,用于绘制下面这些三维物体:
    圆锥体                二十面体               茶壶
    立方体                八面体                四面体
    十二面体               球体                 圆环面
   
    void glutWireCube(GLdouble size);
    void glutSolidCube(GLdouble size);
    void glutWireSphere(GLdoublw radius,GLint slices,GLint stacks);
    void glutSolidSphere(GLdouble radius,GLInt slices,GLint stacks);
   
七、清除窗口
    在计算机中,保存图片的内存通常被计算机所绘制到前一幅图像所填满,因此在绘制新场景之前需要把它清除为某种背景颜色。如果是字处理程序,在绘制新文本之前把背景清除为白色。如果所绘的是在航天飞机上所看到的太空景象,那么在开始绘制恒星、行星以及外星人到飞船之前需要把背景清除为黑色。也有时候,背景并不需要清除。
    清除窗口这种方式有几点优势。首先,特殊的清除窗口函数的效率可能远远高于普通的绘图函数。其次,就像在之前所看到到那样,OpenGL允许任意设置坐标系统、观察点和观察方向。这样一来,判断窗口清除矩形的大小和位置就可能非常困难。最后,在许多机器上,图形硬件除了包含被显示到像素颜色的缓冲区之外,还包含许多别的缓冲区。这些缓冲区随时可能被清除,如果有一条命令能够按照任意组合形式清除这些缓冲区,无疑是非常方便的。
    例如,下面这两行代码把一个RGBA模式的窗口清除为黑色。
    glCLearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    第一行代码把清除颜色设置为黑色,第二行代码把整个窗口清除为当前的清除颜色。glClear()的唯一参数表示需要被清除的缓冲区。在这个例子里,程序只清除颜色缓冲区,显示在屏幕上的图像仍然保持原样。例如,为了同时清除颜色缓冲区和深度缓冲区,只要使用下面这个操作序列就可以:
    glClearColor(0.0,0.0,0.0,0.0);
    glClearDepth(1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    在上面到代码里,glClearColor()函数的作用和前一段代码相同。glClearDepth()函数指定了深度缓冲区中的每个像素需要被设置的值。
   
    void glClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha);
    void glClear(GLbitfield mask);
    用当前的缓冲区清除指定的缓冲区。mask参数的值如下:
    缓冲区            名称                     
    颜色缓冲区         GL_COLOR_BUFFER_BIT
    深度缓冲区         GL_DEPTH_BUFFER_BIT
    累积缓冲区         GL_ACCUM_BUFFER_BIT
    模版缓冲区         GL_SIENCIL_BUFFER_BIT
   
八、强制完成绘图操作
    glFlush()并不等待绘图完成,它只是强制绘图命令开始执行,因此保证所有的命令都在有限的时间内执行,即使在此之后并没有任何渲染命令需要执行。
   
九、坐标系统工具箱
    无论是在刚打开窗口的时候,还是在以后移动窗口或改变窗口大小的时候,窗口系统都会发送一个事件来通知你。如果使用是GLUT,它会自动产生通知,并且在glutReshapeFunc()中注册的那个函数将会调用。必须注册一个回调函数,完成下列任务:
    1、重新建立一个矩形区域,把它作为新的渲染画布
    2、定义一个用于绘制物体的坐标系统
    例如,可以调用glutReshapeFunc(reshape),其中reshape(int w,int h)。
    void reshape(int w,int h)
    {
        glViewport(0,0,(GLsizei)w,(GLsizei)h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0,(GLdouble) w,0.0,(GLdouble) h);
    }
    在系统内部,GLUT向这个函数传递两个参数:width和height,它们表示这个新的(或经过移动的、或改变了大小的)窗口的宽度和高度(以像素为单位)。glViewport()函数调整用于绘图的像素矩形,使它占据整个新窗口。接下来的3行代码调整用于绘图的坐标系统,使左下角到坐标为(0,0),右上角的坐标为(w,h)。gluOrtho2D函数的作用就是,指定这个2D平面的左,右,上,下的坐标,以指定整个坐标系,想要将OpenGL的坐标体系换成windows那样,只需要如下调用gluOrtho2D即可:
    gluOrtho2D(0.0,(double)Width,(double)Height,0.0);
    即,指定客户去左边界坐标为0,右边界坐标为客户区宽度,下边界坐标为客户区高度,上边界为0,这样,一个windows坐标体系就诞生了。在OpenGL中由于更惯用的是:
    gluOrtho2D(0.0,(double)Width,0.0,(double)Height);
    体系,这样于真实笛卡尔坐标体系第一象限一致,也与OpenGL中默认的x,y轴方向一致。
   
十、描述点、直线和多边形
    用户可以把顶点指定为二维的形式(也就是只有x和y坐标),并由OpenGL为它赋一个值为零的z坐标。
    OpenGL是根据三维投影几何的齐次坐标进行操作的。因此,对于内部的计算,所有的顶点都是用4个浮点坐标值(x,y,z,w)来表示的。如果w不等于0,那么这些坐标值就对应于欧几里德三维点(x/w,y/w,z/w)。可以用OpenGL函数指定w坐标,如果未指定w坐标,它就默认为1.0.
    矩形
    void glRect{sifd}(TYPE x1,TYPE y1,TYPE x2,TYPE y2);
    void glRect{sifd}v(TYPE *v1,TYPE *v2);
    绘制由角顶点(x1,y1)和(x2,y2)所定义的矩形。这个矩形位于z=0的平面上,并且它的边与x轴和y轴平行。
    指定顶点
    void glVertex{234}{sifd}[v](TYPE coords);
    既可以为一个顶点提供多达4个的坐标(x,y,z,w)也可以只提供2个坐标(x,y)。如果使用的函数版本并没有显式指定z或w,z就会被当作0,w则默认为1.glVertext*()函数只有在位于glBegin()和glEnd()之间才有效。
   
    几何绘图图元
    void glBegin(GLenum mode);
    标志着一个顶点数据列表的开始,这个顶点描述了一个几何图元。mode参数指定了图元的类型,如下:
                                 几何图元的名称和含义
    值                              含义
    GL_POINTS                    单个的点
    GL_LINES                     一对顶点被解释为一条直线段
    GL_LINE_STRIP                一系列的连接直线段
    GL_LINE_LOOP                 和上面相同,但第一个顶点和最后一个顶点彼此相连
    GL_TRIANGLES                 三个顶点被解释为一个三角形
    GL_TRIANGLE_STRIP            三角形的连接串
    GL_TRIANGLE_FAN              连接成扇形的三角形系列
    GL_QUADS                     四个顶点被解释为一个四边形
    GL_QUAD_STRIP                四边形的连接串
    GL_POLYGON                   一个简单的凸多边形的边界
   
    void glEnd(void);
    标志一个顶点数据列表的结束。
   
十一、基本状态管理
    为了打开或关闭某些状态,可以使用下面这两个简单的函数:
    void glEnable(GLenum cap);
    void glDisable(GLenum cap);
    还可以查询一个状态当前是否处于打开还是关闭状态:
    GLboolean glIsEnable(GLenum capability)
    根据被查询的状态当前处于启用还是禁用状态,返回GL_TRUE或GL_FALSE。
    可以使用5个查询函数,查询许多状态的当前值:
    void glGetBooleanv(GLenum pname,GLboolean *params);
    void glGetIntegerv(GLenum pname,GLint *params);
    void glGetFloatv(GLenum pname,GLfloat *params);
    void glGetDoublev(GLenum pname,GLdouble *params);
    void glGetPointerv(GLenum pname,GLvoid **params);
    params参数是个符号变量,表示需要返回的状态变量。params是一个指定类型的数组指针,指向包含返回数据的位置。
   
十一、显示点、直线和多边形
    为了控制被渲染的点的大小,可以使用glPointSize()函数,并在参数中提供一个值,表示希望的点的大小(以像素为参数)。
    void glPointSize(GLfloat size);
    设置被渲染点的宽度,以像素为单位。size必须大于0.0,在默认情况下为1.0。
    如果抗锯齿功能被禁用(默认情况),带小数的宽度值被四舍五入为整型值,在屏幕上绘制的是对齐的正方形像素区域。因此,如果宽度值为1.0,这个方块就是1个像素乘以1个像素,如果宽度为2.0,这个方块就是2个像素乘以2个像素。
    如果启用了矿局吃或多重采样,屏幕上绘制的将是一个圆形的像素区域,位于边界的像素在一般情况下使用的颜色强度较小,使边缘具有更平滑的外观。在这种情况下宽度值并不会被四舍五入。
    大多数OpenGL实现都支持非常大的点。可以使用glGetFloatv()函数(以GL_ALIASED_POINT_RANGE为参数)查询在未进行抗锯齿处理的情况下最小和最大的点。类似地,可以在这个函数中使用GL_SMOOTH_POINT_SIZE_RANGE为参数查询在进行了抗锯齿处理的情况下最小和最大的点。以GL_SMOOTH_POINT_SIZE_GRANULARITY为参数调用glGetFloatv()函数将返回系统对特定的抗锯齿点在大小方面的精度。例如,如果调用glPointSize(2.37),并且返回的粒度值为0.1,那么这个点的将四舍五入为2.4.
   
    直线的宽度
    void glLineWidth(GLfloat width);
    以像素为单位设置宽度,用于直线的渲染,width参数必须大于0.0,在默认情况下为0.0.
    如果为使用抗锯齿功能,那么宽度为1、2和3的直线将分别画成1、2和3个像素的宽度。如果启用了抗锯齿功能,它就允许使用非整数的宽度,位于边界处的像素一般会画得淡一点。可以使用GL_ALIASED_LINE_WIDTH_RANGE为参数查询受系统所支持的直线宽度的方位。为了查询系统所支持的抗锯齿直线的最小和最大宽度,以及使用的OpenGL实现所支持的直线宽度粒度,可以分别用GL_SMOOTH_LINE_WIDTH_RANGE和GL_SMOOTH_LINE_WIDTH_GRANULARITY为参数调用glGetFloatv()函数。
   
    点画线
    可以使用glLineStipple()函数定义点画模式,然后glEnable()函数启用直线点画功能。
    glLineStipple(1,0x3F07);
    glEnable(GL_LINE_STIPPLE);
   
    void glLineStipple(GLint factor,GLushort pattern);
    设置直线的当前点画模式。pattern参数是个由1和0组成的16位序列。从这个模式的低位开始,一个像素一个像素进行处理。如果模式中对应的位为1,就绘制这个像素,否则就不绘制。模式可以使用factor参数进行扩展,它与连续的1和0的子序列相承。因此,如果模式中出现了连续3个1,如果factor是2,那么它们就扩展为6个连续的1.必须以GL_LINE_STIPPLE为参数调用glEnable()才能启用直线点画功能。可以向glDisable()函数传递同一个参数,禁用直线点画功能。
   
    多边形的细节
    1.点、轮廓或实心形式的多边形
    多边形具有两个面:正面和背面。取决于哪一面将面对观察着,它们可能会被渲染成不同的样子。
    void glPolygonMode(GLenum face,GLenum mode);
    控制一个多边形的正面和背面的绘图模式。face参数可以是GL_FRONT_AND_BACK、GL_FRONT或GL_BACK。mode参数可以是GL_POINT、GL_LINE或GL_FILL,表示多边形应该被画成点、轮廓还是填充形式。在默认情况下,多边形的正面和背面都被画成填充模式。
    例如,可以通过下面这两个函数调用,把正面画成填充形式,把背面画成轮廓模式:
    glPolygonMode(GL_FRONT,GL_FILL);
    glPolygonMode(GL_BACK,GL_LINE);
   
    2、反转和剔除多边形表面
    void glFrontFace(GLenum mode);
    控制多边形的正面是如何决定的。在默认情况下,mode是GL_CCW,它对应于窗口坐标上一个投影多边形的有序顶点的逆时针方向。如果mode是GL_CW,顶点顺序为顺时针方向的表面被认定是正面。

posted on 2010-04-03 23:44 八路 阅读(1547) 评论(0)  编辑 收藏 引用 所属分类: 学习笔记


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理