From f4bae02e782ea3fa76712d50b7080dd2f8e2c8ab Mon Sep 17 00:00:00 2001 From: "re.kovalev" Date: Fri, 22 Jul 2022 14:30:05 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BB=D0=B0=D1=81=D1=81=D1=8B=20VAO/VBO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Buffers.h | 50 +++++++++++++++++++ src/Buffers.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 64 +++++++++++-------------- 3 files changed, 197 insertions(+), 36 deletions(-) create mode 100644 include/Buffers.h create mode 100644 src/Buffers.cpp diff --git a/include/Buffers.h b/include/Buffers.h new file mode 100644 index 0000000..999dba4 --- /dev/null +++ b/include/Buffers.h @@ -0,0 +1,50 @@ +#ifndef BUFFERS_H +#define BUFFERS_H + +#include + +#include + +// Объект массива вершин +class VAO +{ + public: + VAO(); // Создает VAO и активирует его + ~VAO(); // Уничтожает VAO + VAO(const VAO & copy); // Конструктор копирования + VAO& operator=(const VAO & other); // Оператор присваивания + + void use(); // Активация VAO + static void disable(); // Деактивация активного VAO + + private: + GLuint handler; // Дескриптор + static std::map handler_count; // Счетчик использований дескриптора +}; + +// Тип буфера +enum BUFFER_TYPE { VERTEX = GL_ARRAY_BUFFER + , ELEMENT = GL_ELEMENT_ARRAY_BUFFER + }; + +// Объект вершинного буфера +class BO +{ + public: + BO(BUFFER_TYPE type); // Создает пустой буфер заданного типа + BO(BUFFER_TYPE type, const void *data, int size); // Создает и загружает туда данные + ~BO(); // Уничтожает буфер + BO(const BO & copy); // Конструктор копирования + BO& operator=(const BO & other); // Оператор присваивания + + void load(const void *data, int size, GLuint mode = GL_STATIC_DRAW); // Загрузка данных в буфер + void use(); + + protected: + GLuint handler; // Дескриптор + BUFFER_TYPE type; // Тип буфера + private: + static std::map handler_count; // Счетчик использований дескриптора +}; + +#endif // BUFFERS_H \ No newline at end of file diff --git a/src/Buffers.cpp b/src/Buffers.cpp new file mode 100644 index 0000000..cb47cd2 --- /dev/null +++ b/src/Buffers.cpp @@ -0,0 +1,119 @@ +#include "Buffers.h" + +// Счетчики использований дескрипторов +std::map VAO::handler_count; +std::map BO::handler_count; + +// Создает VAO и активирует его +VAO::VAO() +{ + glGenVertexArrays(1, &handler); // Генерация одного объекта массива вершин + glBindVertexArray(handler); // Привязка для использования + handler_count[handler] = 1; // Инициализация счетчика для дескриптора +} + +// Уничтожает VAO +VAO::~VAO() +{ + // Если дескриптор никем не используется - освободим его + if (!--handler_count[handler]) + { + glDeleteVertexArrays(1, &handler); + handler_count.erase(handler); // Удаление из словаря + } +} + +// Конструктор копирования +VAO::VAO(const VAO & copy) : handler(copy.handler) +{ + handler_count[handler]++; +} + +// Оператор присваивания +VAO& VAO::operator=(const VAO & other) +{ + // Если это разные дескрипторы + if (handler != other.handler) + { // то следуюет удалить текущий перед заменой + this->~VAO(); + handler = other.handler; + handler_count[handler]++; + } + + return *this; +} + +// Активация VAO +void VAO::use() +{ + glBindVertexArray(handler); // Привязка VAO для использования +} + +// Деактивация активного VAO +void VAO::disable() +{ + glBindVertexArray(0); // Отключение VAO +} + +// Создает пустой буфер заданного типа +BO::BO(BUFFER_TYPE t) : type(t) +{ + glGenBuffers(1, &handler); // Генерация одного объекта буфера + handler_count[handler] = 1; + use(); // Привязка буфера +} + +// Создает и загружает туда данные +BO::BO(BUFFER_TYPE t, const void *data, int size) : BO(t) +{ + load(data, size); +} + +// Уничтожает буфер +BO::~BO() +{ + if (handler) // Если буфер был создан + { + // Если дескриптор никем не используется - освободим его + if (!--handler_count[handler]) + { + glDeleteBuffers(1, &handler); + handler_count.erase(handler); // Удаление из словаря + } + handler = 0; + } +} + +// Конструктор копирования +BO::BO(const BO & copy) : handler(copy.handler), type(copy.type) +{ + handler_count[handler]++; +} + +// Оператор присваивания +BO& BO::operator=(const BO & other) +{ + // Если это разные дескрипторы + if (handler != other.handler) + { // то следуюет удалить текущий перед заменой + this->~BO(); + handler = other.handler; + handler_count[handler]++; + } + // Изменим тип + type = other.type; + + return *this; +} + +// Загрузка вершин в буфер +void BO::load(const void *data, int size, GLuint mode) +{ + use(); // Привязка буфера + glBufferData(type, size, data, mode); +} + +void BO::use() +{ + glBindBuffer(type, handler); // Привязка элементного буфера +} diff --git a/src/main.cpp b/src/main.cpp index 556b814..98db93b 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,8 @@ #include +#include "Buffers.h" + #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define WINDOW_CAPTION "OPENGL notes on rekovalev.site" @@ -110,6 +112,21 @@ GLuint LoadShaders(const char *vertex_file, const char *fragment_file) return programID; } +// Функция для конфигурации атрибутов +void attrib_config() +{ + // Определим спецификацию атрибута + glVertexAttribPointer( 0 // индекс атрибута, должен совпадать с Layout шейдера + , 3 // количество компонент одного элемента + , GL_FLOAT // тип + , GL_FALSE // необходимость нормировать значения + , 0 // шаг + , (void *)0 // отступ с начала массива + ); + // Включаем необходимый атрибут у выбранного VAO + glEnableVertexAttribArray(0); +} + int main(void) { GLFWwindow* window; // Указатель на окно GLFW3 @@ -163,44 +180,26 @@ int main(void) }; // VAO - GLuint VertexArrayID; - glGenVertexArrays(1, &VertexArrayID); // Генерация одного объекта массива вершин - glBindVertexArray(VertexArrayID); // Привязка для использования - + VAO vao; // VBO вершинный - GLuint vertexbuffer; - glGenBuffers(1, &vertexbuffer); // Генерация одного объекта буфера вершин - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // Привязка буфера вершин к используемому VAO - + BO vbo_vert(VERTEX); + attrib_config(); // Конфигурация аттрибутов // Загрузка вершин в используемый буфер вершин - glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW); - - // Определим спецификацию атрибута - glVertexAttribPointer( 0 // индекс атрибута, должен совпадать с Layout шейдера - , 3 // количество компонент одного элемента - , GL_FLOAT // тип - , GL_FALSE // необходимость нормировать значения - , 0 // шаг - , (void *)0 // отступ с начала массива - ); - // Включаем необходимый атрибут у выбранного VAO - glEnableVertexAttribArray(0); + vbo_vert.load(verticies, sizeof(verticies)); // индексы вершин GLuint indices[] = {0, 1, 2, 2, 3, 0}; // VBO элементный (индексы вершин) - GLuint elementbuffer; - glGenBuffers(1, &elementbuffer); // Генерация одного объекта буфера вершин - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer); // Привязка элементного буфера + BO vbo_elem(ELEMENT); + + // Загрузка индексов в используемый элементный буфер + vbo_elem.load(indices, sizeof(indices)); - // Загрузка индексов в используемый элементныйбуфер - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - - // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // Пока не произойдет событие запроса закрытия окна while(!glfwWindowShouldClose(window)) { @@ -208,9 +207,9 @@ int main(void) glClear(GL_COLOR_BUFFER_BIT); // Тут производится рендер - glBindVertexArray(VertexArrayID); // Привязка VAO для использования + vao.use(); glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLuint), GL_UNSIGNED_INT, (void*)0); - glBindVertexArray(0); // Отключение VAO + vao.disable(); // Представление содержимого буфера цепочки показа на окно glfwSwapBuffers(window); @@ -220,13 +219,6 @@ int main(void) // Удаление шейдерной программы glDeleteProgram(shaderProgram); - - // Удаление VBO - glDeleteBuffers(1, &vertexbuffer); - glDeleteBuffers(1, &elementbuffer); - - // Удаление VAO - glDeleteVertexArrays(1, &VertexArrayID); return 0; }