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

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. JavaSE 教程的选择

    你好 我是大福 你现在看的是大福笔记 又降温了 下点小雨 出门有点冷 走路到公司20多分钟,又走的有点热 昨天说到了,今年的计划是从零开始重新学习并梳理下这两年学习和接触到的技术 那么今天开始第一个知 ...

  2. Applovin Interview (面经)

    职位:SDE Intern positon 地点: San Jose 轮电面:self introduction what's your interest Concept of "Concu ...

  3. SpringMVC:学习笔记(2)——RequestMapping及请求映射

    SpringMVC--RequestMapping及请求映射 @RequestMapping 说明 Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请 ...

  4. mybatis入门-动态sql

    什么是动态sql 判断的动态sql mybatis核心就是对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接.组装. 现有需求如下:需要查询用户,输入的是用户类,如果用户的性别类不为空 ...

  5. Ansible_自动化运维《Ansible之初识-1》

    1.Ansible简介 1.1 Ansible介绍 Ansible 是一个简单的自动化运维管理工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fab ...

  6. JavaScript处理json格式数据

    JSON即JavaScript对象标记,是一种轻量级的数据交换格式,非常适用于服务器与JavaScript的交互.JSON是基于纯文本的数据格式. JSON是JavaScript的原生格式,可以使用J ...

  7. 新学到的xss姿势,分享一下

    在js中有一种神奇的对象叫做window 当页面中包含如类似的 <script>var c = urlQuery("callback"); var r = JSON.p ...

  8. android列表停止滚动,加载图片,较为通用的一种办法

    在Adapter的itemView里面,判断列表是否在滚动中,其实是比较麻烦的,可能耦合性会比较严重. 所以考虑了下,是否能在itemView里面,检测列表的滚动状态,并监听停止状态加载图片,实现it ...

  9. 学习笔记——Java核心技术之接口、继承与多态练习题

    1.创建一个抽象类,验证它是否可以实例化对象. package com.lzw; public abstract class UseCase3 { abstract void doit(); publ ...

  10. 《经久不衰的Spring框架:Spring+SpringMVC+MyBatis 整合》

    前言 主角即Spring.SpringMVC.MyBatis,即所谓的SSM框架,大家应该也都有所了解,概念性的东西就不写了,有万能的百度.之前没有记录SSM整合的过程,这次刚刚好基于自己的一个小项目 ...