Categories: C/C++

opengl-simple-project/

В свободное время я потихоньку раскуриваю OpenGL. Это у меня что-то вроде нового хобби. Как кто-то из вас может помнить, когда-то я уже пробовал играться с OpenGL на Haskell . Однако использовать тамошний ни на что не похожий и практически не документированный DSL оказалось слишком сложной задачей для меня, и от затеи пришлось отказаться.

Надо отметить, что в этот раз я чуть было не совершил ту же ошибку, выбрав поначалу язык Scala и библиотеку LWJGL . С документацией у LWJGL все отлично, никакого своего DSL не накручено, и примеров в сети очень много. Но проблема заключается в том, что в большинстве туториалов и книг по OpenGL все же используется язык C++. И если ты столкнешься с какой-то проблемой, никто ни в каком IRC или на StackOverflow не станет разбираться в твоем коде на Scala. Плюс неизвестно еще, ты просто неправильно используешь OpenGL, или может это какая-то ошибка в LWJGL, или может это какой-то хитрый баг, вызванный взаимодействием кода на Scala с LWJGL. Сообщество вокруг LWJGL достаточно велико само по себе, но чтобы кто-то из этого сообщества тебе помог, код должен быть на Java, а с Java связываться ну очень не хотелось. Кроме того, у LWJGL на данный момент есть стабильная, но постепенно теряющая свою актуальность версия 2.9, а также совершенно новая, ни с чем не совместимая, и все еще находящаяся в альфе версия 3.0.

В силу всех этих причин на время изучения OpenGL я решил использовать C++. Когда у меня будет больше опыта в самом OpenGL, можно будет попробовать использовать и альтернативные языки, например, Scala или Go . В качестве системы сборки был выбран CMake . Дело в том, что в Linux, активным пользователем которого я являюсь, по всей видимости, пока что наиболее приличной IDE для C++ является CLion . Я реально проводил серьезный ресерч на эту тему. А CLion ничего кроме CMake пока не поддерживает. Кроме того, у меня есть очень приятный опыт использования продукции JetBrains в прошлом, да и в настоящем.

Интересно, как культура и традиции могут определять выбор технологий, не правда ли?

Теперь, когда инструментарий выбран, можно создать новый Git-репозиторий , открыть CLion и создать в этом репозитории новый проект. В проекте нам понадобятся кое-какие зависимости. И тут начинается интересное, так как общепринятого способа управления зависимостями в C++ вроде как нет. Довольно перспективно выглядит Biicode , но, насколько я могу судить, пока что он не получил широкого распространения. Не то, чтобы я много работал с C++ в последнее время, но похоже, что неплохое решение заключается в следующем. Зависимости, которые можно поставить через менеджер пакетов ОС, например, apt-get , ставятся через него. Прочие же зависимости подтягиваются в виде исходных кодов через механизм сабмодулей в Git .

Например, нам в нашем проекте понадобятся библиотеки GLM и GLFW. Первая предназначена для работы с матрицами и векторами. Вторая — для рисования окошек, реагирования на движения мыши, нажатия клавиш клавиатуры и так далее. Еще для решения той же задачи есть GLUT. В одних туториалах используется GLFW, в других GLUT, и в чем принципиальное различие между ними на данный момент мне не до конца понятно. Так что, по сути, тут я выбирал наугад. Итак, используя сабмодули Git, подключаем эти библиотеки к проекту:

git submodule add https: // github.com / glfw / glfw glfw
git submodule add https: // github.com / Groovounet / glm glm

Если вы склонируете репозиторий на другую машину, подтянуть зависимости можно так:

git submodule init
git submodule update

Интересный факт о сабмодулях — они смотрят на конкретный коммит. Изменить его можно, перейдя в каталог сабмодуля и сделав checkout интересующей ветки или тэга. После этого git diff вашего собственного репозитория покажет, что в нем есть изменения, который можно закоммитить. Также в какой-то момент вы можете обнаружить, что удаляются сабмодули Git очень непросто. Делается это так ( почти рабочий рецепт был найден на gist , приведенная ниже инструкция тестировалась на Git 1.9.1):

  1. Скажите git rm --cached имя_сабмодуля ;
  2. Удалите соответствующие строчки из файла .gitmodules;
  3. Также грохните соответствующую секцию в .git/config;
  4. Сделайте коммит;
  5. Удалите файлы сабмодуля;
  6. Удалите каталог .git/modules/имя_сабмодуля;

Теперь правим файл CMakeList.txt нашего проекта:

cmake_minimum_required ( VERSION 2.8 )
project ( red_triangle )

find_package ( OpenGL REQUIRED )

add_subdirectory ( glfw )

include_directories ( glfw/include )
include_directories ( glm )

set ( CMAKE_CXX_FLAGS » ${CMAKE_CXX_FLAGS} -O2 -Wall -Wextra -std=c++11″ )

set ( SOURCE_FILES main.cpp )
add_executable ( red_triangle ${SOURCE_FILES} )

target_link_libraries ( red_triangle
glfw ${GLFW_LIBRARIES} ${OPENGL_LIBRARY} )

Как видите, здесь просто указывается минимальная версия cmake, название проекта, его зависимости и флаги компиляции. Ничего сложного.

В main.cpp пишем следующий код:

#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <iostream>

int main ( ) {
if ( ! glfwInit ( ) ) {
std :: cerr << «Failed to initialize GLFW» << std :: endl ;
return 1 ;
}

glfwDefaultWindowHints ( ) ;

GLFWwindow * window = glfwCreateWindow ( 300 , 300 , «Red Triangle» ,
nullptr, nullptr ) ;
if ( window == nullptr ) {
std :: cerr << «Failed to open GLFW window» << std :: endl ;
glfwTerminate ( ) ;
return 1 ;
}

glfwMakeContextCurrent ( window ) ;
glfwSwapInterval ( 1 ) ;
glfwShowWindow ( window ) ;

// Важно! Не эквивалентно glEnable(GL_DEPTH_TEST | GL_DOUBLEBUFFER)
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_DOUBLEBUFFER ) ;
glDepthFunc ( GL_LESS ) ;

glClearColor ( 0 , 0 , 0 , 1 ) ;

glm :: mat4 m = glm :: perspective ( 45.0f , 4.0f / 3.0f , 1.0f , 100.0f ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadMatrixf ( glm :: value_ptr ( m ) ) ;

while ( glfwWindowShouldClose ( window ) == GL_FALSE ) {
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
glColor4f ( 1 , 0 , 0 , 1 ) ;
glBegin ( GL_TRIANGLES ) ;
glVertex3f ( 0 , 0.5 , 5 ) ;
glVertex3f ( 0.5 , 0.5 , 5 ) ;
glVertex3f ( 0.5 , 0.5 , 5 ) ;
glEnd ( ) ;

glfwSwapBuffers ( window ) ;
glfwPollEvents ( ) ;
}

glfwDestroyWindow ( window ) ;
glfwTerminate ( ) ;
return 0 ;
}

Важно! Имейте в виду, что все эти glBegin, glEnd и glVertex3f — это устаревший OpenGL. В новых проектах вы не должны их использовать. Здесь эти функции используются только для того, чтобы не уводить повествование в сторону VAO, VBO и шейдеров. Заинтересованные читатели могут ознакомиться с почти таким же проектом на новом OpenGL .

Код предположительно очень прост и на данном этапе не нуждается в особых пояснениях. Здесь вы видите пример создания окна при помощи GLFW, простой пример использования GLM, а также рисование красного треугольника на черном фоне при помощи устаревших функций OpenGL. Заинтересованные читатели могут найти больше теории в предыдущих постах этого блога, посвященных OpenGL, или дождаться будущих. Результат же будет выглядеть как-то так:

А сборка проекта «вручную», без использования CLion, осуществляется так:

mkdir build
cd build
cmake ..
make

Примечательно, что это же проект успешно компилируется и под Windows. Там есть свои сложности, связанные с необходимостью устанавливать MinGW и Git для Windows , но в целом все работает точно так же. Еще может потребоваться немного подправить идущий с MinGW файл math.h, так как в нем есть баг . Кроме того, код успешно собирается и под MacOS.

Итак, теперь у нас есть полноценная среда для изучения OpenGL. Полную версию исходного кода к заметке вы найдете в этом репозитории .

Дополнение: Продолжаем изучение OpenGL: VBO, VAO и шейдеры

admin

Share
Published by
admin
Tags: C/C++

Recent Posts

vim-commands/

Самое главное — побороть боязнь белого листа. Я всегда говорю это себе, когда нужно начать…

4 недели ago

firefox-thunderbird-en-ru-dict/

По не вполне ясным причинам, Firefox умеет проверять орфографию либо только в русских, либо только…

4 недели ago

perl-hacks/

Около месяца собирал разные «хаки» на языке программирования Perl. Эта подборка наглядно демонстрирует, как в…

4 недели ago

perl-cy-check/

C недавних пор я стал увлекаться SEO. Порой передо мной встает задача быстро проверить индекс…

4 недели ago

which-cms-perl/

Недавно написал несколько скриптов, позволяющих автоматически определять, какая CMS (Content Management System, система управления контентом)…

4 недели ago

smtp-descr/

Я так подозреваю, что среди вас найдется те, кто скажет, что этот пост боян и…

4 недели ago