6.顶点属性、顶点数组、缓冲区对象

本文深入探讨OpenGL中的顶点属性概念,包括属性的指定、顶点数组与缓冲区对象的使用,以及如何通过顶点着色器处理属性。同时,详细介绍了顶点缓冲区对象(VBO)和顶点数组对象(VAO)的创建、绑定和配置过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

顶点属性:

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值