GLFW + GLAD = OpenGL графика с шейдерами

от автора

Здравствуйте, как давно меня здесь не было… Наверное не было ещё такой темы ради которой стоило бы Вас, дорогие читатели моих опусов, беспокоить.

Решил я познакомится поближе с OpenGL. Единственный доступный инструмент для написания программ и их компиляции, оказался NetBeans IDE 8.2, установочный файл netbeans-8.2-windows.exe размером 225 472 кб. и jdk-8u144-windows-x64 установочный файл jdk-8u144-windows-x64.exe размером 202 523 кб.

Размеры файлов и названия пишу точно, поскольку их размер зависит от их комплектации, а комплектация, насколько могу быть точным от конечной функциональности. После установки получаем вот такой инструмент разработки:

NetBeans IDE 8.2

NetBeans IDE 8.2
Настройки компиляторов

Настройки компиляторов

Использую компилятор CLang. Все инструменты скачаны при помощи утилиты MSYS которую можно скачать по ссылке https://www.msys2.org. Упор был сделан на инструменты UCRT64. MinGW не пользуюсь совсем.

Об инструментах поговорили и перейдём к OpenGL.

Проблема состояла в том, как тот код, который из интернета, запихать в конструкцию из GLFW + GLAD и получить OpenGL графику с шейдерами.

Первая проблема была с тем, как инициализировать GLAD? С glad.h проблем не было, а вот с glad.c возникли. Поиски решения оказались успешными и её реализацию вы увидите в коде, который я приведу ниже.

Вторая проблема в том, что часто можно увидеть конструкцию GLFW+GLEW, но я от неё отказался поскольку хотел реализовать конструкцию GLFW+GLAD.

Третья проблема, что везде в «туториалах» даётся множество примеров, которые отвязаны от цельного кода, куда писать, как встраивать код в программу, где искать дополнительные файлы, не понятно.

Я новичок в программировании, поэтому пишу с позиции именно новичка, так что не нападайте 🙂

main.cpp

//#define GLAD_GL_IMPLEMENTATION #include <GLAD/glad Core v.3.3/include/glad/glad.h> #include <GLAD/glad Core v.3.3/src/glad.c> #define GLFW_INCLUDE_NONE #include <GLFW/glfw3.h>  #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std;  //GLFWwindow  *window;  static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {     if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)         glfwSetWindowShouldClose(window, GLFW_TRUE);          switch (key)     {         case GLFW_KEY_ESCAPE:             glfwSetWindowShouldClose(window, GLFW_TRUE);             break;        /* case GLFW_KEY_SPACE:             cur_icon_color = (cur_icon_color + 1) % 5;             set_icon(window, cur_icon_color);             break;         case GLFW_KEY_X:             glfwSetWindowIcon(window, 0, NULL);             break;*/     } }      void triang() {     GLuint vbo = 0; GLuint vao = 0; float points[] = {    0.0f,  0.5f,  0.0f,    0.5f, -0.5f,  0.0f,   -0.5f, -0.5f,  0.0f }; const char* vertex_shader = "#version 400\n" "in vec3 vp;" "void main() {" "  gl_Position = vec4(vp, 1.0);" "}"; const char* fragment_shader = "#version 400\n" "out vec4 frag_colour;" "void main() {" "  frag_colour = vec4(0.2, 0.0, 0.5, 1.0);" "}"; GLuint vs = glCreateShader(GL_VERTEX_SHADER); GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); GLuint shader_programme = glCreateProgram(); glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);  glGenVertexArrays(1, &vao); glBindVertexArray(vao); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);   glShaderSource(vs, 1, &vertex_shader, NULL); glCompileShader(vs);  glShaderSource(fs, 1, &fragment_shader, NULL); glCompileShader(fs);  glAttachShader(shader_programme, fs); glAttachShader(shader_programme, vs); glLinkProgram(shader_programme);  glUseProgram(shader_programme);   glBindVertexArray(vao);   // draw points 0-3 from the currently bound VAO with current in-use shader   glDrawArrays(GL_TRIANGLES, 0, 3);   // update other events like input handling  }   // Когда пользователь меняет размер окна, окно просмотра также должно быть скорректировано, требуя функцию обратного вызова void framebuffer_size_callback(GLFWwindow* window,int width,int height){          // Первые два параметра функции glViewport управляют положением нижнего левого угла окна, а третий и четвертый параметры контролируют ширину и высоту окна рендеринга     glfwSetKeyCallback(window, key_callback);     glfwGetFramebufferSize(window, &width, &height);     glViewport(0,0,width,height); } // Объявляем функцию, чтобы определить, нажата ли конкретная клавиша void processInput(GLFWwindow * window){          // Проверка, нажимает ли пользователь клавишу возврата (Esc) (если не нажата, glfwGetKey вернет GLFW_RELEASE, если нажата, GLFW_PRESS)     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {         glfwSetWindowShouldClose(window, true);     } }  int main(int argc, char** argv) { // Инициализация GLFW     glfwInit();               // Установить номер основной версии OpenGL (Major) и номер вспомогательной версии (Minor) в 3     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);               // Использование режима ядра (Core-profile)     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);               // Если это система MacOS, вам понадобится следующая строка кода для работы конфигурации     //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);               // Создать объект окна     GLFWwindow * window = glfwCreateWindow(800, 600, "GLFW + GLAD", NULL, NULL);     if (window == NULL){         cout << "Failed to create GLFW window" << endl;         glfwTerminate();         return -1;     }          // Уведомить GLFW, чтобы установить контекст нашего окна в качестве основного контекста текущего потока     glfwMakeContextCurrent(window);               // GLAD используется для управления указателем функции OpenGL, нам нужно инициализировать GLAD перед вызовом любой функции OpenGL     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){         cout << "Failed to initialize GLAD" << endl;         return -1;     }               // Зарегистрируем определенную функцию обратного вызова и сообщаем GLFW вызывать эту функцию при каждом изменении размера окна     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);                         // Визуализация цикла     while (!glfwWindowShouldClose(window)) {                           // Проверить, нажата ли конкретная клавиша, и обрабатывать ее каждый кадр         processInput(window);                           // функция glClearColor - это функция установки состояния, используемая для установки цвета, используемого для очистки экрана         glClearColor(0.2f,0.3f,0.3f,1.0f);                  // Функция glClear - это функция использования состояния, которая использует текущее состояние для очистки экрана с указанным цветом         glClear(GL_COLOR_BUFFER_BIT);         //triang(); - запускаем отрисовку треугольника. Работает именно в этом месте!         triang();                  // Функция glfwSwapBuffers будет обмениваться цветовыми буферами         glfwSwapBuffers(window);                  // Функция glfwPollEvents проверяет, запущены ли какие-либо события         glfwPollEvents();     }                    // Освободить все ресурсы, выделенные ранее     glfwTerminate();          return 0; } 

результат работы программы:

В этом коде я собрал много разных идей, здесь нет ни чего моего, кроме компоновки кода.

Результат работы программы

Результат работы программы

Да. Программа не ахти какая, но как видно из примера, работать в этой конструкции можно и вполне себе успешно. Можно выдернуть код, удалив всего одну функцию не разрушив целость структуры и так же вставить другой код. Какие перспективы у данной реализации? Наверно ограничиваются только фантазией.

Всем творческих успехов.


ссылка на оригинал статьи https://habr.com/ru/articles/746884/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *