使用VBO对glVertexAttribPointer的影响

在openGL中glVertexAttribPointer是用来上传顶点数据到显卡的方法。这里的顶点数据是数组的形式。函数原型如下

void glVertexAttribPointer(GLuint index, 
                           GLint size,
                           GLenum type,
                           GLboolean normalized,
                           GLsizei stride,
                           const void *ptr)
 
// index: 着色器脚本对应变量ID
// size : 此类型数据的个数
// type : 此类型的sizeof值
// normalized : 是否对非float类型数据转化到float时候进行归一化处理
// stride : 此类型数据在数组中的重复间隔宽度,byte类型计数
// ptr    : 数据指针, 这个值受到VBO的影响

在不使用VBO的情况下:事情是这样的,ptr就是一个指针,指向的是需要上传到顶点数据指针。通常是数组名的偏移量。

在使用VBO的情况下:首先要glBindBuffer,以后ptr指向的就不是具体的数据了。因为数据已经缓存在缓冲区了。这里的ptr指向的是缓冲区数据的偏移量。这里的偏移量是整型,但是需要强制转换为const GLvoid *类型传入。注意的是,这里的偏移的意思是数据个数总宽度数值。

比如说:这里存放的数据前面有3个float类型数据,那么这里的偏移就是,3*sizeof(float).

最后解释一下,glVertexAttribPointer的工作原理:

  • 首先,通过index得到着色器对应的变量openGL会把数据复制给着色器的变量。
  • 以后,通过size和type知道当前数据什么类型,有几个。openGL会映射到float,vec2, vec3 等等。
  • 由于每次上传的顶点数据不止一个,可能是一次4,5,6顶点数据。那么通过stride就是在数组中间隔多少byte字节拿到下个顶点此类型数据。
  • 最后,通过ptr的指针在迭代中获得所有数据。

那么,最最后openGL如何知道ptr指向的数组有多长,读取几次呢。是的,openGL不知道。所以在调用绘制的时候,需要传入一个count数值,就是告诉openGL绘制的时候迭代几次glVertexAttribPointer调用。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,glVertexAttribPointer函数是用来设置顶点属性指针的,它的原型如下: ``` void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); ``` 参数的含义如下: - `index`:指定要设置的顶点属性的索引。这个索引对应着顶点着色器中的attribute变量的位置,它是一个非负整数。 - `size`:指定每个顶点属性的分量数。它的值可以是1、2、3或4,表示顶点属性是一个标量、向量、矩阵等。 - `type`:指定顶点属性的数据类型。它的值可以是GL_BYTE、GL_UNSIGNED_BYTE、GL_SHORT、GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT、GL_HALF_FLOAT、GL_FLOAT、GL_DOUBLE、GL_FIXED等。 - `normalized`:指定顶点属性是否需要被标准化。它的值可以是GL_TRUE或GL_FALSE。如果设置为GL_TRUE,则OpenGL会将所有的顶点属性都标准化到[-1, 1]或[0, 1]的范围内;如果设置为GL_FALSE,则不进行标准化处理。 - `stride`:指定连续的顶点属性之间的字节跨度。这个参数的值通常是sizeof(Vertex)或sizeof(GLfloat)*3,表示相邻顶点之间的属性在顶点缓冲区中的偏移量。 - `pointer`:指定顶点缓冲区中顶点属性的起始位置。这个参数的值通常是0或者(void*)offsetof(Vertex, position),表示顶点属性在顶点缓冲区中的偏移量。 下面是一个使用glVertexAttribPointer函数设置顶点属性指针的例子: ``` struct Vertex { vec3 position; vec3 normal; vec2 texcoord; }; Vertex vertices[] = { {vec3(-1.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f), vec2(0.0f, 0.0f)}, {vec3(1.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f), vec2(1.0f, 0.0f)}, {vec3(1.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f), vec2(1.0f, 1.0f)}, {vec3(-1.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f), vec2(0.0f, 1.0f)} }; GLuint vbo, vao; // 创建顶点缓冲对象 glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 创建顶点数组对象 glGenVertexArrays(1, &vao); glBindVertexArray(vao); // 设置顶点属性指针 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position)); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texcoord)); glEnableVertexAttribArray(2); ``` 在这个例子中,我们先创建了一个包含顶点位置、法向量和纹理坐标的结构体Vertex,并把顶点数据存储在一个顶点数组vertices中。然后我们创建了一个顶点缓冲对象vbo,并把顶点数据传递给OpenGL。 接着,我们创建了一个顶点数组对象vao,并绑定它。在这个顶点数组对象中,我们使用glVertexAttribPointer函数来设置三个顶点属性指针。第一个参数表示顶点属性的索引,这里分别是0、1、2。第二个参数表示顶点属性的分量数,分别是3、3、2。第三个参数表示顶点属性的数据类型,这里都是GL_FLOAT。第四个参数表示顶点属性是否需要被标准化,这里都是GL_FALSE。第五个参数表示连续的顶点属性之间的字节跨度,这里都是sizeof(Vertex)。最后一个参数表示顶点缓冲区中顶点属性的起始位置,这里使用了offsetof宏来计算偏移量,以确保每个顶点属性在顶点缓冲区中的位置都是正确的。在设置完顶点属性指针后,我们需要通过glEnableVertexAttribArray函数来启用这些顶点属性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值