OpenGL 4.6 COMPAT模式C++多顶点缓冲区仅绘制第二个问题
问题原因分析
- 你对OpenGL顶点属性指针的工作逻辑存在误解:
glVertexAttribPointer调用时,会将当前绑定的GL_ARRAY_BUFFER对象与对应顶点属性槽位(这里是槽位0)做关联,这个关联关系会保存在当前绑定的顶点数组对象(VAO)中,而不是动态读取你后续绑定的GL_ARRAY_BUFFER。 - 你的代码里两次调用
glVertexAttribPointer配置同一个槽位0,第二次配置直接覆盖了第一次的VBO关联,所以不管你绘制前绑定哪个VBO,顶点属性始终从第二个VBO读取,自然只能渲染出第二个的内容。 - 额外说明:你使用
glDrawElements的时候没有绑定索引缓冲对象(IBO/EBO),直接传入客户端内存的indices指针,在核心模式下这是非法的,不过COMPAT模式兼容这种用法,但长期来看不推荐。
解决方法
以下两种方案均可解决问题,推荐优先使用方案2:
方案1:绘制前重新配置顶点属性指针
绘制时不要仅绑定VBO,还要同步更新顶点属性指针的关联关系:
// 绘制第一个VBO glBindBuffer(GL_ARRAY_BUFFER, id); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (const void*)8); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices); // 绘制第二个VBO glBindBuffer(GL_ARRAY_BUFFER, ida); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (const void*)8); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
该方案改动量小,适合简单测试场景,但频繁修改顶点属性指针会影响渲染性能。
方案2:使用VAO分别保存两个VBO的配置(推荐)
OpenGL设计中VAO的作用就是保存顶点属性的配置状态,为每个VBO创建独立的VAO,绘制时直接绑定对应VAO即可,性能更高也符合规范:
// 初始化阶段新增VAO配置 unsigned int vao1, vao2; // 第一个VAO关联第一个VBO的配置 glGenVertexArrays(1, &vao1); glBindVertexArray(vao1); glBindBuffer(GL_ARRAY_BUFFER, id); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (const void*)8); // 第二个VAO关联第二个VBO的配置 glGenVertexArrays(1, &vao2); glBindVertexArray(vao2); glBindBuffer(GL_ARRAY_BUFFER, ida); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (const void*)8); // 解绑避免后续操作误改配置 glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); // 绘制阶段直接绑定对应VAO即可 glBindVertexArray(vao1); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices); glBindVertexArray(vao2); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
内容的提问来源于stack exchange,提问作者Aes123
相关产品推荐
相关产品推荐

