【问题标题】:Generic vertex attribute buffer doesn't seem to work without glVertexPointer没有 glVertexPointer,通用顶点属性缓冲区似乎不起作用
【发布时间】:2014-07-10 20:53:34
【问题描述】:

我正在绘制一个交错缓冲区——它是一个通用的顶点属性缓冲区。布局由三个作为顶点坐标的浮点数和另外两个浮点数属性组成,因此交错:

| float    | float    | float    | float   | float   |
| coords.x | coords.y | coords.z | attrib1 | attrib2 |
|_______vertex coordinates_______|_________|_________|

我希望能够仅使用 glVertexAttribPointer 来绘制此图,而且这似乎确实有效 - 但是,只有在我也使用 glEnableClientState(GL_VERTEX_ARRAY)glVertexPointer() 时才有效,甚至虽然我没有在着色器中访问gl_Vertex

最小的顶点着色器(GLSL 1.20):

#version 120

attribute vec3 coords;
attribute float attrib1;
attribute float attrib2;

void main() {
  gl_Position = gl_ModelViewProjectionMatrix * vec4(coords.x, coords.y, coords.z, 1.0);
  // attrib1 and 2 are used here but this is not relevant
}

绘制缓冲区的代码:

// set up states
glUseProgram(shader);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLuint shader_att0 = glGetAttribLocation(shader, "coords");
GLuint shader_att1 = glGetAttribLocation(shader, "attrib1");
GLuint shader_att2 = glGetAttribLocation(shader, "attrib2");
glEnableVertexAttribArray(shader_att0);
glEnableVertexAttribArray(shader_att1);
glEnableVertexAttribArray(shader_att2);
// *** These two lines below should not be necessary: ***
//glEnableClientState(GL_VERTEX_ARRAY);
//glVertexPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), reinterpret_cast<void*>(0));
// *** ...but without them, nothing is drawn! ***
glVertexAttribPointer(shader_att0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), reinterpret_cast<void*>(0));                    // 0: vertex coords
glVertexAttribPointer(shader_att1, 1, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), reinterpret_cast<void*>(3 * sizeof(GLfloat))); // 1: attrib1
glVertexAttribPointer(shader_att2, 1, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), reinterpret_cast<void*>(4 * sizeof(GLfloat))); // 2: attrib2

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

// do the drawing
glDrawElements(GL_TRIANGLES, numverts, GL_UNSIGNED_INT, 0);

// revert all the states again
glUseProgram(0);
glDisableVertexAttribArray(shader_att0);
glDisableVertexAttribArray(shader_att1);
glDisableVertexAttribArray(shader_att2);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

在上面的代码中一切正常如果我取消注释两个带注释的行;否则,不绘制任何内容。

这真的让我很难过......我是否错过了某处的一些状态更改,或者我忘记启用某些东西?

编辑:我没有使用 VAO,除了您在此处看到的之外,没有设置其他状态。没有绑定纹理或其他缓冲区。

【问题讨论】:

  • 没有什么明显的跳出。您尝试glGetError() 以确保没有错误状态?并且您确定着色器已正确编译和链接?从glGetAttribLocation() 调用中获得的值看起来很正常?您正在使用 glDisableVertexAttribArray() 的文字值而不是您检索到的位置,但在这种情况下不会造成任何伤害。
  • @RetoKoradi:属性的索引值分别为 1、2 和 3;我已经尝试为它们分配不同的值并且效果很好,尽管尝试将索引 0 绑定到任何属性会阻止着色器链接。 glGetError() 返回 0。文字是粘贴代码时的拼写错误,我现在已对其进行了编辑。
  • @Riot: "glLinkProgram 如果程序对象中使用的顶点着色器包含对绑定到通用属性的属性变量的分配(在预处理期间未删除),则也会失败 zero 和常规顶点位置 (gl_Vertex)。” 尽管我讨厌这样说,但我认为如果 常规 顶点位置数组未启用是一个驱动程序错误,当时 (GL 2.1) 使用常规顶点位置 not 并不常见.
  • @Riot:我实际上没有看到 Andon M. Coleman 引用的规范声明与您的情况有何相关 - 您没有为 gl_Vertex 或顶点着色器中的任何输入属性分配任何内容.我还有专门使用通用顶点属性的代码(并明确地将我的位置属性绑定到位置 0),并且它在 Windows 上的旧 2.x 可支持 ATI(Radeon X1600,iirc)上运行良好。能否展示完整的着色器源代码?
  • @Riot:我希望这不仅仅是第一个 Pastbin 站点中的复制和粘贴错误。如果这确实是您使用的代码,那么一切都可以解释,我添加了一个答案。

标签: c++ opengl glsl vertex-shader vertex-array


【解决方案1】:

来自您在 cmets 中的链接着色器代码:

#version 120
#pragma optimize(on)
#pragma debug(on)

attribute vec4 coords;    // we only input a vec3, so w defaults to 1.0
attribute float lambertian_main;
attribute float lambertian_side;

varying float height;
varying float lambertian_main_frag;
varying float lambertian_side_frag;

void main() {
  gl_Position = gl_ModelViewProjectionMatrix * coords;
  lambertian_main_frag = lambertian_main;
  lambertian_side_frag = lambertian_side;
  height = gl_Vertex.y;
}

正在在这里使用gl_Vertex...如果使用它,它将始终获得属性 ID 0。这完全解释了您在问题和问题中看到和描述的行为厘米。只需使用height = coords.y,一切都会如您所愿。

【讨论】:

  • 天哪;我怎么会错过……我知道我忽略了这将是非常明显的事情。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-03
  • 2019-07-17
  • 2011-06-08
  • 2010-10-08
相关资源
最近更新 更多