#include <glad/glad.h> #include <GLFW/glfw3.h> #include <GLM/glm.hpp> #include <iostream> #include "Scene.h" #include "Shader.h" #include "Lights.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); } 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::current().rotate(offset); } 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); // Вертикальная синхронизация // Установка callback-функции для мыши и камеры glfwSetCursorPosCallback(window, mouse_callback); // Загрузка функций OpenGL с помощью GLAD if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "GLAD load GL error\n"; return -1; } // Включаем проверку по буферу глубины glEnable(GL_DEPTH_TEST); // Базовый шейдер ShaderProgram base; // Загрузка и компиляция шейдеров base.load(GL_VERTEX_SHADER, "shaders/shader.vert"); base.load(GL_FRAGMENT_SHADER, "shaders/shader.frag"); base.link(); // Установим значения текстур const char* textures_base_shader_names[] = {"tex_diffuse", "tex_ambient", "tex_specular"}; base.bindTextures(textures_base_shader_names, sizeof(textures_base_shader_names)/sizeof(const char*)); // Загрузка сцены из obj файла Scene scene = loadOBJtoScene("../resources/models/blob.obj", "../resources/models/", "../resources/textures/"); scene.root.e_scale() = glm::vec3(0.01); scene.root.e_position().z = 1; // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Расположение Uniform-переменной GLuint model_uniform = base.getUniformLoc("model"); // Источник света LightData light = { {1.0f, 3.0f, 0.0f} // позиция , {1.0f, 1.0f, 1.0f} // цвет }; // Uniform-буферы UBO cameraUB(sizeof(CameraData), 0); UBO material_data(sizeof(Material), 1); UBO light_data(&light, sizeof(LightData), 2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Использование уменьшенных версий mipmap // Пока не произойдет событие запроса закрытия окна while(!glfwWindowShouldClose(window)) { // Загрузка данных о камере cameraUB.loadSub(&Camera::current().getData(), sizeof(CameraData)); // Очистка буфера цвета glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Тут производится рендер scene.render(model_uniform, material_data); // Представление содержимого буфера цепочки показа на окно glfwSwapBuffers(window); // Обработка системных событий glfwPollEvents(); } return 0; }