2

我从这个问题中了解到,一旦程序链接,着色器对象就可以被分离和删除。

缓冲区对象的行为是否与 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;
        }
    }
}
4

1 回答 1

3

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

所以不,不要那样做。

于 2013-03-08T00:40:16.060 回答