【问题标题】:How to use VBOs without VAOs with OpenGL core profile?如何在没有 VAO 的情况下使用带有 OpenGL 核心配置文件的 VBO?
【发布时间】:2015-07-15 10:36:06
【问题描述】:

我在使用顶点缓冲区对象时遇到问题没有使用顶点数组对象。

我的理解是,VAO 只是将状态封装在 VBO 周围。但是 VBO 不应该在没有 VAO 的情况下使用吗?

这是一个小例子。使用use_vao=true 可以正常工作(呈现橙色矩形)。对于use_vao=false,这不会渲染任何内容并在glDrawElements 上生成GL_INVALID_OPERATION 错误。

// make sure the modern opengl headers are included before any others
#include <OpenGL/gl3.h>
#define __gl_h_
#include <GLUT/glut.h>
#include <string>
#include <cassert>

// For rendering a full-viewport quad, set tex-coord from position
std::string tex_v_shader = R"(
#version 330 core
in vec3 position;
void main()
{
  gl_Position = vec4(position,1.);
}
)";
// Render directly from color or depth texture
std::string tex_f_shader = R"(
#version 330 core
out vec4 color;
void main()
{
  color = vec4(0.8,0.4,0.0,0.75);
}
)";
// shader id, vertex array object
GLuint tex_p_id;
int w=1440,h=480;
const GLfloat V[] = {-0.5,-0.5,0,0.5,-0.5,0,0.5,0.5,0,-0.5,0.5,0};
const GLuint F[] ={0,1,2, 0,2,3};
int main(int argc, char * argv[])
{
  // Init glut and create window + OpenGL context
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_3_2_CORE_PROFILE|GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); 
  glutInitWindowSize(w,h);
  glutCreateWindow("test");
  // Compile shaders
  const auto & compile = [](const char * src,const GLenum type)->GLuint
  {
    GLuint s = glCreateShader(type);
    glShaderSource(s, 1, &src, NULL);
    glCompileShader(s);
    return s;
  };
  tex_p_id = glCreateProgram();
  glAttachShader(tex_p_id,compile(tex_v_shader.c_str(), GL_VERTEX_SHADER));
  glAttachShader(tex_p_id,compile(tex_f_shader.c_str(), GL_FRAGMENT_SHADER));
  glLinkProgram(tex_p_id);
  glutDisplayFunc(
    []()
    {
      glViewport(0,0,w,h);
      glUseProgram(tex_p_id);
      glClearColor(0.0,0.4,0.7,0.);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      const bool use_vao = true;
      GLuint VAO;
      if(use_vao)
      {
        glGenVertexArrays(1, &VAO);
        glBindVertexArray(VAO);
      }
      GLuint VBO, EBO;
      glGenBuffers(1, &VBO);
      glGenBuffers(1, &EBO);
      glBindBuffer(GL_ARRAY_BUFFER, VBO);
      glBufferData(GL_ARRAY_BUFFER, sizeof(V), V, GL_STATIC_DRAW);
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(F), F, GL_STATIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER, 0); 
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
      glBindBuffer(GL_ARRAY_BUFFER, VBO); 
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 
      if(use_vao)
      {
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0); 
      }
      assert(glGetError() == GL_NO_ERROR);
      glDrawElements(GL_TRIANGLES,sizeof(F)/sizeof(GLuint),GL_UNSIGNED_INT, 0);
      assert(glGetError() == GL_NO_ERROR);
      glutSwapBuffers();
    }
    );
  glutReshapeFunc( [](int w,int h){::h=h, ::w=w;});
  glutMainLoop();
}

在我的机器上glGetString(GL_VERSION) 产生4.1 INTEL-10.6.20

【问题讨论】:

    标签: c++ opengl opengl-3 opengl-4


    【解决方案1】:

    在核心配置文件中需要使用 VAO。来自 OpenGL 3.3 规范,第 342 页,在 E.2.2 “删除的功能”部分:

    默认的顶点数组对象(名称为零)也已弃用。

    这意味着如果不创建和绑定自己的 VAO,就无法设置顶点属性。

    【讨论】:

      【解决方案2】:

      没有核心 3.3+ 配置文件,您需要一个 VAO 来渲染。

      但是,您可以只创建和绑定一个 VAO,然后忘记它(保持绑定)。

      除了glEnableVertexAttribArray(0); 之外,即使在使用兼容性配置文件而不使用 VAO 时仍必须调用。

      还有一些注意事项是,您每帧都重新生成所有缓冲区和 VAO,但不清理它。您应该在初始化期间执行一次,然后在绘制时重新绑定:

      if(!use_vao){
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
      }
      else
      {
            glBindVertexArray(VAO);
      }
      

      【讨论】:

      • 谢谢。您是否有说明 VAO 是强制性的参考资料?我很好奇这是在哪里写的,因为我自己没有找到。
      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 2012-06-30
      • 2012-02-10
      • 1970-01-01
      • 2015-12-02
      相关资源
      最近更新 更多