zoukankan      html  css  js  c++  java
  • 第二章 状态管理和绘制几何物体 总结

    目标 1. 清除窗口

      2.强制完成所有尚未执行的绘图操作

      3.在2d或3d空间绘制图元

      4.打开、关闭、查询状态

      5.控制图元显示

      6.在实心物体表面适当位置指定法线向量

      7.用顶点数组和缓冲区对象存储和访问几何数据。

      8.同时保存和恢复几个状态变量。

    1.1 3种基本操作:清除窗口、绘制几何图形、绘制光栅对象。

    2. 绘图工具箱:

      2.1 清除RGBA模式的窗口

    glClearColor(R, G, B, A);    //将当前清除颜色设置成为一个状态变量
    glClearDepth(1.0);        //指定深度缓冲区中每个像素要设置的值
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  // 表示要清除的缓冲区为颜色缓冲区和深度缓冲区

      2.2 指定颜色

    glColor3f(R,G,B);

      2.3 强制完成绘图操作

    void glFlush(void);
    void glFinish(void);

      2.4 坐标系统工具箱

      当窗口发生改变的时候,会发送一个时间作为通知。在glutReshapeFunc()中注册的那个函数会被调用。并且必须注册一个回调函数完成下面任务:

      1)重新建立一个矩形区域,把它作为新的渲染画布。

      2)定义一个用于绘制物体的坐标系统。

    //一个2d的glutReshapeFunc(reshape)回调函数
    void reshape(int w, int h)
    {
        glViewport(0, 0, (GLsizei)w, (GLsizei) h);//调整用于绘图的像素矩形,使它占据整个窗口
        glMatrixMode(GL_PROJECTION);        //接下来的三行代码表示让坐标系的左下角为原点(0,0)
        glLoadIdentity();
        gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
    }

    3 描述图元:点、直线、多边形

      3.1 矩形:

        void glRect{sifd}(x1, y1, x2, y2);

      3.2 指定顶点:

        void glVertex[234]{sifd}();   //注意只有在glBegin 和glEnd之间时才有效

        void glVertex[234]{sifd}v();

      3.3 几何图元:

        将一组顶点放在glBegin 和glEnd之间, 传递给glBegin的参数决定了利用这些顶点所构成的几何图元的类型;

        有GL_POINTGL_LINESGL_LINE_STRIPGL_LINE_LOOPGL_TRIANGLESGL_TRIANGLES_STRIPGL_TRIANGLE_FANGL_QUADSGL_QUAD_STRIPGL_POLYGON

    glBegin(GL_POLYGON);
        glVertex2f(0, 0);
        glVertex2f(0, 3);
        glVertex2f(3, 4);
    glEnd();

        在glBegin和glEnd之间还可以用另外的一些函数来指定顶点的额外的属性数据, 例如:颜色glColor*(); 法线向量glNormal*(); 纹理坐标glTexCoord*();等

    4. 基本状态管理

       物体在渲染的时候可能会用到光照、纹理、隐藏表面消除、雾或者其他的状态

      这都是由函数 void glEnable(); 和 void glDisalbe();来控制 , 例如有GL_BLEND, GL_DEPTH_TEST, GL_FOG, GL_LINE_STIPPE, GL_LIGHTING等。

       查询GLboolean glIsEnable(GLenum capability); 它返回GL_TRUEGL_FALSE,  还可以查询其他类型的。

    5. 显示点、直线和多边形

      5.1 点

        void glPointSize();

      5.2 直线

        线宽: void glLineWidth(GLfloat width);

        点画线: void glLineStipple(GLint factor, GLushort pattern) ; 必须掉用glEnable(GL_LINE_STIPPLE)来启用点画线功能。

      5.3 多边形细节

        点、轮廓、实心:void glPolygonMode(GLenum face, GLenum mode);  参数face可以是GL_FRONT_AND_BACK, GL_FRONT, GL_BACK. 参数mode可以是GL_POINT, GL_LINE,GL_FILL

       反转和剔除多边形表面:void glFrontFace(GLenum mode), mode表示哪面为正面 GL_CCW表示逆时针方向为正面, GL_CW表示顺时针方向为正面。

       剔除:glEnable(GL_CULL_FACE); void glCullFace(GLenum mode);

       点画多边形:glEnable(GL_POLYGON_STIPPLE); void glPolygonStipple();

      5.4 法线

        void glNormal*()

      5.5 标记多边形的边界边

        void glEdgeFlag(GL_TRUE) 表示其后的顶点为边界边的起点。

    6. 顶点数组(我认为是顶点相关的属性数组) 

      使用顶点数组对几何图形进行渲染需要三个步骤:

      1)激活顶点数组:顶点坐标(数组)、表面法线、RGBA颜色,辅助颜色、颜色索引、雾坐标、纹理坐标、多边形边界标志 

        void glEnableClientState(GLenum array);//GL_VERTEX_ARRAY, etc.

        void glDisableClientState();

      2)把数据放入数组中。

        void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);//size是每个顶点的坐标数量2/3/4,stride是连续顶点之间的字节偏移量。type为GL_INT等,pointer是第一个顶点的内存位置

        void glColorPointer()void glSecondaryColorPointerglIndexPointerglNormalPointerglFogCoordPointerglTexCoordPointerglEdgeFlagPointer

    static GLint vertics[] = {
        25, 25,
        100, 325,
         175,25  
    }   
    
    static GLfloat colors[] = {
    1.0, 0.2, 0.2,
    0.2, 0.2, 1.0,
    0.8, 1.0, 0.2  
    }
    
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    
    glColorPointer(3, GL_FLOAT, 0, colors);
    glVertexPointer(2, GL_INT, 0, vertices);

     3)用这些数据绘制几何图形:解引用和渲染。

      解引用:客户端的数组中数据被提取发送到服务器,然后发送到图形处理管线进行渲染。

      a. void glArrayElement(GLint ith); 获取当前已启用数组(可以是多个)的第ith个顶点数据。

    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRYA);
    glColorPointer(3, GL_FLOAT, 0, colors);
    glVertexPointer(2, GL_INT, 0, vertices);
    
    glBegin(GL_TRIANGLES)
    glArrayElement(2);
    glArrayElement(3);
    glArrayElement(5);
    glEnd();

      b. void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);   // mode表示要创建那种图元GL_POLYGON/GL_LINE_LOOP/GL_LINES/GL_POINTS, count表示解引用数组元素的个数,type表示类型为GL_UNSIGNED_BYTE等, indices表示元素的内存索引位置。

       c. void glMultiDrawElements(GLenum mode, GLsizei *count,  GLenum type, const GLvoid **indices, GLsizei primcount); //调用primcount个glDrawElements()函数

    static GLubyte oneIndices[] = {0, 1, 2, 3, 4, 5, 6};
    static GLubyte twoIndices[] = {7, 1, 8, 9, 10, 11}
    static GLsizei count[] = {7, 6};
    static GLvoid * indices[2] = {oneIndices, twoIndices};
    glMultiDrawElements(GL_LINE_STRIP, count, GL_UNSIGNED_BYTE, indices, 2);

      d. void glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);//

      e. void glDrawArrays(GLenum mode, GLint first, GLsizei count); //

      f. void glMultiDrawArrays(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);

      4)图元重启索引:

        void glPrimitiveRestartIndex(GLuint index);

        指定一个顶点数组元素索引,用来表示一个新的图元在渲染时的开始位置。当顶点数组元素索引的处理中遇到和index匹配的一个值的时候,就没有顶点数据要处理了,当前的图形图元就终止了,相同类型的一个新的图元开始了。通过调用glEnable()或者glDisable来控制图元重启GL_PRIMITIVE_RESTART。

       5)实例化绘制

        void glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount); 相当于以下效果:

    for(i = 0; i < primcount; i++)
    {
        gl_instanceID = i;
        glDrawArrays(mode, first, count);
    }
    gl_InstanceID = 0;

        void glDrawElementsInstanced();

      6) 混合数组                                  

        void glInterleavedArray(GLenum format, GLsizei stride, const GLvoid * pointer);

    7. 缓冲区对象

      1)创建缓冲区对象:利用opengl分配缓冲区对象标识符,调用void glGenBuffers(GLsizei n, GLuint *buffers);//buffers 数组返回n个当前未使用的名称,表示缓冲区对象

        调用GLboolean glIsBuffer(GLuint buffer);来判断一个标志符是否是当前被使用的缓冲区对象标识符

      2) 激活缓冲区对象:为了激活缓冲区对象,首先需要将它绑定,使用void glBindBuffer(GLenum target, GLuint buffer); //target必须要设置成GL_ARRYA_BUFFERGL_ELEMENT_ARRAY_BUFFER... , buffer指定了要绑定的缓冲区对象。

      3) 数据分配和初始化缓冲区对象: 一旦绑定了缓冲区对象就需要保留空间以存储数据,通过调用void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); //将客户机中data指示的数据size个复制到服务器缓冲区。

      4)更新缓冲区对象的数据值:void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);//用data指向的数据更新与target相关联的当前绑定缓冲区对象中offset开始的size个字节数据。

       GLvoid *glMapBuffer(GLenum target, Glenum access); 这个函数返回一个指向缓冲区对象的指针。

      在完成了对数据存储的访问以后可以调用glUnmapBuffer()来取消对这个缓冲区的映射。

    GLfloat*data;
    
    data = (GLfloat*) glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
    
    if(data!=(GLfloat*)NULL)
    {
      for(i = 0; i<8 ; i++)
    {
      data[3*i + 2]*=2.0;//modify Z value
      glUnmapBuffer(GL_ARRAY_BUFFER);    
    }  
    }
    else{}

      GLvoid* glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);如果在access标志中使用了GL_MAP_FLUSH_EXPLICIT_BIT的话,还需要调用glFlushMappedBufferRange()向opengl表明映射缓冲区中的范围需要修改。

      5)在缓冲区对象之间复制数据

        void glCopyBufferSubData(GLenum readbuffer,GLenum writebuffer, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);

       6) 清除缓冲区对象 glDeleteBuffers();

    #define VERTICES    0
    #define INDICES    1
    #define NUM_BUFFERS     2
    GLuint buffer[NUM_BUFFERS];
    
    GLfloat vertices[][3] = {
    {-1.0, -1.0, -1.0},
    {1.0, -1.0, -1.0},
    {1.0, 1.0, -1.0},
    ...
    {-1.0, 1, 1}
    }
    
    GLubyte indices[][4] = {
    {0, 1, 2, 3}
    ...
    {1, 5, 6, 2}
    }
    
    glGenBuffers(NUM_BUFFERS, buffers);
    
    glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTICES]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));  
    glEnableClientState(GL_VERTEX_ARRAY);
    
    glbindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDICES]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));

    8、顶点数组对象

       1)创建顶点数组对象,调用void glGenVertexArrays(GLsizei n, GLuint *array); //返回n个当前未使用的名字,用作数组arrays中的顶点数组对象。

      2)使用GLvoid glBindVertexArray(GLuint array);

      3)glDeleteVertexArrays();

    9. 属性组

      使用glPushAttrib()和glPopClientAttrib()来操作属性组。例如:GL_LINE_BIT包括了GL_LINE_SMOOTH在内的5个状态。

      OPENGL有两个属性堆栈,除了原来的属性堆栈,还有一个客户堆栈,是通过glPushClientAttrib()和glPopClientAttrib()来函数访问的。

  • 相关阅读:
    Idea配置注释
    mysql省市区数据表
    php实现汉字转拼音的类
    git push时如果不再弹出用户和密码的输入提示框该怎么办
    .gitignore 忽略特殊文件无效
    vmware中CentOS7网络设置教程详解
    Tp5中配置多模块开发
    安装tp6 并使用多应用模式
    ldf和mdf文件怎么还原到sqlserver数据库
    git本地仓库与远程仓库建立连接。
  • 原文地址:https://www.cnblogs.com/bubbler/p/3697737.html
Copyright © 2011-2022 走看看