OpenGL中glVertexAttribPointer的stride参数含义及用法疑问
关于glVertexAttribPointer中stride参数的困惑
我刚学OpenGL,想搞懂每一行代码的作用,但卡在了glVertexAttribPointer的stride参数上。文档说:
指定连续通用顶点属性之间的字节偏移量。如果stride为0,则认为通用顶点属性在数组中紧密排列。初始值为0。
我能理解stride为0的场景:比如顶点数组只有紧密排列的位置属性时:
GLfloat vertices[] = { //x, y, z 0.0f, 0.5f, 0.0f, // 顶部中点 -0.5f, -0.5f, 0.0f, // 左下角 0.5f, -0.5f, 0.0f // 右下角 };
这时设置stride为0没问题:
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
但给顶点数组加上颜色属性后:
GLfloat vertices[] = { //x, y, z, r, g, b 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 顶部中点 -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下角 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f // 右下角 };
这时必须把stride设为每个顶点的总字节数(也就是6*sizeof(GLfloat))才能正常运行,我搞不懂为什么。如果按自己的逻辑把stride设为3*sizeof(GLfloat)(以为是两个位置属性之间的间隔),就会出问题。
核心误区:stride是"下一个顶点同属性的起始偏移",不是"同属性元素的间隔"
你之前的错误在于误解了stride的定义——它不是指同一个属性的两个值之间的间隔,而是指从当前顶点的这个属性的第一个字节,到下一个顶点的同一个属性的第一个字节,中间隔了多少字节。
拿带颜色的顶点数组举例:
- 第一个顶点的位置属性从索引0开始,占3个float(12字节);
- 接下来是它的颜色属性,占3个float(12字节);
- 第二个顶点的位置属性,是从第一个顶点位置的起始字节往后数
6*sizeof(GLfloat)(24字节)的位置开始的——因为每个顶点总共占6个float的空间。
如果把stride设为3*sizeof(GLfloat)(12字节),OpenGL会认为:
- 第一个位置在0字节,第二个位置就在0+12字节的位置(也就是第一个顶点的r值),第三个位置在12+12=24字节的位置(第二个顶点的r值),这完全不是你要的位置数据,自然会出问题。
换个更直白的说法:
当你调用glVertexAttribPointer时,你是在告诉OpenGL:
- 这个属性每一组数据占
3个GL_FLOAT; - 从buffer的某个偏移量(最后一个参数)开始取第一组数据;
- 要取下一组数据时,直接往前跳
stride个字节就行。
- 单属性紧密排列时,下一组位置数据就在当前组的结尾,所以stride设为0(OpenGL会自动计算成
3*sizeof(GLfloat)); - 多属性交叉排列时,下一组位置数据要跳过当前顶点的所有其他属性(这里就是颜色的3个float),所以总跨度是整个顶点的大小:
3+3个float的字节数,也就是6*sizeof(GLfloat)。
内容的提问来源于stack exchange,提问作者octopus
相关产品推荐
相关产品推荐

