OpenGL ES2.0 Programming Guide - chapter 6:Vertex attributes, vertex array and buffer objects

chapter 6:Vertex attributes, vertex array and buffer objects

概要:
1. 什么是vertex attributes
2. 如何描述vertex attributes,如何存储vertex attribute
3. 如何将vertex attribute index与vertex attribute name绑定
4. 为何要引入顶点缓冲对象?顶点缓冲对象编码流程?
5. 映射缓冲对象到用户空间

阅读逻辑:
什么是vertex attribute -> 两类vertex attributes -> 应用程序设置vertex attribute与index对应关系 -> 在vertex shader中声明应用程序中对应的vertex attribute变量 -> 绑定vertex shader变量与vertex attribute index -> 为何引入缓存对象 -> 缓存对象编码流程 -> 图形内存与用户空间映射

容易懵逼的地方
上述阅读逻辑其实分两块,书里没有明显的说明:
1. 不用缓存对象的OpenGL ES编程
2. 使用缓冲对象的OpenGL ES编程,这里才涉及空间映射问题

什么是vertex attributes

vertex attribute用来描述每一个顶点。每个顶点可以各有各的attribute,也可以一个原件(primitive)内的所有顶点共用attribute。

每个顶点有有四个vertex attributes:position, normal, and two texture coordinates。

如何描述vertex attributes,如何存储vertex attribute

OpenGL ES2.0规定,至少要支持8个vertex attributes。
可以通过constant vertex attribute及vertex arrays描述vertex attribute。以下分别介绍:

1. 常量vertex attribute

可通过glVertexAttrib*族函数来设置constant vertext attribute。

注意:OpenGL中支持的常量类型很多,而OpenGL ES中只支持float常量类型。原因是OpenGL ES中常量vertex attribute并不常用,并且内部一般均以float类型来存储。

2. Vertex arrays

可将用户空间的值通过glVertexAttribPointer函数来设定vertex arrays。最常用的存储vertex attribute数据的方法有两种:

2.1 array of structures

数组以顶点的结构体以基本元素,每个结构体包含position, normal, texture coordinate0和texture coordinate1。存储顺序从低地址到高地址如下(假设存储空间往高地址增长):

vetex 1……vetex n
poisition,normal,tex0,tex1……pisition,normal,tex0,tex1

目前OpenGL ES2.0采用这个方案,有好亦有坏,但利大于弊(欲知原因,请参见P107)

2.2 structure of arrays

所有顶点的position打包在一起存放,Normal也是,tex0也是,tex1也是。存储顺序从低地址到高地址如下(假设存储空间往高地址增长):

positionnormaltex0tex1
postion 1……position nnormal 1……normal ntex0 1……tex0 ntex1 1……tex1 n

描述vertex array还涉及另一个问题,即变量类型问题。OpenGL ES2.0推荐如下:
1. GL_HALF_FLOAT_OES : Texture coordinates, normals,binormals, tangent vectors and so on
2. GL_UNSIGNED_BYTE : vertex Color
3. GL_HALF_FLOAT_OES : vertex position

那么,应用开发者怎么来选择constant vertex attribute或者vertex array来作最终的vertex data呢?

开发人员可以通过glEnableVertexAttribArray / glDisableVertexAttribArray函数来选择开或关vertex array。如果某个attribute index的vertex array被关闭了,那么constant vertex attribute自动会被打开。

如何在vertex shader中声明attribute

上面讲解了如何在OpenGL ES中描述vertex attribute,接下来介绍如何在vertex shader中描述attribute。

  1. attribute只能在vertex shader中声明,fragment shader中声明attribute将会编译错误
  2. attribute只能声明成float, vec2, vec3, vec4, mat2, mat3, mat4,内部均以32位的float类型存储。不能是用于structure,不能声明数组变量。
  3. attribute变量是只读变量,不能被赋值
  4. 当活跃attribute大于GL_MAX_VERTEX_ATTRIBS时,链接会失败。

可通过glGetProgramiv查询活跃attribute数量,通过glGetActiveAttrib查询指定attribute的信息。

绑定给vertex attribute变量分配Index

有两种方法:
1. 显式的通过glBindAttribLocation函数来绑定变量名与索引。
这种绑定将在下一次链接时生效,而且绑定动作可以在shader未与program attach前。
2. 隐式的由链接器自动绑定。

若未通过显式绑定,则在链接阶段会自动绑定attribute与index,但不同的OpenGL ES实现会有不同的绑定机制。因此,可通过glGetAttribLocation确定某个attribute绑定到哪个Index上。

顶点缓冲对象(vertex buffer object)

当调用glDrawArrays或glDrawElements时,存放于客户端内存的vertex data将会被复制到图形内存中(graphics memory)。这种做法将增加电量消耗并且受内存带宽限制。而电量与内存带宽对于手持设备又至关重要,顶点缓冲对象可以很好的解决这两个问题

顶点缓冲对象允许OpenGL ES2.0的应用程序在高性能的图形内存中分配空间来缓存vertex data。此外,vertex index也可以放置于图形内存中。

OpenGL ES支持两类缓冲对象:
1. array buffer object : GL_ARRAY_BUFFER,存放vertex data
2. element array buffer object : GL_ELEMENT_ARRAY_BUFFER,存放vertex attribute index

以下介绍缓冲对象的编码流程:
1. 通过glGenBuffers创建缓冲对象(这步并非必需的,但最好有这一步)
2. 通过glBindBuffer指定缓冲对象存放的是array buffer object还是element array buffer object,并将缓存对象设置为当前值。
3. 通过glBufferData创建并初始化vertex array data或element array data的存储空间。
4. 通过glBufferSubData来初始化或更新缓冲对象数据(并非必需)
5. 通过glDeleteBuffers来删除缓冲对象,及时释放资源

映射缓冲对象到用户空间

通过glMapBufferOES可以将vertex buffer object的数据映射到用户地址空间(映射空间只写不读)。映射成功后,应用程序开发者就可以将对用户地址空间数据的更新映射到图形内存中。

通过glUnmapBufferOES来解除映射。当然,映射成功后如果图形内存空间中对应的空间corrupted了(可能因屏幕分辨率改变、OpenGL ES上下文用于多个屏幕、或者内存溢出),解除将会失败。

Tips

  1. glVertexAttribPointer的参数normalized的用法,规定了非float转换成float时如何进行归一化,因参数normalized的取值true或flase分两类讨论。
  2. 更多函数参数的细节可以在本章节内找到说明,或可查阅相关文档。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值