[转]OpenGL快速渲染函数glDrawElements使用说明
2010-01-18 16:50
489 查看
OpenGL基本的绘图函数例如glVertex、glNormal等在调试模式下运行时,如果模型的顶点数或者三角面数过大(比如超过一万时),则程序运行速度会非常慢,根本就无法进行正常的调试。为此查阅了相关资料,找到glArrayElement、glDrawElements这两个个函数。这两个函数都能通过少数几条语句的调用实现大量数据的绘制,从而节省了函数调用的资源占用。
glArrayElement函数用法简单直接,只要把所有的顶点、法向量等数据,按照三角形的顺序准备好,就可以直接渲染,但缺点是不支持顶点索引,所以内存占用比较大。举例来说,如果一个网格有100个顶点,一般大约会有200个三角面,如果使用glArrayElement就需要存储200×3=600个顶点的数据,相比原有的数据多了5倍。如果是已经条带化的数据,这种冗余数据多的可能就不只5倍了。权衡之下还是决定使用glDrawElements函数。
glDrawElements函数支持顶点数据列表,更为方便的是它还支持顶点索引,所以就成为了快速渲染的首选。可是我在具体使用过程中,却总是没有任何顶点数据被绘制出来,查了相关资料,既不是数据错误,也不是硬件不支持,只好暂时搁置一边了。一个偶然的机会,我看到某段示例代码,发现glDrawElements中索引数据类型的参数是GL_UNSIGNED_INT,而我之前用的参数都是GL_INT(因为算法的需要,有时需要存储负数索引,以表示正反方向的不同)。抱着试试看的想法,我把参数改成了GL_UNSIGNED_INT,结果竟然绘制出图像来了。赶紧查阅了MSDN,对glDrawElements的说明如下:
void glDrawElements(
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices
);
注意其中对type参数的说明,索引数据的类型必须是GL_UNSIGNED_BYTE、GL_UNSIGNED_SHORT、GL_UNSIGNED_INT之一。这一来就解释了为什么glDrawElements没有绘制出任何元素的问题所在了。可气的是OpenGL竟然没有对这个问题给出任何的提示,不知到是不是微软有意如此淡化OpenGL的作用,如果改天有机会可以用linux系统下的编译器作作测试。
最后,附上我在渲染时调用的部分代码。
//顶点
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, (float*)m_vDataCoord[0]);
// 法向量
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, (float*)m_vDataNormal[0]);
//顶点颜色
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0, (float*)m_vDataColor[0]);
//纹理坐标
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, (float*)m_vDataUv[0]);
glDrawElements(GL_TRIANGLES, (GLsizei)m_vIndexCoord.size()*3, GL_UNSIGNED_INT, (GLvoid*)m_vIndexCoord[0]);
glArrayElement函数用法简单直接,只要把所有的顶点、法向量等数据,按照三角形的顺序准备好,就可以直接渲染,但缺点是不支持顶点索引,所以内存占用比较大。举例来说,如果一个网格有100个顶点,一般大约会有200个三角面,如果使用glArrayElement就需要存储200×3=600个顶点的数据,相比原有的数据多了5倍。如果是已经条带化的数据,这种冗余数据多的可能就不只5倍了。权衡之下还是决定使用glDrawElements函数。
glDrawElements函数支持顶点数据列表,更为方便的是它还支持顶点索引,所以就成为了快速渲染的首选。可是我在具体使用过程中,却总是没有任何顶点数据被绘制出来,查了相关资料,既不是数据错误,也不是硬件不支持,只好暂时搁置一边了。一个偶然的机会,我看到某段示例代码,发现glDrawElements中索引数据类型的参数是GL_UNSIGNED_INT,而我之前用的参数都是GL_INT(因为算法的需要,有时需要存储负数索引,以表示正反方向的不同)。抱着试试看的想法,我把参数改成了GL_UNSIGNED_INT,结果竟然绘制出图像来了。赶紧查阅了MSDN,对glDrawElements的说明如下:
void glDrawElements(
GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices
);
Parameters
mode The kind of primitives to render. It can assume one of the following symbolic values: GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON. count The number of elements to be rendered. type The type of the values in indices. Must be one of GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT. indices A pointer to the location where the indices are stored.注意其中对type参数的说明,索引数据的类型必须是GL_UNSIGNED_BYTE、GL_UNSIGNED_SHORT、GL_UNSIGNED_INT之一。这一来就解释了为什么glDrawElements没有绘制出任何元素的问题所在了。可气的是OpenGL竟然没有对这个问题给出任何的提示,不知到是不是微软有意如此淡化OpenGL的作用,如果改天有机会可以用linux系统下的编译器作作测试。
最后,附上我在渲染时调用的部分代码。
//顶点
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, (float*)m_vDataCoord[0]);
// 法向量
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, (float*)m_vDataNormal[0]);
//顶点颜色
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0, (float*)m_vDataColor[0]);
//纹理坐标
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, (float*)m_vDataUv[0]);
glDrawElements(GL_TRIANGLES, (GLsizei)m_vIndexCoord.size()*3, GL_UNSIGNED_INT, (GLvoid*)m_vIndexCoord[0]);
相关文章推荐
- OpenGL7-1-快速绘制接口(使用高效的函数接口进行绘制)
- OpenGL7-1-快速绘制接口(使用高效的函数接口进行绘制)
- sscanf和sprintf()函数使用说明
- . 有一个一维数组,里面存储整形数据,请写一个函数,将他们按从大到小的顺序排列,要求执行效率高,并说明如何改善执行效率(该函数必须自己实现,不能使用php函数)。
- [原型扩展] 实用型功能函数集合 [使用说明]
- php array_map()数组函数使用说明
- IP处理函数inet_aton()和inet_ntoa()使用说明
- Screen快速使用说明
- 使用doxygen生成头文件函数说明文档/帮助文档
- VS下Qt的例子使用OpenGL遇到glGetIntegerv函数崩溃
- 自译: 如何使用服务器端渲染构建快速加载的React apps
- SQL SERVER 中日期格式化,及GETDATE()、CONVERT()函数使用说明
- OpenGL 函数 gluLookAt() glScalef() glTranslatef() glRotatef() glFrustum() glPerspective() 的使用
- OpenGL API glDrawElements
- Matlab之exist函数使用说明
- OpenGL glDrawBuffer()函数
- PHP中header()函数使用说明
- access()函数 linux 使用说明
- glDrawElements(函数)
- 在Lua脚本中使用OpenGL函数