2015-05-05 11 views
8

Non riesco a utilizzare gli oggetti del buffer vertice senza utilizzando un oggetto matrice vertice.Come utilizzare VBO senza VAO con profilo core OpenGL?

La mia comprensione era che i VAO incapsulavano lo stato attorno ai VBO. Ma i VBO non dovrebbero essere utilizzabili senza un VAO?

Ecco un mini-esempio. Con use_vao=true funziona correttamente (esegue il rendering in arancione). Con use_vao=false questo non restituisce nulla e genera un errore GL_INVALID_OPERATION su glDrawElements.

// 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(); 
} 

Sulla mia macchina glGetString(GL_VERSION) produce 4.1 INTEL-10.6.20.

risposta

13

Uso Vaos è richiesta nel profilo principale. Dalla specifica OpenGL 3.3, pagina 342, nella sezione E.2.2 "Funzionalità rimosse":

Anche l'oggetto matrice di vertici predefinito (il nome zero) è deprecato.

Ciò significa che non è possibile impostare gli attributi di vertice senza creare e associare il proprio VAO.

9

No con un profilo nucleo 3.3+ è necessario un VAO da rendere.

È tuttavia possibile semplicemente creare e associare un VAO e dimenticarlo (tenerlo vincolato).

Inoltre, è necessario chiamare anche glEnableVertexAttribArray(0); anche quando si utilizza il profilo di compatibilità e non si utilizza un VAO.

Un altro paio di osservazioni è che si rigenera tutti i buffer e VAO su ogni fotogramma ma non si pulisce. Si dovrebbe fare che una volta durante l'inizializzazione e quindi riassociare nell'elaborazione:

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); 
} 
+1

Grazie. Hai un riferimento che afferma che VAO è obbligatorio? Sono curioso di sapere dove è stato scritto, dal momento che non l'ho trovato da solo. –