最近对程序中绘制卡顿的问题忍无可忍,终于决定下手处理了。程序涉及的绘制比较多,除了点、线、三角形、多边形、圆柱体之外,还有自组格式模型。开始想全部采用显示列表优化,毕竟效率最高,虽然显示列表存在编译之后不能更改的缺点,但是程序中更改模型的情况不多,更改每个类别的模型后重新加载该类别的显示列表就行了。

1.显示列表+顶点数组

显示列表的使用就不赘述了。主要想说一下配合顶点数组使用显示列表,可以带来更大的性能提升。对于三角网格和基于顶点的自组格式模型来说,摒弃一个个三角形画吧,效果绝对令你满意!当然,这么做的前提应该是顶点vertex在不同三角形中的属性相同(法线、颜色……)

list = glGenLists(1);
glNewList(list);

……
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);

glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);//纹理

glTexCoordPointer(2,GL_FLOAT,0,textures);

glColorPointer(3,GL_FLOAT,0,colors);//颜色 nTri*3

glNormalPointer(GL_FLOAT,0,normals);//法线 nTri*3
glVertexPointer(3,GL_FLOAT,0,vertexs);//顶点 nVer
glDrawElements(GL_TRIANGLES,nTri*3,GL_UNSIGNED_INT,iIndex);//索引 nTri*3

glEndList();

2.VBO(vertex buffer object)+VAO(vertex array object)

  另一个选择是采用VBO进行绘制。VBO的好处是采用将数据提交到高速缓存的同时还保留数据的存取入口,可以直接获取并更新数据。VBO有两种方式,一种是使用glEnableClientState进行绘制,另一种就是组合VAO进行使用,也就是将对应不同属性的多组VBO存储到同一个VAO中(在渲染的时候可以少写很多代码)。

关于两种方式的取舍在这篇文章里面有介绍(http://www.zwqxin.com/archives/opengl/vao-and-vbo-stuff.html),这里我使用了第二种方式,也就是VBO+VAO进行使用。

GLuint vao;
GLuint vbo;

……

//初始化代码
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);//当前VAO 到glBindVertexArray(NULL)之间的vbo等都成为该vao的属性  
//
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER,12 * 3 * sizeof(float),vertexs,GL_STATIC_DRAW);//此处点坐标按照每个四边形四个点进行存入
glEnableVertexAttribArray(0); //坐标
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER,NULL);
//
glBindVertexArray(NULL);
glBindBuffer(GL_ARRAY_BUFFER,NULL);

……

//渲染代码

glBindVertexArray(vbo);
glDrawArrays(GL_QUADS,0,4);

glBindVertexArray(vbo);

之后突然想到,VA的使用中,共用顶点的索引方式index会比直接每个多边形顶点暴力存储效率高很多。所以查了下,果然有关于索引的用法:

---IBO(http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/)

其实就是VBO的方式运用索引而已,GL_ELEMENT_ARRAY_BUFFER。经过修改,代码就变成了下面的样式:

GLuint vao;

……

glGenVertexArrays(1,&vao);
glBindVertexArray(vao);//当前VAO 到glBindVertexArray(NULL)之间的vbo等都成为该vao的属性  
//
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER,nVert * 3 * sizeof(float),vertexs,GL_STATIC_DRAW);
glEnableVertexAttribArray(0); //坐标
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER,NULL);
//
GLuint colorVbo;//
glGenBuffers(1, &colorVbo);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glBufferData(GL_ARRAY_BUFFER,nVert * 3 * sizeof(float),colors,GL_STATIC_DRAW);
glEnableVertexAttribArray(1); //颜色
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER,NULL);
//
GLuint normalVbo;//
glGenBuffers(1, &normalVbo);
glBindBuffer(GL_ARRAY_BUFFER, normalVbo);
glBufferData(GL_ARRAY_BUFFER,nVert * 3 * sizeof(float),normals,GL_STATIC_DRAW);
glEnableVertexAttribArray(2); //法线
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER,NULL);
//
GLuint ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,nElem * 4 * sizeof(short), index,GL_STATIC_DRAW);//由于是绘制六棱柱侧面,nElem = nVert/2
//
glBindVertexArray(NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ARRAY_BUFFER,NULL);

渲染部分代码稍作改变

glBindVertexArray(vao);
glDrawElements(GL_QUADS,24, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(NULL);

3.目前存在的问题

  (1)由于我的程序仍在opengl 2.0下写的,并没有采用shader和GLSL,要做的事情实在太多,明知道需要学习,但还是无法在技术上投入太多时间。

  (2)在上面VAO+VBO+IBO版的代码中遇到了一个问题:颜色没有设置成功(法线没问题),不知为何,仍在寻找中。如果有高手看到烦请赐教。

  (3)关于VBO的更新:目前还没测试更新的效率。GL_STATIC_DRAW之后两种更新方式(复制和直接给出内存映射地址)貌似都需要重新设置/更新数据,还未测试GL_DYNAMIC_DRAW的使用效率。

  (4)对其后台机制还是模棱两可。还是那句话,烦请高手赐教!也欢迎新手讨论!

VAO VBO IBO大乱炖的更多相关文章

  1. opengl中VAO,VBO,IBO用法小结(zz) 【转】

    http://cowboy.1988.blog.163.com/blog/static/751057982014380251300/ opengl中VAO,VBO,IBO用法小结 这三个玩意全面取代旧 ...

  2. opengl中VAO,VBO,IBO用法小结【转】

    http://cowboy.1988.blog.163.com/blog/static/751057982014380251300/ opengl中VAO,VBO,IBO用法小结 这三个玩意全面取代旧 ...

  3. HTM CSS 笔记乱炖

    一.常用实体(字符转义) '<' == '<' '©' == '©' '>' == '>' '"' == '"' ' ' == ' ' '®' == '®' ...

  4. OpenGL ES 2: debugging, and improvements to VAO, VBO

    OpenGL ES 2: debugging, and improvements to VAO, VBO http://www.altdevblogaday.com/2013/10/12/opengl ...

  5. GridView的 PreRender事件与 RowCreated、RowDataBound事件大乱斗

    GridView的 PreRender事件与 RowCreated.RowDataBound事件大乱斗 之前写了几个范例,做了GridView的 PreRender事件与 RowCreated.Row ...

  6. python红蓝英雄大乱斗(面向对象实现)

    红蓝英雄大乱斗 游戏规则 ''' 有红蓝两方英雄(可自定义个数) 随机一方英雄使用随机攻击方式攻击另一方英雄,任意一方英雄全部阵亡则游戏结束 每个英雄有 名字.生命值.普通攻击.Q技能攻击.W技能攻击 ...

  7. OpenGL渲染管道,Shader,VAO&VBO&EBO

    OpenGL渲染管线 (也就是)OpenGL渲染一帧图形的流程 以下列举最简单的,渲染一个三角形的流程,你可以将它视为 精简版OpenGL渲染管线 更复杂的流程也仅仅就是:在此基础上的各个流程中 添加 ...

  8. openGL 提升渲染性能 之 顶点数组 VBO IBO VAO

    使用openGL图形库绘制,都需要通过openGL接口向图像显卡提交顶点数据,显卡根据提交的数据绘制出相应的图形. openGL绘制方式有:直接模式,显示列表,顶点数组,顶点索引. 直接模式:最简单, ...

  9. OpenGL中VA,VAO,VBO和EBO的区别

    1,顶点数组(Vertex Array) VA,顶点数组也是收集好所有的顶点,一次性发送给GPU.不过数据不是存储于GPU中的,绘制速度上没有显示列表快,优点是可以修改数据. 4.VBO(Vertex ...

随机推荐

  1. 《JAVASCRIPT高级程序设计》第五章(1)

    引用类型是一种将数据和功能组合到一起的数据结构,它与类相似,但是是不同的概念:ECMAScript虽然是一门面向对象的语言,但它不具备传统的面向对象语言所支持的类和结构等基本结构.引用类型也被称为“对 ...

  2. ion-scroll zooming="true" android端无法缩放的问题

    很久很久没更新博客了,从今天开始决定以后陆续写一些博文,总结下自己在开发中碰到的问题. ionic项目.ion-scroll zooming="true" 在android端无法缩 ...

  3. Weex系列二、显示图片

    上次我们创建了一个简单的Weex的demo. 一.常用的类 WXSDKEngine:SDK开放的绝大多数接口都在此有声明. WXLog: 用来打印日志. WXDebugTool: weex提供的对外调 ...

  4. Unity渲染优化中文翻译(二)——CPU的优化策略

    紧接上一篇文章,继续渲染的优化问题,若有错误,请指出,让我也学习进步,谢谢. 如果游戏渲染问题来自CPU 概括的来说,CPU在一帧的渲染中的工作可以分为三个部分: . 决定谁需要被渲染 . 为GPU准 ...

  5. MASM32快速起步

    MASM32是一个免费的软件程序,让您编辑Microsoft宏汇编程序(MASM)代码从一个基本的文本界面.它强调MASM代码各部分以不同的颜色,使其更容易扫描和检测错误.它提供了一个简单的布局程序员 ...

  6. PHP Closure创建匿名函数

    Closure 类 用于代表匿名函数的类. 匿名函数(在 PHP 5.3 中被引入)会产生这个类型的对象.在过去,这个类被认为是一个实现细节,但现在可以依赖它做一些事情.自 PHP 5.4 起, 这个 ...

  7. Java 内部类详解

    什么 定义在一个类内部的类,称为内部类(累不累),如下: public class A { private int c = 1; public class C { public void test() ...

  8. laravel中的Database Notifications

    创建Post and  User模型 php artisan make:model Post php artisan make:model User 创建posts and  users 表文件 ph ...

  9. 【2017-02-23】switch...case...和for循环

    1.代码简化折叠: #region 标题 ... ... #endregion 一.switch...case... 1.格式 switch(变量){ case 值:代码段;break; case 值 ...

  10. java基础:数组查询,同一数组一个元素最多出现两次