Копия проекта с 02

This commit is contained in:
2022-07-26 13:13:30 +03:00
parent da9a3ffde7
commit 19990e877b
9 changed files with 567 additions and 0 deletions

119
src/Buffers.cpp Normal file
View File

@@ -0,0 +1,119 @@
#include "Buffers.h"
// Счетчики использований дескрипторов
std::map<GLuint, GLuint> VAO::handler_count;
std::map<GLuint, GLuint> 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); // Привязка элементного буфера
}

224
src/main.cpp Executable file
View File

@@ -0,0 +1,224 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <GLM/glm.hpp>
#include <iostream>
#include "Buffers.h"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_CAPTION "OPENGL notes on rekovalev.site"
// Функция-callback для изменения размеров буфера кадра в случае изменения размеров поверхности окна
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
#include <fstream>
#include <sstream>
// Функция чтения шейдера из файла
std::string readFile(const char* filename)
{
std::string text;
std::ifstream file(filename, std::ios::in); // Открываем файл на чтение
// Если файл доступен и успешно открыт
if (file.is_open())
{
std::stringstream sstr; // Буфер для чтения
sstr << file.rdbuf(); // Считываем файл
text = sstr.str(); // Преобразуем буфер к строке
file.close(); // Закрываем файл
}
return text;
}
// Функция для загрузки шейдеров
// Принимает два адреса вершинного и фрагментного шейдеров
// Возвращает дескриптор шейдерной программы
GLuint LoadShaders(const char *vertex_file, const char *fragment_file)
{
// Создание дескрипторов вершинного и фрагментного шейдеров
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Переменные под результат компиляции
GLint result = GL_FALSE;
int infoLogLength;
// Считываем текст вершинного шейдера
std::string code = readFile(vertex_file);
const char* pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
// Компиляция кода вершинного шейдера
glShaderSource(vertexShaderID, 1, &pointer, NULL);
glCompileShader(vertexShaderID);
// Проверка результата компиляции
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0)
{
char* errorMessage = new char[infoLogLength + 1];
glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, errorMessage);
std::cout << errorMessage;
delete[] errorMessage;
}
// Считываем текст вершинного шейдера
code = readFile(fragment_file);
pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
// Компиляция кода фрагментного шейдера
glShaderSource(fragmentShaderID, 1, &pointer, NULL);
glCompileShader(fragmentShaderID);
// Проверка результата компиляции
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result);
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0)
{
char* errorMessage = new char[infoLogLength + 1];
glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, errorMessage);
std::cout << errorMessage;
delete[] errorMessage;
}
// Привязка скомпилированных шейдеров
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
// Проверка программы
glGetProgramiv(programID, GL_LINK_STATUS, &result);
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0)
{
char* errorMessage = new char[infoLogLength + 1];
glGetProgramInfoLog(programID, infoLogLength, NULL, errorMessage);
std::cout << errorMessage;
delete[] errorMessage;
}
// Освобождение дескрипторов шейдеров
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
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
// Инициализация GLFW3
if (!glfwInit())
{
std::cout << "GLFW init error\n";
return -1;
}
// Завершение работы с GLFW3 перед выходом
atexit(glfwTerminate);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Мажорная версия спецификаций OpenGL
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); // Минорная версия спецификаций OpenGL
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Контекст OpenGL, который поддерживает только основные функции
// Создание окна GLFW3 с заданными шириной, высотой и заголовком окна
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION, NULL, NULL);
if (!window)
{
std::cout << "GLFW create window error\n";
return -1;
}
// Установка основного контекста окна
glfwMakeContextCurrent(window);
// Установка callback-функции для изменения размеров окна и буфера кадра
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSwapInterval(1); // Вертикальная синхронизация
// Загрузка функций OpenGL с помощью GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "GLAD load GL error\n";
return -1;
}
// Компиляция шейдеров
GLuint shaderProgram = LoadShaders("shaders/shader.vert", "shaders/shader.frag");
// Активация шейдера
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 вершинный
BO vbo_vert(VERTEX);
attrib_config(); // Конфигурация аттрибутов
// Загрузка вершин в используемый буфер вершин
vbo_vert.load(verticies, sizeof(verticies));
// индексы вершин
GLuint indices[] = {0, 1, 2, 2, 3, 0};
// VBO элементный (индексы вершин)
BO vbo_elem(ELEMENT);
// Загрузка индексов в используемый элементный буфер
vbo_elem.load(indices, sizeof(indices));
// Установка цвета очистки буфера цвета
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Пока не произойдет событие запроса закрытия окна
while(!glfwWindowShouldClose(window))
{
// Очистка буфера цвета
glClear(GL_COLOR_BUFFER_BIT);
// Тут производится рендер
vao.use();
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLuint), GL_UNSIGNED_INT, (void*)0);
vao.disable();
// Представление содержимого буфера цепочки показа на окно
glfwSwapBuffers(window);
// Обработка системных событий
glfwPollEvents();
}
// Удаление шейдерной программы
glDeleteProgram(shaderProgram);
return 0;
}