Here's a snippet of my code. I have a Button structure made up by 2 Figure structures, which contains vertices, colors and the relative VBOs and VAO.
I have a function to allocate the memory and one to free it, but I'm not sure if it's missing something.
#include "GL/glew.h"
#include "GL/freeglut.h"
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtx/transform.hpp"
#include "glm/gtc/type_ptr.hpp"
// Structures
typedef struct {
std::vector<glm::vec2> vertices;
std::vector<glm::vec4> colors;
GLuint VAO, VBO_V, VBO_C;
int drawMode;
} Figure;
typedef struct {
glm::vec2 pos;
glm::vec2 size;
glm::vec4 color;
glm::vec4 colorHover;
Figure bg;
Figure border;
void (*onClick)(void);
} Button;
// Creation
Button* createButton(float posx, float posy, float width, float height,
glm::vec4 color, glm::vec4 colorHover, glm::vec4 colorBorder, void (*onClick)(void))
{
Button* button = new Button;
button->pos.x = posx;
button->pos.y = posy;
button->size.x = width;
button->size.y = height;
button->color = color;
button->colorHover = colorHover;
button->onClick = onClick;
// Background Figure
button->bg.drawMode = GL_TRIANGLES;
button->bg.vertices.push_back({ -1.0f, 1.0f });
button->bg.vertices.push_back({ -1.0f, -1.0f });
button->bg.vertices.push_back({ 1.0f, 1.0f });
button->bg.vertices.push_back({ 1.0f, 1.0f });
button->bg.vertices.push_back({ 1.0f, -1.0f });
button->bg.vertices.push_back({ -1.0f, -1.0f });
for (int i = 0; i < button->bg.vertices.size(); i++)
{
button->bg.colors.push_back(button->color);
}
// Generate VAO
glGenVertexArrays(1, &button->bg.VAO);
glBindVertexArray(button->bg.VAO);
// VBO for vertices
glGenBuffers(1, &button->bg.VBO_V);
glBindBuffer(GL_ARRAY_BUFFER, button->bg.VBO_V);
glBufferData(GL_ARRAY_BUFFER, button->bg.vertices.size() * sizeof(glm::vec2), button->bg.vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
// VBO for colors
glGenBuffers(1, &button->bg.VBO_C);
glBindBuffer(GL_ARRAY_BUFFER, button->bg.VBO_C);
// Check: cambiare a GL_DYNAMIC_DRAW?
glBufferData(GL_ARRAY_BUFFER, button->bg.colors.size() * sizeof(glm::vec4), button->bg.colors.data(), GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
// Border Figure
button->border.drawMode = GL_LINE_LOOP;
button->border.vertices.push_back({ -1.0f, 1.0f });
button->border.vertices.push_back({ -1.0f, -1.0f });
button->border.vertices.push_back({ 1.0f, -1.0f });
button->border.vertices.push_back({ 1.0f, 1.0f });
for (int i = 0; i < button->border.vertices.size(); i++)
{
button->border.colors.push_back({ 1.0f, 1.0f, 1.0f, 1.0f });
}
glGenVertexArrays(1, &button->border.VAO);
glBindVertexArray(button->border.VAO);
glGenBuffers(1, &button->border.VBO_V);
glBindBuffer(GL_ARRAY_BUFFER, button->border.VBO_V);
glBufferData(GL_ARRAY_BUFFER, button->border.vertices.size() * sizeof(glm::vec2), button->border.vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glGenBuffers(1, &button->border.VBO_C);
glBindBuffer(GL_ARRAY_BUFFER, button->border.VBO_C);
glBufferData(GL_ARRAY_BUFFER, button->border.colors.size() * sizeof(glm::vec4), button->border.colors.data(), GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
return button;
}
void destroyButton(Button* button)
{
glDeleteBuffers(1, &button->bg.VBO_V);
glDeleteBuffers(1, &button->bg.VBO_C);
glBindVertexArray(0); // Unbind any currently bound VAO
glDeleteVertexArrays(1, &button->bg.VAO);
button->bg.vertices.clear();
button->bg.colors.clear();
glDeleteBuffers(1, &button->border.VBO_V);
glDeleteBuffers(1, &button->border.VBO_C);
glBindVertexArray(0); // Unbind any currently bound VAO
glDeleteVertexArrays(1, &button->border.VAO);
button->border.vertices.clear();
button->border.colors.clear();
delete button;
}
int main(int argc, char** argv)
{
// glut/OpenGL init code
// [...]
Button* myButton = createButton(100.0f, 100.0f, 150.0f, 40.0f,
{ 0.0f, 0.0f, 0.7f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f }, nullptr);
destroyButton(myButton);
return 0;
}
Is that the correct approach to free the allocated resources, or am I missing something? Is it ok to delete VAO after the VBOs?
Note
These snippets are part of a quite big project...
If somebody needs a MRE, please add a comment: I can add the initialization code and whatever is needed as soon as I get to use my device and test the code
GL_STATIC_DRAW(indicating you will not be changing them) are copies of the RAM vectors you fill them from usingglBufferDataThe associated vectors inFigure.vertices.colorsshould only have a life inside thecreateButtonmethod. They are just unused copies of the GL buffers. \$\endgroup\$createButton()function, and therefore not save their value in theFigurestructure at all, right? \$\endgroup\$std::unique_ptr<Button, ButtonDeleter>. If for some reason you’re not allowed to just add a destructor to the class. \$\endgroup\$