OpenGL编程指南6:顶点数组
来源:互联网 发布:淘宝买水果拒收 编辑:程序博客网 时间:2024/06/01 18:36
1.前言
前面的例子中,我们可以看到,OpenGL需要进行大量的函数调用才能完成对几何图元的渲染。绘制一个20条边的多边形至少需要22个函数调用。首先调用一个glBegin(),然后为每个顶点调用一次函数,最后调用1次glEnd().如果我们还要添加其他的额外信息(如多边形边界标志或表面法线),在每个顶点上还要增加函数调用。这可能会成倍地增加渲染几何物体所需要的函数调用数量。在很多系统中,函数调用具有相当大的开销,可能会影响应用程序的性能。另一个问题是,相邻多边形的共享定点的冗余处理。如上图所示的立方体具有六个面和8个共享顶点。遗憾的是,如果按照标准方法描述这个物体,每个顶点必须被指定3次,因为每个顶点都在三个面上。这样就造成了大量的冗余。幸运的是,OpenGL提供了一些顶点数组函数,允许只用少数几个数组指定大量的与顶点相关的数据,并用少量函数调用(与顶点数组的数量相仿)访问这些数据。使用顶点数组函数,一个拥有20条边的多边形的顶点可以放在一个数组中,并且只通过1个函数进行调用。其实有其他如文理、法向量等,也可以只通过1个函数进行调用。把数据放在顶点数组中可以提高应用程序的性能。使用顶点数组可以减少函数的调用次数,从而提高性能,也可以避免共享顶点的冗余处理。
2.顶点数组对几何图形渲染步骤
1.激活/启用最多可达8个数组
每个数组用于存储不同类型的数据:顶点坐标、表面法线、RGBA颜色、辅助颜色、颜色索引、雾坐标、纹理坐标以及多边形的边界标志。该步骤是调用void glEnableClientState(GLenum array)函数实现。array指定了需要启用的数组。其参数可以是下面常量:GL_VERTEX_ARRAY / GL_COLOR_ARRAY / GL_SECONDARY_COLOR_ARRRAY / GL_INDEX_ARRAY / GL_NORMAL_ARRAY / GL_FOG_COORDINATE_ARRAY / GL_TEXTURE_COORD_ARRAY / GL_EDGE_FLAG_ARRAY.例如,如果我们需要光照,就可以为每一个顶点定义一条发现向量。这种情况下使用顶点数组时,需要同时激活表面法向数组和顶点坐标数组。glEnableClientState(GL_NORMAL_ARRAY);glEnableClientState(GL_VERTEX_ARRAY);void display(void) { glClear(GL_COLOR_BUFFER_BIT); GLfloat vertices[]={0.25,0.25, 0.75,0.25, 0.75,0.75, 0.25,0.75}; GLfloat colors[]={1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2,GL_FLOAT,0,vertices); glColorPointer (3,GL_FLOAT,0,colors); glBegin(GL_POLYGON); glArrayElement(0);glArrayElement(1);glArrayElement(2);glArrayElement(3); glEnd(); glFlush(); }输出结果如下:2.把数据放入数组中
这些数据是通过指针进行访问的。3.绘制几何图形
绘制图形关键点在于“解引用”,而解引用关键在于glArrayElement()函数。该函数通常在glBegin()和glEnd()之间调用。否则,glArrayElement()函数就会设置所有启用数组的当前状态(顶点除外,因为它不存在当前状态)。下面例子展示的是,使用取自启用的顶点数组的0,3,4号顶点绘制三角形。glBegin(GL_POLYGON); glArrayElement(0);glArrayElement(2);glArrayElement(3); glEnd();输出结果:由于glArrayElemrnt()函数对于每个顶点只调用一次,因此它可能减少对函数的调用数量,从而提高程序的整体性能。
3.重启图元
在OpenGL绘制图形时,可能需要绘制多个并不相连的图形。这样的情况下这几个图形没法被当做一个图形来处理。也就需要多次调用 DrawArrays 或 DrawElements. 如果图形很多,可能会需要用一个循环来调用:for (int i = 0; i < num_objects; i++) { glDrawArrays(GL_TRIANGLES, object[n]->first_vertex, object[n]->vertex_count);}每一次调用OpenGL 的绘制函数,都需要一定的资源开销,如果每一帧调用太多次,会对程序的性能产生较大的影响。提高性能的办法就是调用一次绘制函数,画出分散的图形。
一种方法是使用 glMultiDrawElements 函数来代替旧的绘制函数,可以减少调用次数,仅需调用此函数一次即可。但是这个函数在OpenGL ES 没有得到支持。而且使用这个函数,仍然需要将每一个分散的图形维护一组单独的顶点坐标/纹理坐标,这个是免不了的,这些数据仍然需要分开上传,还是会消耗一定的资源。针对这种情况使用图元重启会更加合适。3.1 基本介绍
考虑通常的情况,当用户绘制 GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_LINE_STRIP, GL_LINE_LOOP 这些图元时,所有的绘制点按照特定的顺序被连起来,以形成一个最终的复杂图形,也就是说最终的复杂图形由多个相连的三角形或线段组成。像上面提到的情况,想要绘制分散的图形,应该怎么办?
图元重启(Primitive restart) 允许用户绘制不连续的、分散的图形。考虑使用glDrawElements 函数,绘制时按照indices所指定的顶点的顺序来绘制的。此时可以指定某一个值,该值表示一个重启的标志。遇到这个值的时候,OpenGL不会绘制图元,而是结束上一段绘制,然后重新启动新的绘制,也就是說用后面的索引所指定的顶点来从头绘制一个图形。
举个例子:比如指定8为重启的标志,遇到8就重启。上面的是不启用图元重启的情况,即通常的情况。下面的是启用图元重启的情况,我们可以看到,从9开始,又重新从头开始绘制Triangle strip了。3.2 执行过程
指定重启位置的数值,在桌面版的OpenGL是可以自行设定的,glPrimitiveRestartIndex 函数指定重启的标志。在OpenGL ES 无法自行指定,只能用给定的值。
首先设置启用图元重启:glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);Fixed index就代表了使用固定的重启的标志,具体数值和indices内数据类型有关。glDrawElements 的indices参数类型必须是以下的一种:GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT. 那么分别对应的重启的标志就是 2^8 - 1;2^16 - 1;2^32 - 1;也就是說重启的标志的数值就是indices数组所能允许的最大值。这个值一般来说是不会被用到的,拿来当标志正好。
所以我们只需要在 indices 里面的合适的位置插入一个标志,然后再调用 glDrawElements 函数即可实现图元重启。
下面代码片段是一个具体的例子:
// Prepare index buffer data (not shown: vertex buffer data, loading vertex and index buffers)GLushort indexData[11] = { 0, 1, 2, 3, 4, // triangle strip ABCDE 0xFFFF, // primitive restart index (largest possible GLushort value) 5, 6, 7, 8, 9, // triangle strip FGHIJ};// Draw triangle stripsglEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);glDrawElements(GL_TRIANGLE_STRIP, 11, GL_UNSIGNED_SHORT, 0);
4.参看资料
[1].Primitive Restart Makes GPGPU Tech Sparkle
[2].Combining Drawing Functions, Combining Geometry Using Primitive
[3].TechniquesforWorkingwithVertexData
0 0
- OpenGL编程指南6:顶点数组
- OpenGL编程指南-顶点数组、视图变换、投影变换
- OpenGL ES 3.0编程指南学习笔记 第6章 顶点属性、顶点数组和缓冲区对象
- openGL学习--顶点数组
- OpenGL顶点数组
- OpenGL顶点数组
- OpenGL顶点数组
- OpenGL顶点数组
- opengl顶点数组
- Win32 OpenGL编程(5)顶点数组详细介绍
- 顶点数组, glDrawArrays,glDrawElements - [OpenGL]
- OpenGL学习笔记:顶点数组
- OPENGL顶点数组, glDrawArrays,glDrawElements
- OpenGL学习七:顶点数组
- OPENGL顶点数组, glDrawArrays,glDrawElements
- opengl 顶点数组 学习笔记
- OpenGL 顶点数组的使用
- OpenGL笔记15 顶点数组
- 0penCV_(Watershed Segmenter)使用 分水岭算法 对图像进行分割
- TensorFlow笔记之MNIST例程详解
- 理解ansible里的item和with_items
- 集合
- org.apache.commons.lang.StringUtils方法讲解
- OpenGL编程指南6:顶点数组
- poj 2606 Rabbit hunt
- oracle数据库创建表空间,创建用户,给用户授权
- js 跨域问题解决方案
- CI1.4 字符串空格替换
- Android绕过usb主机permision确认对话框framework修改方案
- [Leetcode] Binary Tree Level Order Traversal & Binary Tree Zigzag Level Order Traversal
- JZOJ5006. A
- Spring 注解