228 lines
9.0 KiB
C++
228 lines
9.0 KiB
C++
|
||
#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()
|
||
{
|
||
// Включаем необходимый атрибут у выбранного VAO
|
||
glEnableVertexAttribArray(0);
|
||
// Устанавливаем связь между VAO и привязанным VBO
|
||
glVertexAttribPointer( 0 // индекс атрибута, должен совпадать с Layout шейдера
|
||
, 3 // количество компонент одного элемента
|
||
, GL_FLOAT // тип
|
||
, GL_FALSE // нормализованность значений
|
||
, 0 // шаг
|
||
, (void *)0 // отступ с начала массива
|
||
);
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
GLFWwindow* window; // Указатель на окно GLFW3
|
||
|
||
// Инициализация GLFW3
|
||
if (!glfwInit())
|
||
{
|
||
std::cout << "GLFW init error\n";
|
||
return -1;
|
||
}
|
||
|
||
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";
|
||
glfwTerminate(); // Завершение работы с GLFW3 в случае ошибки
|
||
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";
|
||
glfwTerminate(); // Завершение работы с GLFW3 в случае ошибки
|
||
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 вершинный
|
||
VBO vbo_vert(VERTEX, attrib_config);
|
||
|
||
// Загрузка вершин в используемый буфер вершин
|
||
vbo_vert.load(verticies, sizeof(verticies));
|
||
|
||
// индексы вершин
|
||
GLuint indices[] = {0, 1, 2, 2, 3, 0};
|
||
|
||
// VBO элементный (индексы вершин)
|
||
VBO 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);
|
||
|
||
// Отключение атрибутов
|
||
glDisableVertexAttribArray(0);
|
||
|
||
// Завершение работы с GLFW3 перед выходом
|
||
glfwTerminate();
|
||
}
|