OpenGL Vertex Array
来源:互联网 发布:云计算网络虚拟化技术 编辑:程序博客网 时间:2024/05/22 00:08
原文地址http://www.songho.ca/opengl/gl_vertexarray.html
概要
你可以在一系列数组保存顶点信息,如顶点坐标,向量,纹理坐标,颜色信息,来代替立即模式下输入顶点信息的方法(即在glBegin()和glEnd()中指定顶点信息)。你可以使用数组索引找到数组中的元素,来画出几何体。仔细看下面使用立即模式下画立方体的代码。
glBegin(GL_TRIANGLES); // draw a cube with 12 triangles // front face ================= glVertex3fv(v0); // v0-v1-v2 glVertex3fv(v1); glVertex3fv(v2); glVertex3fv(v2); // v2-v3-v0 glVertex3fv(v3); glVertex3fv(v0); // right face ================= glVertex3fv(v0); // v0-v3-v4 glVertex3fv(v3); glVertex3fv(v4); glVertex3fv(v4); // v4-v5-v0 glVertex3fv(v5); glVertex3fv(v0); // top face =================== glVertex3fv(v0); // v0-v5-v6 glVertex3fv(v5); glVertex3fv(v6); glVertex3fv(v6); // v6-v1-v0 glVertex3fv(v1); glVertex3fv(v0); ... // draw other 3 facesglEnd();
每一个面要调用glVertex*()函数六次,来画出二个三角形。如前面的三角片v0-v1-v2和三角片v2-v2-v0。一个立方体有六个面,共要调用glVertex*()函数36次。如果你再指定法向量,纹理坐标和顶点对应的颜色,将增加调用OpenGL函数的次数。顶点v0被三个邻近的面共享。前面、右面、顶面。在立即模式下,你使用了此顶点6次,twice for each side as show in the code。使用顶点数组,可以减少函数调用次数和冗余的共享顶点。
有三种不同的OpenGL函数可使用顶点数组。glDrawArrays(),glDrawEelemnts()和glDrawRangeEelemnts().更好的方法是使用vertex buffer objects和display lists。
初始化OpenGL提供glEnableClientState()和glDisableClientState()函数来激活和禁止6种不同类型的数组。6个函数可指定这些数组的地址。OpenGL可在你的程序里访问这些数组。(me:即这些数组放在内存里,而不是显卡中)。glVertexPointer(): 指定一个指向顶点坐标的数组
glNormalPointer(): 指定一个指向法向量的数组
glColorPointer(): 指定一个指向颜色的数组
glIndexPointer(): 指定一个指向索引的数组
glTexCoordPointer(): 指定一个指向纹理的数组
glEdgeFlagPointer(): 指定一个指向边标志的数组
glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
size: 顶点坐标的数量,2为2D点,3为3D点
type: GL_FLOAT, GL_SHORT, GL_INT或GL_DOUBLE.
stride: 到下一个顶点的偏移字节数(用于interleaved数组)
pointer: 指向顶点的数组
glNormalPointer(GLenum type, GLsizei stride, const GLvoid* pointer)
type: GL_FLOAT, GL_SHORT, GL_INT or GL_DOUBLE.
stride: 到下一个顶点的偏移字节数(用于interleaved数组)
pointer: 指向顶点的数组
注意,顶点数组在你的程序中(系统内存中),即在客户端。OpenGL在服务端访问它们。用glEnableClientState()和glDisableClientState()代替glEnable和glDisable()。
glDrawArrays()
glDrawArrays()从数组中读取顶点数据,但不能在数组中跳来跳去(me:即按索引顺序0,1,2,...,n读取数组元素,不能随机读取数组元素)。因为glDrawArrays()不允许在顶点数组中跳来跳去,你仍要重复每个面上的共享顶点。
glDrawArrays()有三个参数。第一个参数是图元类型。第二个参数是数组的偏移值。最后一个参数是顶点数组中顶点的数量。在上面画立方体的例子中,第一个参数是GL_TRIANGLES,第二个参数是,即从数组起点处开始。最后一个参数是36.一个立方体有6张面。每张面有6个顶点。每张面有二个三角形。共6x6=36
GLfloat vertices[] = {...}; // 36 of vertex coords...// activate and specify pointer to vertex arrayglEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(3, GL_FLOAT, 0, vertices);// draw a cubeglDrawArrays(GL_TRIANGLES, 0, 36);// deactivate vertex arrays after drawingglDisableClientState(GL_VERTEX_ARRAY);你可以使用一个glDrawArrays()代替36个glVertex*()。然而,我们仍要重复共享的顶点,这样在数组中定义的顶点数仍旧是36个而不是8个。glDrawElements()可以减少在数组中顶点的数量,这样可向OpenGL传递更少的数据。
glDrawElements()
glDrawElements()可以使用相关的索引数组,按索引访问顶点数组,来画出图像。它即可以减少函数的调用次数也可以减少顶点的传输量。OpenGL可能缓存最近的被处理的结果并重用它们,而不用多次发送同样的顶点数据到渲染管线中。glDrawElements需要4个参数:第一个参数是图元的类型,第二个参数是索引数组中索引的数量。第三个参数是索引数组的类型。最后一个参数是索引数组的地址。在此例中,参数为GL_TRIANGLES,36,GL_UNSIGNED_BYTE和索引数组地址。
<me>
void glVertexPointer( GLint size,
GLenum type,
GLsizei stride,
const GLvoid * pointer);
glVertexPointer定义一个顶点坐标数量。
size 为每个顶点的坐标数量。必须是2,3,4。初始值为4.即(x,y),(x,y,z)及齐次坐标(x,y,z,w)
type 每个坐标分量的类型。可以是GL_SHORT,GL_INT,GL_FLOAT,或者是GL_DOUBLE。初始值为GL_FLOAT.
stride 指定两个连续顶点的字节偏移量。如果stride是0,顶点在数组中紧密排布。初始值为0。
pointer 指定数组地址。
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
在此例中,顶点为三维点,故第一个参数为3,vertices的元素类型为GL_Float,故第二个参数为GL_FLOATglVertexPointer指定了glDrawElements要用到的顶点数据数组。而后,要为glDrawElements指定一个索引数组,此后glDrawElements从最近一次由glVertexPointer指定的顶点数组中,按索引数组indices中索引的顺序取顶点,完成绘图工作。
</me>
GLfloat vertices[] = {...}; // 8 of vertex coordsGLubyte indices[] = {0,1,2, 2,3,0, // 36 of indices 0,3,4, 4,5,0, 0,5,6, 6,1,0, 1,6,7, 7,2,1, 7,4,3, 3,2,7, 4,7,6, 6,5,4};...// activate and specify pointer to vertex arrayglEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(3, GL_FLOAT, 0, vertices);// draw a cubeglDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);// deactivate vertex arrays after drawingglDisableClientState(GL_VERTEX_ARRAY);顶点坐标数组的大小现在为8,此为立方体没有冗余的顶点数。
注意索引数组的数据类型为GLubyte,而不是GLuint或GLushort。这样做,是为了减小索引数组的大小。GLubyte的大小可以
满足此例中最大索引数量的需要,否则可能会引起数据丢失。因为顶点数组包含8个顶点,GUubtye足够储存所有索引了。
在共享顶点上的不同的法向量
glDrawRangeElements()
类似glDrawElements(), glDrawRangeElements()也可随机访问顶点数组。 然而,glDrawRangeElements()多了两个参数(start and end index) ,用来事先指定顶点的范围。通过添加范围约束,OpengGL可能事先得到顶点数据数组的受限大小,这可能提升性能。 在glDrawRangeElements中额外的参数是start和end index, OpenGL可以事先得到受限的顶点数组的大小:end - start + 1. 此值必须在start和end index之间。注意,晨不是所有在(start,end)范围内的的顶点都会都引用。But, if you specify a sparsely used range, it causes unnecessary process for many unused vertices in that range.GLfloat vertices[] = {...}; // 8 of vertex coordsGLubyte indices[] = {0,1,2, 2,3,0, // first half (18 indices) 0,3,4, 4,5,0, 0,5,6, 6,1,0, 1,6,7, 7,2,1, // second half (18 indices) 7,4,3, 3,2,7, 4,7,6, 6,5,4};...// activate and specify pointer to vertex arrayglEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(3, GL_FLOAT, 0, vertices);// draw first half, range is 6 - 0 + 1 = 7 vertices usedglDrawRangeElements(GL_TRIANGLES, 0, 6, 18, GL_UNSIGNED_BYTE, indices);// draw second half, range is 7 - 1 + 1 = 7 vertices usedglDrawRangeElements(GL_TRIANGLES, 1, 7, 18, GL_UNSIGNED_BYTE, indices+18);// deactivate vertex arrays after drawingglDisableClientState(GL_VERTEX_ARRAY);使用glGetIntegerv(),传入参数GL_MAX_ELEMENTS_VERTICES或GL_MAX_ELEMENTS_INDICES,你便可以查询顶点数组和索引数组的最大值。注意glDrawRangeElements()在OpenGL1.2及更高版本中有效。
- OpenGL Vertex Array【转】
- [转]OpenGL Vertex Array
- OpenGL Vertex Array
- OpenGL Vertex Array
- OpenGL Vertex Array
- OpenGL Vertex Array
- OpenGL.Vertex Array Object (VAO).
- 关于OpenGL中VAO(Vertex Array Object)的理解
- OpenGL顶点数组对象(vertex Array Object)VAO
- OpenGL ES2.0 Programming Guide - chapter 6:Vertex attributes, vertex array and buffer objects
- Vertex Cache (OpenGL实现)
- openGL CG2 vertex lighting
- [OpenGL]Vertex Specification
- OpenGL 之顶点vertex
- OpenGL Vertex Buffer Objects(VBOs)
- OpenGL Vertex Buffer Object (VBO)
- OpenGL Vertex Buffer Object (VBO)
- OpenGL Vertex Buffer Objects(VBOs)
- linux cpu信息查看
- 关于TNS_ADMIN环境变量
- 考验智商的谜题
- StrCat <shlwapi.h> strcat <string.h> wcscat <string.h>
- 【计算几何】计算几何复习
- OpenGL Vertex Array
- Ubuntu 防火墙配置(转载)
- 作为软件工程师,你必须知道的20个常识
- accept()函数
- 在MySql中添加远程超级用户
- How To Install Berkeley DB
- 拆分公式函数及应用
- 平滑升级Nginx的Shell脚本
- 安装配置VPN服务端和客服端