OpenGL--顶点数组与缓冲区中使用顶点数组
2015-03-21 17:43
274 查看
理论基础
顶点数组:就是把一些顶点数据保存到数组中储存,这些数据包括:顶点坐标,表面法线,RGBA颜色,辅助颜色,颜色索引,雾坐标,纹理坐标以及多边形的边界标志。这样就可以只通过一个函数调用来完成绘制,大大减少了函数的调用次数,同时还可以避免共享顶点的冗余处理,提高了程序性能。缓冲区对象:由于OpenGL是一个CS的结构,有时从客服端传输数据到服务端可能会比较缓慢,所以增加了一个缓冲区对象,可以直接显示的指定把哪些数据存储到图形服务器中。
实例代码
使用顶点数组绘制一个三角形#include "GLTools.h" #include "GLShaderManager.h" #ifdef __APPLE__ #include <glut/glut.h> #else #define FREEGLUT_STATIC #endif static GLint vertices[] = {25, 25, 100, 325, 175, 25, 175, 325, 250, 25, 325, 325}; static GLfloat colors[] = {1.0, 0.2, 0.2, 0.2, 0.2, 1.0, 0.8, 1.0, 0.2, 0.75, 0.75, 0.75, 0.35, 0.35, 0.35, 0.5, 0.5, 0.5}; void display(void) { glClear (GL_COLOR_BUFFER_BIT); //第三步:解引用和渲染 glBegin (GL_TRIANGLES); /*glArrayElement(int v):获取所有开启顶点数组的第v个数据, 作为他们对应的设置数据,执行顺序是先执行的其它类型的顶 点数组,最后才执行顶点坐标数据glVertex*v() */ glArrayElement (2); glArrayElement (3); glArrayElement (5); glEnd (); // //上面等价于下面这种形式 // glBegin(GL_TRIANGLES); // glColor3fv(colors + (2 * 3)); // glVertex2iv(vertices + (2 * 2)); // glColor3fv(colors + (3 * 3)); // glVertex2iv(vertices + (3 * 2)); // glColor3fv(colors + (5 * 3)); // glVertex2iv(vertices + (5 * 2)); // glEnd(); glFlush (); } void setupPointers() { //第一步:激活要使用的顶点数组 glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_COLOR_ARRAY); //第二步:指定数组的数据 glVertexPointer (2, GL_INT, 0, vertices); glColorPointer (3, GL_FLOAT, 0, colors); } void init() { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); setupPointers (); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); /*顶点位置坐标,经过变换矩阵的变换,得到的坐标,才会真的拿去绘制, 所以这里的矩阵变换不能省。*/ glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluOrtho2D (0.0, (GLdouble) w, 0.0, (GLdouble) h); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (350, 350); glutInitWindowPosition (100, 100); glutCreateWindow ("varray"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; }
注释:这里使用的glArrayElement这种顶点数组解引用和渲染的形式,这也是最基本的方式。在它之上还有一些效率更高的接口,如:glDrawElements(),glMultiDrawElements(),glDrawRangeElements()和glDrawArrays()等。
使用缓冲区对象绘制正方体框
#include "GLTools.h" #include "GLShaderManager.h" #ifdef __APPLE__ #include <glut/glut.h> #else #define FREEGLUT_STATIC #endif #define VERTICES 0 #define INDECES 1 #define NUM_DUFFERS 2 GLuint buffers[NUM_DUFFERS]; static GLfloat vertices[] = {-1.0f, -1.0f, -5.0f, //前面的正方形 1.0f, -1.0f,-5.0f, 1.0f, 1.0f, -5.0f, -1.0f, 1.0f, -5.0f, -1.0f, -1.0f, -10.0f,//背面的正方形 1.0f, -1.0f, -10.0f, 1.0f, 1.0f, -10.0f, -1.0f, 1.0f, -10.0f}; static GLubyte indices[] = {0, 1, 2, 3, //前面 0, 3, 7, 4, //左面 5, 6, 2, 1, //右面 7, 6, 5, 4, //后面 3, 2, 6, 7, //上面 1, 0, 4, 5 //地面 }; void init() { glClearColor (0.0, 0.0, 0.0, 0.0); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glShadeModel (GL_FLAT); glewInit();//glGenBuffers是glew库的接口,要初始化它才能认识 //生成缓冲区标示符 glGenBuffers(NUM_DUFFERS, buffers); //绑定顶点缓冲区对象,并设置顶点数组 glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTICES]);//绑定 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//初始化数据,即将数据拷贝到服务器内存 glVertexPointer(3, GL_FLOAT, 0, 0); } void reshape (int w, int h) { if(h == 0) h = 1; glViewport(0, 0, w, h); GLfloat fAspect = (GLfloat)w / (GLfloat)h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); /*透视投影,参数:角度,宽高比,近平面,远平面*/ gluPerspective(35.0f, fAspect, 1.0f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void display(void) { glClear (GL_COLOR_BUFFER_BIT); glColor3f(0.0f, 0.0f, 1.0f); glPushMatrix(); glEnableClientState(GL_VERTEX_ARRAY);//激活顶点数组 //绑定索引缓冲区对象,并进行渲染 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDECES]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0); glDisableClientState(GL_VERTEX_ARRAY);//关闭顶点数组 glPopMatrix(); glutSwapBuffers(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (350, 350); glutInitWindowPosition (100, 100); glutCreateWindow ("VBO"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; }
注释:
glDrawElements(mode, count, type, indices)
是用索引的形式绘制,这样比直接顶点数据渲染效率要高,而这里的索引,直观点讲就是顶点数据数组对应的下标而已。它相当于如下代码:
glBegin(mode);
for(i = 0; i < count; i++)
glArrayElement(indices[i]);
glEnd();
相关文章推荐
- OpenGL--顶点数组与缓冲区中使用顶点数组
- 4.OpenGL--顶点数组与缓冲区中使用顶点数组
- OpenGL使用顶点数组进行图形的绘制
- opengl es3.0学习篇四:顶点属性,顶点数组和缓冲区对象
- OpenGL 顶点数组与缓冲区对象进行渲染(含纹理贴图)
- 看opengl写代码(9)使用顶点数组(VAO)
- opengl中使用顶点数组的方法
- OpenGL 顶点数组的使用
- 看opengl写代码(5) 使用顶点数组
- 在BlackBerry上使用OpenGL绘图(四):顶点数组与法向量数组
- opengl顶点数组
- Qt下的OpenGL 编程(7)顶点数组和显示列表
- OpenGL状态管理和绘制几何物体之顶点数组
- OpenGL系列教程之六:OpenGL顶点数组
- Qt下的OpenGL 编程(7)顶点数组和显示列表
- OpenGL顶点数组
- OpenGL ES中的顶点数组、顶点属性、缓冲区对象
- OpenGL蓝宝书第六章代码疑虑:为什么使用了GL_TEXTURE_1D??纹理和顶点间的映射是如何实现?
- [OpenGL] 兔子与顶点数组、拾取
- 看opengl写代码(7) 使用混合数组(glInterLeavedArrays)