何时删除缓冲区对象?

Posted

技术标签:

【中文标题】何时删除缓冲区对象?【英文标题】:When to delete buffer object? 【发布时间】:2013-03-08 00:25:35 【问题描述】:

我从this question 了解到,一旦程序链接,着色器对象就可以被分离和删除。

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

场景.h:

class Scene

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

场景.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;
        
    

【问题讨论】:

【参考方案1】:

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

所以不,不要那样做。

【讨论】:

所以,我不能在那里删除它们,但我不必绑定/取消绑定每一帧(因为 VAO 持有绑定)? 正确。这首先是 VAO 背后的基本原理,用一个来替换潜在的大量绑定调用。

以上是关于何时删除缓冲区对象?的主要内容,如果未能解决你的问题,请参考以下文章

顶点缓冲区对象(删除进程)opengl

何时更新 ALSA 音频驱动程序缓冲区指针

绑定到“顶点数组对象”后,我应该删除“顶点缓冲区对象”吗?

如果我在程序退出时未能删除顶点缓冲区对象会发生啥?

在重叠模式下使用 WSASend 时,我应该何时释放缓冲区?

确定何时播放缓冲区而不在 OpenAL 中轮询源