顶点属性:
1.3.0至少支持16个顶点属性,使用 GLint maxVertexAttribs查询只是的最大数量;
2.指定每个顶点的数据,如坐标;使用 void glVertexAttrib* *代表1f,2f,3f,4f---1fv,2fv,3fv,4fv;
//指定每个值
void glVertexAttrib4f(Gluint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
//通过指针取值
void glVertexAttrib4fv(Gluint index, const GLfloat *values);
顶点数组:作为顶点缓冲区对象的基础,灵活、高效
使用 void glVertexAttribPointer()/*2.0 api*/、void glVertexAttribIpointer()/*3.0 api*/ 指定
该方法的主要参数如下:
Gluinit index:顶点属性所引值,取值范围 0~maxVertexAttribs()
GLint size:顶点属性指定的分量数量:1~4:xyzw
GLenum type:数据格式枚举值,两函数包含的枚举值
- GL_BYTE、
- GL_UNSIGNED_BYTE、
- GL_SHORT、
- GL_UNSIGNED_SHORT、
- GL_INT、
- GL_UNSINGED_INT;
- glVertexAttribPointer还有GL_HALF_FLOAT、GL_FLOAT、GL_FIXED、GL_INT_2_10_10_10_REV、GL_UNSIGNED_2_10_10_10_REV
Glboolean normalized:2.0 用于表示非浮点数据格式类型转换为浮点值时是否应该规范化。3.0这些值都是作为整数对待
GLsizei stride:读取属性跨距,类似指针步长
const void *ptr:如为顶点数组:代表缓冲区指针。如为缓冲区对象,则表示该缓冲区内的偏移量
结构数组与数组结构
理解“结构”表示顶点的所有属性,每个顶点有一个属性的数组。通俗讲就是一个顶点的各种数据,xyz纹理坐标、法线这些数据代表一个结构。
结构数组:在一个缓冲区中存储顶点属性,所有顶点的属性是在一个数组中的。
数组结构:在单独的缓冲区中保存每个顶点属性
:推荐使用顶点缓冲区对象,更高效,避免使用顶点数组,3.0支持此api是为了与2.0兼容。
启用或禁用顶点数组
启用之后才可以为顶点设置属性。禁用之后则无法再进行设置。
void glEnableVertexAttribArray(GLuint index);
void glDisableVertexAttribArray(GLuint index);
声明顶点属性变量
- 顶点属性变量由in限定符指定,内建变量为gl_position
- in限定符只能修复基本数据类型,float,int,vec,mat等,不能修饰数组或者结构
- 顶点着色器中声明为顶点属性的变量是制度变量,不能修改
- 属性再顶点着色器内部声明,但是没有使用,则认定为非活动属性,不纳入计数。
- 属性数量大于GL_MAX_VERTEX_ATTRIBS后,顶点着色器无法链接
- 链接成功后,使用glGetProgramiv(program,GL_ACTIVE_ATTRIBUTES, &numberActiveAttribs);
绑定顶点属性到顶点着色其中的属性变量
- layout(position = N)指定
- glBindAttribLocation(GLint program, GLint index, const GLchar *name);下次程序链接时生效,不影响当前次;不存在的属性将被忽略
- glGetAttribLocation(GLint program,const GLchar *name);如果指定了绑定,则使用指定的,如果没有指定,则分配通用顶点属性索引。return 分配的索引,错误返回-1
顶点缓冲区对象:VBO(Vertex Buffer Object)
顶点数据指定的顶点数据保存在内存中,在glDrawArrays或者glDrawElements时,会从内存向显存拷贝,如果每次绘图都进行拷贝,则渲染性能较低,所以出来了顶点缓冲区对象。
支持两种缓冲区对象:
- 数组缓冲区对象:顶点数据--> GL_ARRAY_BUFFER
- 元素数组缓冲区对象:图源数据 --> GL_ELEMENT_ARRAY_BUFFER
//代码比较乱,只是展示了调用顺序及逻辑,参数不太准确
//GL_ELEMENT_ARRAY_BUFFER
//GL_ARRAY_BUFFER
#define POS_ATTRIB 0
GLuint mVB[VB_COUNT];
struct Vertex {
GLfloat pos[2];
GLubyte rgba[4];
} QUAD;
QUAD quad;
//-----------以上为准备数据-----------------------
//-----------以上为相关api-----------------------
glGenBuffers(count, mVB); // 返回的都是0以外的无符号整数,0是预留值,不表示缓冲区对象。如果查询、修改对象0的缓冲区对象则产生错误。
glBindBuffer(GL_ARRAY_BUFFER, mVB[0]);
//GL_STATIC_DRAW:缓冲区对象将被修改一次,使用多次
//GL_STATIC_READ
//GL_STATIC_COPY
//GL_DYNAMIC_DRAW:缓冲区对象将被重复修改,使用多次
//GL_DYNAMIC_READ
//GL_DYNAMIC_COPY
//GL_STREAM_DRAW:缓冲区对象将被修改一次,使用少数几次
//GL_STREAM_READ
//GL_STREAM_COPY
//以上模式只是一个提示,而不是保证,所以,可以分配一个缓冲区对象数据,设置为GL_STATIC_DRAW,并且修改多次。
//GL_ARRAY_BUFFER
//GL_ELEMENT_ARRAY_BUFFER
//GL_COPY_READ_BUFFER
//GL_COPY_WRITE_BUFFER
//GL_PIXEL_PACK_BUFFER
//GL_PIXEL_UNPACK_BUFFER
//GL_TRANSFORM_FEEDBACK_BUFFER
//GL_UNIFORM_BUFFER
glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD), &QUAD, GL_STATIC_DRAW);
//glBufferSubData();更新数据
glEnableVertexAttribArray(POS_ATTRIB);
glVertexAttribPointer(POS_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)offsetof(Vertex, pos));
//绘制完重置
glDisableVertexAttribArray(POS_ATTRIB)
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//程序运行结束释放
glDeleteBuffers(VB_COUNT, mVB);
顶点数组对象:VAO(Vertex Array Object)
VBO需要频换切换glBindBuffer、glEnableVertexAttribArray、glVertexAttribPointer,3.0出来了VAO,包含在顶点数组/定点缓冲区对象配置之间切换所需要的所有状态的单一对象。
性能上来说更高效一点
glGenVertexArrays(GLsizei n, GLuint *arrays);
glBindVertexArray(GLuint array);
//glEnableVertexAttribArray
//glVertexAttribPointer
//操作完后重置
glBindVertexArray(0);
//程序结束后,删除
glDeleteVertexArrays(GLsizei n, GLuint *arrays);
映射缓冲区对象
glMapBufferRange:返回指向所有或者一部分缓冲区对象数据存储的指针。
glUnmapBuffer:用于指示更新已完成和释放映射的指针
刷新映射的缓冲区
glFlushMappedBufferRange()
复制缓冲区对象
glCopyBufferSubData()