一、Vertex Attributes简介

Vertex属性即顶点数据,它指定了每个顶点的各种属性数据。在OpenGL ES1.1中,顶点属性有四个预定义的名字:position(位置), normal(法线), color(颜色), 和 texture coordinates(纹理坐标)。在OpenGL ES2.0中,用户必须定义“顶点属性的名字”。

二、常量顶点属性(Constant Vertex Attribute)

常量顶点属性对所有顶点都是一样的。因此只需要指定一个值就可以应用于所有顶点。一般很少使用。其设置函数有:

void glVertexAttrib1f(GLuint index, GLfloat x);
void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z,GLfloat w);
void glVertexAttrib1fv(GLuint index, const GLfloat *values);
void glVertexAttrib2fv(GLuint index, const GLfloat *values);
void glVertexAttrib3fv(GLuint index, const GLfloat *values);
void glVertexAttrib4fv(GLuint index, const GLfloat *values);

三、 如何装载顶点数据?(Vertex Arrays)

Vertex Array(顶点数组):是一个存储在应用程序空间(Client)中的内存buffer,它存储了每个顶点的属性数据。

如何把顶点数据组的数据传递给GPU呢?

void glVertexAttribPointer(GLuint index,

GLint size,     //每个属性元素个数有效值1-4(x,y,z,w)
                                                GLenum type,
                                                GLboolean normalized,
                                                GLsizei stride, //如果数据连续存放,则为0
                                                const void *ptr)  //顶点数组指针

举例如下:

   GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f, -0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f };// Set the viewportglViewport ( 0, 0, esContext->width, esContext->height );// Clear the color bufferglClear ( GL_COLOR_BUFFER_BIT );// Use the program objectglUseProgram (programObject );// Load the vertex dataglVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );

四、顶点属性数据存储方式

1.一个顶点的所有属性存储在一起(Array of Structures)

如下图所示,顶点的位置(x,y,z)、法线(x,y,z)和两个纹理坐标(s,t)存储在一起,如下图所示:

例子代码如下(当然,此代码在CPU上运动):

#define VERTEX_POS_SIZE         3 // x, y and z
#define VERTEX_NORMAL_SIZE      3 // x, y and z
#define VERTEX_TEXCOORD0_SIZE   2 // s and t
#define VERTEX_TEXCOORD1_SIZE   2 // s and t#define VERTEX_POS_INDX         0
#define VERTEX_NORMAL_INDX      1
#define VERTEX_TEXCOORD0_INDX   2
#define VERTEX_TEXCOORD1_INDX   3// the following 4 defines are used to determine location of various
// attributes if vertex data is are stored as an array of structures
#define VERTEX_POS_OFFSET       0
#define VERTEX_NORMAL_OFFSET    3
#define VERTEX_TEXCOORD0_OFFSET 6
#define VERTEX_TEXCOORD1_OFFSET 8#define VERTEX_ATTRIB_SIZE  VERTEX_POS_SIZE + \VERTEX_NORMAL_SIZE + \VERTEX_TEXCOORD0_SIZE + \VERTEX_TEXCOORD1_SIZEfloat *p = malloc(numVertices * VERTEX_ATTRIB_SIZE* sizeof(float));// position is vertex attribute 0
glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,GL_FLOAT, GL_FALSE,VERTEX_ATTRIB_SIZE * sizeof(float),p+VERTEX_POS_OFFSET);// normal is vertex attribute 1
glVertexAttribPointer(VERTEX_NORMAL_INDX, VERTEX_NORMAL_SIZE,GL_FLOAT, GL_FALSE,VERTEX_ATTRIB_SIZE * sizeof(float),(p + VERTEX_NORMAL_OFFSET));// texture coordinate 0 is vertex attribute 2
glVertexAttribPointer(VERTEX_TEXCOORD0_INDX, VERTEX_TEXCOORD0_SIZE,GL_FLOAT, GL_FALSE,VERTEX_ATTRIB_SIZE * sizeof(float),(p + VERTEX_TEXCOORD0_OFFSET));// texture coordinate 1 is vertex attribute 3
glVertexAttribPointer(VERTEX_TEXCOORD1_INDX, VERTEX_TEXCOORD1_SIZE,GL_FLOAT, GL_FALSE,VERTEX_ATTRIB_SIZE * sizeof(float),(p + VERTEX_TEXCOORD1_OFFSET));

2. 顶点的每个属性单独存储(Structure of Arrays)

例子代码如下(当然,此代码在CPU上运动):

#define VERTEX_POS_SIZE         3 // x, y and z
#define VERTEX_NORMAL_SIZE      3 // x, y and z
#define VERTEX_TEXCOORD0_SIZE   2 // s and t
#define VERTEX_TEXCOORD1_SIZE   2 // s and t#define VERTEX_POS_INDX         0
#define VERTEX_NORMAL_INDX      1
#define VERTEX_TEXCOORD0_INDX   2
#define VERTEX_TEXCOORD1_INDX   3#define VERTEX_ATTRIB_SIZE  VERTEX_POS_SIZE + \VERTEX_NORMAL_SIZE + \VERTEX_TEXCOORD0_SIZE + \VERTEX_TEXCOORD1_SIZEfloat *position  = malloc(numVertices * VERTEX_POS_SIZE *sizeof(float));
float *normal    = malloc(numVertices * VERTEX_NORMAL_SIZE *sizeof(float));
float *texcoord0 = malloc(numVertices * VERTEX_TEXCOORD0_SIZE *sizeof(float));
float *texcoord1 = malloc(numVertices * VERTEX_TEXCOORD1_SIZE *sizeof(float));// position is vertex attribute 0
glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,GL_FLOAT, GL_FALSE,VERTEX_POS_SIZE * sizeof(float), position);// normal is vertex attribute 1
glVertexAttribPointer(VERTEX_NORMAL_INDX, VERTEX_NORMAL_SIZE,GL_FLOAT, GL_FALSE,VERTEX_NORMAL_SIZE * sizeof(float), normal);// texture coordinate 0 is vertex attribute 2
glVertexAttribPointer(VERTEX_TEXCOORD0_INDX, VERTEX_TEXCOORD0_SIZE,GL_FLOAT, GL_FALSE, VERTEX_TEXCOORD0_SIZE *sizeof(float), texcoord0);// texture coordinate 1 is vertex attribute 3
glVertexAttribPointer(VERTEX_TEXCOORD1_INDX, VERTEX_TEXCOORD1_SIZE,GL_FLOAT, GL_FALSE,VERTEX_TEXCOORD1_SIZE * sizeof(float),  //也可为0,因为数据是紧接着存放的texcoord1);

3. 哪种顶点属性数据存储方式在GPU上性能更好?

    答案是:把一个顶点的所有属性放在一起(array of structures)。其原因是每个顶点的属性数据以连续的方式读取,使内存访问效率更高。其缺点是,如果要修改其中部分属性数据,将导致整个属性buffer全部重新装载,解决此问题的方法是把这些需要动态修改的属性数据放在单独的buffer中。

五、 顶点属性数据类型优化

顶点属性数据类型不会影响在GPU上每个顶点占用的内存,但在Render a Frame时,它影响CPU与GPU之间的内存带宽。推荐尽量使用GL_HALF_FLOAT_OES。

六、glVertexAttribPointer中的归一化参数

如果normalized为GL_FALSE:则直接把数据转换为GLfloat,因为Vertex Shader内部把顶点属性当作GLfloat(32位)来进行存储。

GL_BYTE, GL_SHORT or GL_FIXED被归一化为[-1,1];GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT被归一化为[0.0,1.0]。具体转换公式为:

七、选择常量或顶点数组Vertex Attribute

可通过以下函数来Enable或Disable顶点数组(Vertex Array)。

void glEnableVertexAttribArray(GLuint index);
void glDisableVertexAttribArray(GLuint index);

其关系如下图所示:

 八、申明attribute变量(在Vertex Shader中)

Attribute变量的数据类型只能为:float, vec2,vec3, vec4, mat2, mat3, and mat4;Attribute变量不能为数组或结构。如下面的申明是错误的:

      attribute foo_t a_A; // foo_t is a structureattribute vec4 a_B[10];

每个GPU支持GL_MAX_VERTEX_ATTRIBS vec4。float、vec2和vec3也被当作一个vec4来进行存储;mat2、mat3、mat4被分别当作2、3、和4个vec4来进行存储。

九、把“顶点属性索引”绑定到“顶点属性名”

把“顶点属性索引”绑定到“顶点属性名”有以下两个方法:

1)OpenGL ES 2.0把“顶点属性索引”绑定到“顶点属性名”,当link program时,OpengGL ES 2.0执行此绑定。然后应用程序通过glGetAttribLocation(失败时返回-1)获取“顶点属性索引”。

     GLint glGetAttribLocation(GLuint program, const GLchar *name)

2)应用程序通过glBindAttribLocation把“顶点属性索引”绑定到“顶点属性名”,glBindAttribLocation在program被link之前执行。

       void glBindAttribLocation(GLuint program, GLuint index,const GLchar *name)

在link program时,OpenGL ES 2.0对每个顶点属性执行如下操作:

(1)首先检查属性变量是否被通过glBindAttribLocation绑定了属性索引,如果是,则使用此绑定的属性索引;否则,为之分配一个属性索引。

在应用程序中,一般使用函数glBindAttribLocation来绑定每个attribute变量的位置,然后用函数glVertexAttribPointer为每个attribute变量赋值。

十、顶点buffer对象(Vertex Buffer Objects)

顶点数组(Vertex Array)被保存在客户端内存,当执行glDrawArrays 或 glDrawElements时,才把它们从客户端内存copy到图形内存。这样占用了大量的内存带宽,Vertex Buffer Objects允许OpengGL ES2.0应用在高性能的图形内存中分配并cache顶点数据,然后从此图形内存中执行render,这样避免了每次画一个原语都要重发送数据。

Vertex Buffer Objects有以下两种类型:

(1)array buffer objects:通过GL_ARRAY_BUFFER标记创建,并存储vertex data。

(2)element array buffer objects:通过GL_ELEMENT_ARRAY_BUFFER标记创建,并存储indices of a primitive。

创建和绑定Vertex Buffer Objects例子代码如下:

void initVertexBufferObjects(vertex_t *vertexBuffer,GLushort *indices,GLuint numVertices, GLuint numIndicesGLuint *vboIds)
{glGenBuffers(2, vboIds);glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertex_t),vertexBuffer, GL_STATIC_DRAW); //save vertex attribute data// bind buffer object for element indicesglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]);glBufferData(GL_ELEMENT_ARRAY_BUFFER,numIndices * sizeof(GLushort),indices,GL_STATIC_DRAW); // save element indices that make up the primitive
}

有无Vertex Buffer Object画图例子:

#define VERTEX_POS_SIZE 3 // x, y and z
#define VERTEX_NORMAL_SIZE 3 // x, y and z
#define VERTEX_TEXCOORD0_SIZE 2 // s and t
#define VERTEX_POS_INDX 0
#define VERTEX_NORMAL_INDX 1
#define VERTEX_TEXCOORD0_INDX 2
//
// vertices – pointer to a buffer that contains vertex attribute
data
// vtxStride – stride of attribute data / vertex in bytes
// numIndices – number of indices that make up primitive
// drawn as triangles
// indices - pointer to element index buffer.
//
void drawPrimitiveWithoutVBOs(GLfloat *vertices, GLint vtxStride,GLint numIndices, GLushort *indices)
{GLfloat *vtxBuf = vertices;glBindBuffer(GL_ARRAY_BUFFER, 0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);glEnableVertexAttribArray(VERTEX_POS_INDX);glEnableVertexAttribArray(VERTEX_NORMAL_INDX);glEnableVertexAttribArray{VERTEX_TEXCOORD0_INDX);glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,GL_FLOAT, GL_FALSE, vtxStride, vtxBuf);vtxBuf += VERTEX_POS_SIZE;glVertexAttribPointer(VERTEX_NORMAL_INDX, VERTEX_NORMAL_SIZE,GL_FLOAT, GL_FALSE, vtxStride, vtxBuf);vtxBuf += VERTEX_NORMAL_SIZE;glVertexAttribPointer(VERTEX_TEXCOORD0_INDX,VERTEX_TEXCOORD0_SIZE, GL_FLOAT,GL_FALSE, vtxStride, vtxBuf);glBindAttribLocation(program, VERTEX_POS_INDX, "v_position");glBindAttribLocation(program, VERTEX_NORMAL_INDX, "v_normal");glBindAttribLocation(program, VERTEX_TEXCOORD0_INDX,"v_texcoord");glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT,indices);
}
void drawPrimitiveWithVBOs(GLint numVertices, GLfloat *vtxBuf,GLint vtxStride, GLint numIndices,GLushort *indices)
{GLuint offset = 0;GLuint vboIds[2];// vboIds[0] – used to store vertex attribute data// vboIds[1] – used to store element indicesglGenBuffers(2, vboIds);glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);glBufferData(GL_ARRAY_BUFFER, vtxStride * numVertices,vtxBuf, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort) * numIndices,indices, GL_STATIC_DRAW);glEnableVertexAttribArray(VERTEX_POS_INDX);glEnableVertexAttribArray(VERTEX_NORMAL_INDX);glEnableVertexAttribArray{VERTEX_TEXCOORD0_INDX);glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,GL_FLOAT, GL_FALSE, vtxStride,(const void*)offset);offset += VERTEX_POS_SIZE * sizeof(GLfloat);glVertexAttribPointer(VERTEX_NORMAL_INDX, VERTEX_NORMAL_SIZE,GL_FLOAT, GL_FALSE, vtxStride,(const void*)offset);offset += VERTEX_NORMAL_SIZE * sizeof(GLfloat);glVertexAttribPointer(VERTEX_TEXCOORD0_INDX,VERTEX_TEXCOORD0_SIZE,GL_FLOAT, GL_FALSE, vtxStride,(const void*)offset);glBindAttribLocation(program, VERTEX_POS_INDX, "v_position");glBindAttribLocation(program, VERTEX_NORMAL_INDX, "v_normal");glBindAttribLocation(program, VERTEX_TEXCOORD0_INDX,"v_texcoord");glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);glDeleteBuffers(2, vboIds);
}

Vertex Atrributes相关推荐

  1. R语言使用igraph包进行网络(network)可视化实战:将变量映射到网络节点(vertex)、将变量映射到网络的边(edge)

    R语言使用igraph包进行网络(network)可视化实战:将变量映射到网络节点(vertex).将变量映射到网络的边(edge) 目录

  2. 集合覆盖 顶点覆盖: set cover和vertex cover

    这里将讲解一下npc问题中set cover和vertex cover分别是什么. set cover: 问题定义: 实例:现在有一个集合A,其中包含了m个元素(注意,集合是无序的,并且包含的元素也是 ...

  3. OpenGL Vertex Array

    原文地址 http://www.songho.ca/opengl/gl_vertexarray.html<-------这博客不错!貌似博主是个棒子. OpenGL Vertex Array R ...

  4. 1134. Vertex Cover (25)

    1134. Vertex Cover (25) 时间限制 600 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A vertex ...

  5. PAT甲级1154 Vertex Coloring :[C++题解]图论、模拟、结构体存边

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 这题的边不用邻接矩阵.邻接表来存,仅仅用结构体来存即可,结构体正好存边的两个端点,我们只要遍历每条边,判断端点的颜色是否相同即可. ...

  6. PAT甲级1134 Vertex Cover :[C++题解]顶点覆盖、图论、用结构体存边,bool数组判断

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析:首先把所有的边存储下来,使用结构体,结构体中保存两个端点. 然后对于每次询问,将出现过的顶点标志为true放在st数组中,然后遍历所有 ...

  7. 五大因素推动中国AI崛起,生态报告概览中国AI产业 By 机器之心2017年7月17日 12:51 中国的人工智能将会在全世界扮演什么样的角色?最近,风险投资机构Vertex发表了一份生态研究报告

    五大因素推动中国AI崛起,生态报告概览中国AI产业 By 机器之心2017年7月17日 12:51 中国的人工智能将会在全世界扮演什么样的角色?最近,风险投资机构Vertex发表了一份生态研究报告,从 ...

  8. shader 2: vertex, fragment, surf的区别

    vertex shader, fragment shader, surf shader vertex shader逐个对顶点进行变换.---->得到物体的轮廓,然后对面上的像素光照进行线性插值. ...

  9. boost::graph模块演示 GGCL Vertex 接口

    boost::graph模块演示 GGCL Vertex 接口 实现功能 C++实现代码 实现功能 boost::graph模块演示 GGCL Vertex 接口 C++实现代码 #include & ...

最新文章

  1. python ---Pandas时间序列:生成指定范围的日期
  2. wpf学习笔记二 深入学习 xaml
  3. 张航、李沐等人提出ResNet最强改进版:性能提高3%,参数不增
  4. vsftpd系统用户配置详解
  5. 在sqlyog中创建MySQL触发器简单实例
  6. 关于for in和for循环的遍历
  7. PHP第三方易宝支付对接
  8. 界面控件DevExpress WinForms v21.2 - 全新升级的图表控件
  9. 声网合伙人王骅:聊聊企业拥抱全球化 关键是什么?
  10. 解锁三星bl锁有几种方法_三星Note5解锁教程_三星Note5 CROM解BL锁的方法
  11. html+css设置背景图移动以及人物行走的动画效果
  12. 智能家居巨头 Aqara 基于 KubeSphere 打造物联网微服务平台
  13. 122412_0529_WORD2013BLO1
  14. java做mp3_用java编写MP3播放器
  15. ESD与EOS(surge)防护器件选型
  16. 全日制本科生入户东莞指南
  17. iframe跨域嵌套头部
  18. Flutter中的Scaffold
  19. Python3安装完全攻略 Mac篇
  20. XMind思维导图相关教程

热门文章

  1. 数电和Verilog-基础概念
  2. 刘韧:和人物共同创作人物故事
  3. mysql5.5版本 64位+界面工具中文破解版版(有教程)
  4. 求n+nn+nnn+nnnn+nnnnn+nnnnnn
  5. 要用什么态度去面对生活?
  6. python 播放声音 叮咚_Python
  7. mac book 华为C8815不能debug
  8. 把笔记本变为无线路由器使用(win7无需软件)
  9. ubuntu 下怎么查看内存条状况
  10. c语言程序设计在哪讲,《C语言程序设计》讲.doc