#include #include #include #include #include "Camera.h" #include "Model.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 #include // Функция чтения шейдера из файла 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; } Camera camera(800.0f/600.0f); bool firstMouse = true; float lastX, lastY; void mouse_callback(GLFWwindow* window, double xpos, double ypos) { if (firstMouse) { lastX = xpos; lastY = ypos; firstMouse = false; } glm::vec2 offset(xpos - lastX, lastY - ypos); lastX = xpos; lastY = ypos; camera.rotate(offset); } int main(void) { GLFWwindow* window; // Указатель на окно GLFW3 // Инициализация GLFW3 if (!glfwInit()) { std::cout << "GLFW init error\n"; return -1; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Мажорная версия спецификаций OpenGL glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Минорная версия спецификаций 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); // Вертикальная синхронизация // Установка callback-функции для мыши и камеры glfwSetCursorPosCallback(window, mouse_callback); // Загрузка функций 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} }; // Модель прямоугольника Model rectangle; // Загрузка вершин модели rectangle.load_verteces(verticies, sizeof(verticies)/sizeof(glm::vec3)); // индексы вершин GLuint indices[] = {0, 1, 2, 2, 3, 0}; // Загрузка индексов модели rectangle.load_indices(indices, sizeof(indices)); rectangle.position.z = 2; rectangle.rotation = glm::vec3(45); // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Расположение Uniform-переменной GLuint mvp_uniform = glGetUniformLocation(shaderProgram, "mvp"); // Пока не произойдет событие запроса закрытия окна while(!glfwWindowShouldClose(window)) { // Очистка буфера цвета glClear(GL_COLOR_BUFFER_BIT); // Тут производится рендер rectangle.render(mvp_uniform); // Представление содержимого буфера цепочки показа на окно glfwSwapBuffers(window); // Обработка системных событий glfwPollEvents(); } // Удаление шейдерной программы glDeleteProgram(shaderProgram); // Отключение атрибутов glDisableVertexAttribArray(0); // Завершение работы с GLFW3 перед выходом glfwTerminate(); }