From c117dd31c2df3ed7c5f1239027b37b38361086ed Mon Sep 17 00:00:00 2001 From: "re.kovalev" Date: Tue, 26 Jul 2022 14:09:20 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BB=D0=B0=D1=81=D1=81=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Buffers.h | 4 +- include/Model.h | 26 ++++++++++++ src/Buffers.cpp | 6 +++ src/Model.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 47 ++++++---------------- 5 files changed, 147 insertions(+), 36 deletions(-) create mode 100644 include/Model.h create mode 100644 src/Model.cpp diff --git a/include/Buffers.h b/include/Buffers.h index f427336..9283955 100644 --- a/include/Buffers.h +++ b/include/Buffers.h @@ -15,6 +15,8 @@ class VAO void use(); // Активация VAO static void disable(); // Деактивация активного VAO + GLuint get_handler(); // возвращает дескриптор + private: GLuint handler; // Дескриптор }; @@ -40,4 +42,4 @@ class VBO BUFFER_TYPE type; // Тип буфера }; -#endif // BUFFERS_H \ No newline at end of file +#endif // BUFFERS_H diff --git a/include/Model.h b/include/Model.h new file mode 100644 index 0000000..c3b86d4 --- /dev/null +++ b/include/Model.h @@ -0,0 +1,26 @@ +#ifndef MODEL_H +#define MODEL_H + +#include "Buffers.h" + +#include + +class Model +{ + public: + Model(); // Конструктор без параметров + Model(const Model& copy); // Конструктор копирования + ~Model(); + void render(); // Вызов отрисовки + void load_verteces(glm::vec3* verteces, GLuint count); // Загрузка вершин в буфер + void load_indices(GLuint* indices, GLuint count); // Загрузка индексов в буфер + + private: + VAO *vao; + VBO *vertex_vbo, *index_vbo; // вершинный и индексный буферы + GLuint verteces_count; // Количество вершин + GLuint indices_count; // Количество индексов + +}; + +#endif // MODEL_H diff --git a/src/Buffers.cpp b/src/Buffers.cpp index e6864c7..112db37 100644 --- a/src/Buffers.cpp +++ b/src/Buffers.cpp @@ -25,6 +25,12 @@ void VAO::disable() glBindVertexArray(0); // Отключение VAO } +// возвращает дескриптор +GLuint VAO::get_handler() +{ + return handler; +} + // Создает пустой буфер, привязывает к активному VAO, если нужно конфигурирует атрибуты VBO::VBO(BUFFER_TYPE t, void (*attrib_config)()) : type(t) { diff --git a/src/Model.cpp b/src/Model.cpp new file mode 100644 index 0000000..814fac1 --- /dev/null +++ b/src/Model.cpp @@ -0,0 +1,100 @@ +#include "Model.h" + +#include + +// Словарь для хранения количества моделей, использующих общие VAO +std::map vaos_count; + +// Конструктор без параметров +Model::Model() : verteces_count(0), indices_count(0), vertex_vbo(0), index_vbo(0) +{ + // Создаем новый буфер + vao = new VAO(); + // Запоминаем, что для нового VAO количество моделей, использующих его, = 1 + vaos_count[vao->get_handler()] = 1; +} + +// Конструктор копирования +Model::Model(const Model& copy) : vao(copy.vao), verteces_count(copy.verteces_count), indices_count(copy.indices_count), vertex_vbo(copy.vertex_vbo), index_vbo(copy.index_vbo) +{ + // Если создается копия модели, то запоминаем поля и инкрементируем словарь с количеством + vaos_count[vao->get_handler()]++; +} + +Model::~Model() +{ + // При уничтожении модели проверяем: если это последний пользователь меша, то осовобождаем из под него память + if (--vaos_count[vao->get_handler()] < 1) + { + if (vertex_vbo) + delete vertex_vbo; + if (index_vbo) + delete index_vbo; + delete vao; + } + +} + +// Вызов отрисовки +void Model::render() +{ + // Подключаем VAO + vao->use(); + // Если есть индексы - рисуем с их использованием + if (indices_count) + glDrawElements(GL_TRIANGLES, indices_count, GL_UNSIGNED_INT, (void*)0); + // Если есть вершины - рисуем на основании массива вершин + else if (verteces_count) + glDrawArrays(GL_TRIANGLES, 0, verteces_count); +} + +// Функция для конфигурации атрибута вершинного буфера +void vertex_attrib_config() +{ + // Включаем необходимый атрибут у выбранного VAO + glEnableVertexAttribArray(0); + // Устанавливаем связь между VAO и привязанным VBO + glVertexAttribPointer( 0 // индекс атрибута, должен совпадать с Layout шейдера + , 3 // количество компонент одного элемента + , GL_FLOAT // тип + , GL_FALSE // нормализованность значений + , 0 // шаг + , (void *)0 // отступ с начала массива + ); +} + +// Загрузка вершин в буфер +void Model::load_verteces(glm::vec3* verteces, GLuint count) +{ + // Подключаем VAO + vao->use(); + + // Если до этого такого буфера не было - создаем его, иначе используем + if (!vertex_vbo) + vertex_vbo = new VBO(VERTEX, vertex_attrib_config); + else + vertex_vbo->use(); + + // Загрузка вершин в память буфера + vertex_vbo->load(verteces, sizeof(glm::vec3)*count); + // Запоминаем количество вершин для отрисовки + verteces_count = count; +} + +// Загрузка индексов в буфер +void Model::load_indices(GLuint* indices, GLuint count) +{ + // Подключаем VAO + vao->use(); + + // Если до этого такого буфера не было - создаем его, иначе используем + if (!index_vbo) + index_vbo = new VBO(ELEMENT); + else + index_vbo->use(); + + // Загрузка вершин в память буфера + index_vbo->load(indices, sizeof(GLuint)*count); + // Запоминаем количество вершин для отрисовки + indices_count = count; +} diff --git a/src/main.cpp b/src/main.cpp index 8fa1cd9..44feb6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ #include -#include "Buffers.h" +#include "Model.h" #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 @@ -112,21 +112,6 @@ GLuint LoadShaders(const char *vertex_file, const char *fragment_file) return programID; } -// Функция для конфигурации атрибутов -void attrib_config() -{ - // Включаем необходимый атрибут у выбранного VAO - glEnableVertexAttribArray(0); - // Устанавливаем связь между VAO и привязанным VBO - glVertexAttribPointer( 0 // индекс атрибута, должен совпадать с Layout шейдера - , 3 // количество компонент одного элемента - , GL_FLOAT // тип - , GL_FALSE // нормализованность значений - , 0 // шаг - , (void *)0 // отступ с начала массива - ); -} - int main(void) { GLFWwindow* window; // Указатель на окно GLFW3 @@ -138,8 +123,8 @@ int main(void) return -1; } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Мажорная версия спецификаций OpenGL - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); // Минорная версия спецификаций OpenGL + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Мажорная версия спецификаций OpenGL + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Минорная версия спецификаций OpenGL glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Контекст OpenGL, который поддерживает только основные функции // Создание окна GLFW3 с заданными шириной, высотой и заголовком окна @@ -171,29 +156,23 @@ int main(void) // Активация шейдера glUseProgram(shaderProgram); - // Вершины треугольника + // Вершины прямоугольника glm::vec3 verticies[] = { {-0.5f, -0.5f, 0.0f} , { 0.5f, -0.5f, 0.0f} , { 0.5f, 0.5f, 0.0f} , {-0.5f, 0.5f, 0.0f} }; - - // VAO - VAO vao; - // VBO вершинный - VBO vbo_vert(VERTEX, attrib_config); - - // Загрузка вершин в используемый буфер вершин - vbo_vert.load(verticies, sizeof(verticies)); + // Модель прямоугольника + Model rectangle; + + // Загрузка вершин модели + rectangle.load_verteces(verticies, sizeof(verticies)/sizeof(glm::vec3)); // индексы вершин GLuint indices[] = {0, 1, 2, 2, 3, 0}; - // VBO элементный (индексы вершин) - VBO vbo_elem(ELEMENT); - - // Загрузка индексов в используемый элементный буфер - vbo_elem.load(indices, sizeof(indices)); + // Загрузка индексов модели + rectangle.load_indices(indices, sizeof(indices)); // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); @@ -206,9 +185,7 @@ int main(void) glClear(GL_COLOR_BUFFER_BIT); // Тут производится рендер - vao.use(); - glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLuint), GL_UNSIGNED_INT, (void*)0); - vao.disable(); + rectangle.render(); // Представление содержимого буфера цепочки показа на окно glfwSwapBuffers(window);