2013-03-08 127 views
2

我从this question了解到,只要程序链接,着色器对象就可以被分离和删除。何时删除缓冲区对象?

缓冲区对象的行为与VAO相似吗?我可以在VAO初始化后(在下面的Scene::Scene()结束时)删除它们吗?还是应该保留我的代码原样,每次我想要使用它们时都绑定它们?

Scene.h:

class Scene 
{ 
public: 
    void render(); 
    Scene(); 
    ~Scene(); 
private: 
    GLuint vertexArray; 
    GLuint vertexBuffer; 
    GLuint indexBuffer; 
    GLuint program; 
}; 

Scene.cpp:

#include <GL/glew.h> 
#include <stdio.h> 

#include "Scene.h" 

namespace 
{ 
    void printProgramInfoLog(GLuint program); 
    void printShaderInfoLog(GLuint shader); 
} 

void Scene::render() 
{ 
    glBindVertexArray(vertexArray); 
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 
    glUseProgram(program); 

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); 

    glUseProgram(0); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 
} 

Scene::Scene() 
{ 
    const float vertices[] = 
    { 
     -1.0f, -1.0f, 0.0f, 
     1.0f, -1.0f, 0.0f, 
     1.0f, 1.0f, 0.0f, 
     -1.0f, 1.0f, 0.0f, 
    }; 

    const unsigned short indices[] = 
    { 
     0, 
     1, 
     2, 
     0, 
     2, 
     3, 
    }; 

    const char* vertexShaderSource[] = 
    { 
     "#version 330\n", 
     "\n", 
     "in vec3 position;\n", 
     "\n", 
     "out vec2 fspos;", 
     "\n", 
     "void main()\n", 
     "{\n", 
     " gl_Position = vec4(position, 1.0);\n", 
      "fspos = vec2(position.x, position.y);\n", 
     "}\n", 
    }; 

    const char* fragmentShaderSource[] = 
    { 
     "#version 330\n", 
     "\n", 
     "precision highp float;\n", 
     "\n", 
     "in vec2 fspos;", 
     "\n", 
     "out vec4 color;\n", 
     "\n", 
     "void main()\n", 
     "{\n", 
     " color = vec4(abs(fspos.x), abs(fspos.y), 0.0, 1.0);\n", 
     "}\n", 
    }; 

    //------------------------------- 
    // Create and bind vertex array. 
    //------------------------------- 
    glGenVertexArrays(1, &vertexArray); 
    glBindVertexArray(vertexArray); 

    //-------------------------------------- 
    // Create, bind and fill vertex buffer. 
    //-------------------------------------- 
    glGenBuffers(1, &vertexBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 

    //------------------------------------- 
    // Create, bind and fill index buffer. 
    //------------------------------------- 
    glGenBuffers(1, &indexBuffer); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 

    //----------------- 
    // Create program. 
    //----------------- 
    program = glCreateProgram(); 

    //---------------------------------- 
    // Create and attach vertex shader. 
    //---------------------------------- 
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, sizeof(vertexShaderSource)/sizeof(vertexShaderSource[0]), vertexShaderSource, 0); 
    glCompileShader(vertexShader); 
    printShaderInfoLog(vertexShader); 
    glAttachShader(program, vertexShader); 

    //------------------------------------ 
    // Create and attach fragment shader. 
    //------------------------------------ 
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShader, sizeof(fragmentShaderSource)/sizeof(fragmentShaderSource[0]), fragmentShaderSource, 0); 
    glCompileShader(fragmentShader); 
    printShaderInfoLog(fragmentShader); 
    glAttachShader(program, fragmentShader); 

    //--------------- 
    // Link program. 
    //--------------- 
    glLinkProgram(program); 
    printProgramInfoLog(program); 

    //----------------------- 
    // Set up shader inputs. 
    //----------------------- 
    GLint position = glGetAttribLocation(program, "position"); 
    glEnableVertexAttribArray(position); 
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, 0); 

    //------------------------------------ 
    // Detach and delete fragment shader. 
    //------------------------------------ 
    glDetachShader(program, fragmentShader); 
    glDeleteShader(fragmentShader); 

    //---------------------------------- 
    // Detach and delete vertex shader. 
    //---------------------------------- 
    glDetachShader(program, vertexShader); 
    glDeleteShader(vertexShader); 

    //---------------------- 
    // Unbind vertex array. 
    //---------------------- 
    glBindVertexArray(0); 

    //!!!!!!!!!!!!!!!!!!! 
    // Unbinding and deleting the buffers here and only binding the VAO in 
    // render() works just fine, but is it okay to do this or should I leave 
    // it as is? 
    //!!!!!!!!!!!!!!!!!!! 
} 

Scene::~Scene() 
{ 
    glDeleteProgram(program); 
    glDeleteBuffers(1, &indexBuffer); 
    glDeleteBuffers(1, &vertexBuffer); 
    glDeleteVertexArrays(1, &vertexArray); 
} 

namespace 
{ 
    void printProgramInfoLog(GLuint program) 
    { 
     int logLength; 
     glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); 
     if (logLength > 0) 
     { 
      char* log = new char[logLength]; 
      glGetProgramInfoLog(program, logLength, 0, log); 
      fprintf(stderr, "%s", log); 
      delete[] log; 
     } 
    } 

    void printShaderInfoLog(GLuint shader) 
    { 
     int logLength; 
     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); 
     if (logLength > 0) 
     { 
      char* log = new char[logLength]; 
      glGetShaderInfoLog(shader, logLength, 0, log); 
      fprintf(stderr, "%s", log); 
      delete[] log; 
     } 
    } 
} 

回答

3

VAOs不数据。它们存储缓冲区对象绑定和顶点格式。缓冲对象仍然是数据存储的持有者。

所以不,不这样做。

+0

因此,我不能在那里删除它们,但我不必绑定/解除绑定每一帧(因为VAO持有绑定)? – lsJfGHkAq1y86nX0 2013-03-08 00:42:43

+0

正确。这就是VAOs首先的基本原理,用一个替代潜在的大量绑定调用。 – radical7 2013-03-08 00:57:41