OpenGL - это мощный инструмент трехмерного программирования, используемый для рисования сложных трехмерных сцен из простых примитивов. В этой статье вы узнаете, как нарисовать простой куб, который можно вращать и просматривать в трех измерениях!
Для этого проекта вам понадобится редактор кода и некоторые знания программирования на C.
Шаги
Часть 1 из 3: Начальная настройка
Шаг 1. Установка OpenGL Для начала выполните следующие шаги для установки OpenGL в вашей системе
Если у вас уже установлен OpenGL и совместимый компилятор C, вы можете пропустить этот шаг и перейти к следующему.
Шаг 2. Создайте документ
Создайте новый файл в своем любимом редакторе кода и сохраните его как mycube.c
Шаг 3. Добавьте #includes
Это основные включения, которые вам понадобятся для вашей программы. Важно понимать, что на самом деле для разных операционных систем требуются разные включаемые компоненты. Обязательно включите все это, чтобы ваша программа была универсальной и могла работать для любого пользователя.
// Включает #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif
Шаг 4. Добавьте прототипы функций и глобальные переменные
Ваш следующий шаг - объявить несколько прототипов функций.
// Прототипы функций void display (); void specialKeys (); // Глобальные переменные double rotate_y = 0; двойной rotate_x = 0;
Шаг 5. Настройте функцию main ()
int main (int argc, char * argv ) {// Инициализируем GLUT и обрабатываем пользовательские параметры glutInit (& argc, argv); // Запрос окна истинного цвета с двойной буферизацией с Z-буфером glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
Шаг 6. Создайте окно
Следующий шаг - создать окно внутри которого вы нарисуете куб. В этом уроке окно называется «Удивительный куб».
// Создание окна glutCreateWindow ("Awesome Cube");
Шаг 7. Включите проверку глубины
OpenGL - это строгий язык, поскольку он не предполагает включения каких-либо специальных функций. Чтобы ваша программа правильно отображалась в 3-х измерениях с использованием Z-буфера, на который вы смотрели ранее, вам необходимо: включить проверку глубины. По мере того, как вы продолжите изучать OpenGL, вы обнаружите множество функций, которые вам нужно будет включить, включая освещение, текстуры, отбраковку и многое другое.
// Включить проверку глубины Z-буфера glEnable (GL_DEPTH_TEST);
Шаг 8. Добавьте функции обратного вызова
Вот прототипы функций обратного вызова, для которых вы написали ранее. Эти функции будут вызываться каждый раз при прохождении основного цикла. Функция отображения перерисовывает сцену на основе любых изменений переменных, которые были внесены с момента предыдущего вызова. Функция specialKeys позволяет нам взаимодействовать с программой.
// Функции обратного вызова glutDisplayFunc (display); glutSpecialFunc (specialKeys);
Шаг 9. Запустите MainLoop
Это вызовет основную функцию до тех пор, пока вы не закроете программу, чтобы разрешить анимацию и взаимодействие с пользователем.
// Передаем управление событиям GLUT glutMainLoop (); // Вернуться в ОС return 0; }
Часть 2 из 3: Функция display ()
Шаг 1. Разберитесь в назначении этой функции
Вся работа по рисованию вашего куба будет выполняться в этой функции. Общая идея вашего куба состоит в том, чтобы нарисовать все шесть сторон по отдельности и разместить их в нужном месте.
Концептуально каждая сторона будет нарисована, определив четыре угла и позволив OpenGL соединить линии и залить их определенным вами цветом. Ниже приведены шаги для этого
Шаг 2. Добавьте glClear ()
Первый шаг, который вам нужно сделать в этой функции, - это очистить буфер цвета и Z. Без этих шагов старые рисунки все еще могут быть видны под новыми рисунками, а нарисованные объекты не будут находиться в правильном месте на экране.
void display () {// Очистить экран и Z-буфер glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Шаг 3. Добавьте glBegin () и glEnd ()
OpenGL определяет объекты как комбинации различных полигонов. С помощью glBegin () вы положите карандаш, чтобы нарисовать фигуру. Чтобы поднять карандаш и начать новую форму, вы должны использовать glEnd () команда. В этом руководстве вы будете использовать GL_POLYGON для рисования каждой стороны куба, но можно использовать другие параметры параметров, такие как GL_LINE, GL_QUAD или GL_TRIANGLE, для создания других форм.
- Здесь вы начнете с передней части куба. Позже вы добавите цвет ко всем 6 сторонам.
// Разноцветная сторона - FRONT glBegin (GL_POLYGON); // Вершины будут добавлены на следующем шаге glEnd ();
Шаг 4. Добавьте glVertex3f ()
После того, как вы заявили, что хотите начать свой многоугольник, вам нужно определить вершины объекта. glVertex имеет несколько форм в зависимости от того, что вы хотите делать с вашим объектом.
- Во-первых, в скольких измерениях вы работаете. 3 выше в glVertex3f говорят, что вы рисуете в 3-х измерениях. Также можно работать в 2 или 4 измерениях. F выше в glVertex3f говорит, что вы работаете с числами с плавающей запятой. Вы также можете использовать короткие, целые или двойные числа.
- Обратите внимание, что эти точки определены в против часовой стрелки манера. На данный момент это не очень важно, но когда вы начнете работать с освещением, текстурами и отбраковкой, это станет невероятно важным, поэтому возьмите за привычку определять свои точки против часовой стрелки.
- Добавьте вершины между линиями glBegin () и glEnd ().
// Разноцветная сторона - FRONT glBegin (GL_POLYGON); glVertex3f (-0,5, -0,5, -0,5); // P1 glVertex3f (-0,5, 0,5, -0,5); // P2 glVertex3f (0.5, 0.5, -0.5); // P3 glVertex3f (0.5, -0.5, -0.5); // P4 glEnd ();
Шаг 5. Добавьте glColor3f ()
glColor работает аналогично glVertex. Вы можете определять точки как короткие, целые, двойные или плавающие. Каждый цвет имеет значение от 0 до 1. Все 0 делают точку черной, а все единицы делают точку белой. Число 3 в glColor3f () относится к цветовой системе RGB без альфа-канала. Альфа цвета определяет его прозрачность. Чтобы изменить альфа-уровень, используйте glColor4f () с последним параметром, имеющим значение от 0 до 1 для непрозрачного или прозрачного.
- Когда вы вызываете glColor3f (), каждая вершина, нарисованная с этой точки, будет этого цвета. Следовательно, если вы хотите, чтобы все четыре вершины были красными, просто установите цвет один раз в любое время перед командами glVertex3f (), и все вершины будут красными.
- Определенная ниже лицевая сторона показывает, как определить новый цвет для каждой вершины. Когда вы это сделаете, вы увидите интересное свойство цветов OpenGL. Поскольку каждая вершина многоугольника имеет свой цвет, OpenGL автоматически смешивает цвета! Следующий шаг покажет, как присвоить четырем вершинам один и тот же цвет.
// Разноцветная сторона - FRONT glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); // P1 красный glColor3f (0.0, 1.0, 0.0); glVertex3f (0,5, 0,5, -0,5); // P2 зеленый glColor3f (0.0, 0.0, 1.0); glVertex3f (-0,5, 0,5, -0,5); // P3 синий glColor3f (1.0, 0.0, 1.0); glVertex3f (-0,5, -0,5, -0,5); // P4 фиолетовый glEnd ();
Шаг 6. Обработайте остальные стороны
Определите расположение каждой вершины для других пяти сторон куба, но для простоты они были вычислены для вас и включены в таблицу final display () функция ниже.
// Белая сторона - НАЗАД glBegin (GL_POLYGON); glColor3f (1.0, 1.0, 1.0); glVertex3f (0,5, -0,5, 0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glEnd (); // Фиолетовая сторона - ПРАВА glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 1.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, -0,5, 0,5); glEnd (); // Зеленая сторона - ЛЕВАЯ glBegin (GL_POLYGON); glColor3f (0,0, 1,0, 0,0); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); // Синяя сторона - TOP glBegin (GL_POLYGON); glColor3f (0,0, 0,0, 1,0); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, 0,5); glEnd (); // Красная сторона - НИЖНИЙ glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); glFlush (); glutSwapBuffers (); }
Мы также хотим добавить две последние строки кода для этой функции. Эти glFlush ();
а также glutSwapBuffers ();
которые дают нам эффект двойной буферизации, о котором вы узнали ранее.
Часть 3 из 3. Взаимодействие с пользователем
Шаг 1. Добавьте specialKeys ()
Вы почти закончили, но на данный момент вы можете нарисовать куб, но не можете его повернуть. Для этого вам нужно создать specialKeys () функция, позволяющая нам нажимать клавиши со стрелками и вращать куб!
- Именно поэтому вы объявили глобальные переменные rotate_x и rotate_y. Когда вы нажимаете клавиши со стрелками вправо и влево, rotate_y будет увеличиваться или уменьшаться на 5 градусов. Точно так же, когда вы нажимаете клавиши со стрелками вверх и вниз, rotate_x изменится соответствующим образом.
void specialKeys (int key, int x, int y) {// Стрелка вправо - увеличить поворот на 5 градусов if (key == GLUT_KEY_RIGHT) rotate_y + = 5; // Стрелка влево - уменьшить поворот на 5 градусов иначе if (key == GLUT_KEY_LEFT) rotate_y - = 5; иначе, если (ключ == GLUT_KEY_UP) rotate_x + = 5; иначе, если (клавиша == GLUT_KEY_DOWN) rotate_x - = 5; // Запросить обновление дисплея glutPostRedisplay (); }
Шаг 2. Добавьте glRotate ()
Ваше последнее утверждение - добавить оператор, который будет вращать ваш объект. Вернитесь к функции display () и перед ПЕРЕДНЕЙ стороной добавьте следующие строки:
// Сбросить преобразования glLoadIdentity (); // Поворот, когда пользователь изменяет rotate_x и rotate_y glRotatef (rotate_x, 1.0, 0.0, 0.0); glRotatef (rotate_y, 0,0, 1,0, 0,0); // Разноцветная сторона - ПЕРЕДНЯЯ….
Шаг 3. Добавьте следующие команды, чтобы масштабировать куб на 2 по оси x, на 2 по оси y, повернуть куб на 180 градусов вокруг оси y и сдвинуть куб на 0,1 вдоль оси x
Убедитесь, что эти и предыдущие команды glRotate () расположены в правильном порядке, как описано выше. (Если вы не уверены, это сделано в окончательном коде в конце руководства.)
// Другие преобразования glTranslatef (0.1, 0.0, 0.0); glRotatef (180, 0,0, 1,0, 0,0); glScalef (2.0, 2.0, 0.0);
Шаг 4. Скомпилируйте и запустите свой код
Предполагая, что вы используете gcc в качестве компилятора, запустите эти команды из вашего терминала, чтобы скомпилировать и протестировать вашу программу.
В Linux: gcc cube.c -o cube -lglut -lGL./ mycube На Mac: gcc -o foo foo.c -framework GLUT -framework OpenGL./ mycube В Windows: gcc -Wall -ofoo foo.c -lglut32cu - lglu32 -lopengl32./ mycube
Шаг 5. Проверьте свой полный код
Должно получиться так:
// // Файл: mycube.c // Автор: Мэтт Дэйсли // Дата создания: 25.04.2012 // Проект: Исходный код для создания куба в OpenGL // Описание: Создает окно OpenGL и рисует 3D-куб / / Что пользователь может вращать с помощью клавиш со стрелками // // Элементы управления: Стрелка влево - Повернуть влево // Стрелка вправо - Повернуть вправо // Стрелка вверх - Повернуть вверх // Стрелка вниз - Повернуть вниз // ------ -------------------------------------------------- -- // Включает в себя // ------------------------------------------- --------------- #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif // ------------- --------------------------------------------- // Прототипы функций / / ------------------------------------------------- --------- void display (); void specialKeys (); // ------------------------------------------------ ---------- // Глобальные переменные // ---------------------------------- ------------------------ двойной rotate_y = 0; двойной rotate_x = 0; // ------------------------------------------------ ---------- // Функция обратного вызова display () // ------------------------------- --------------------------- void display () {// Очистить экран и Z-буфер glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Сброс преобразований glLoadIdentity (); // Другие преобразования // glTranslatef (0.1, 0.0, 0.0); // Не включается // glRotatef (180, 0.0, 1.0, 0.0); // Не включено // Поворот, когда пользователь изменяет rotate_x и rotate_y glRotatef (rotate_x, 1.0, 0.0, 0.0); glRotatef (rotate_y, 0,0, 1,0, 0,0); // Другие преобразования // glScalef (2.0, 2.0, 0.0); // Не входит // Разноцветная сторона - FRONT glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); // P1 красный glColor3f (0.0, 1.0, 0.0); glVertex3f (0,5, 0,5, -0,5); // P2 зеленый glColor3f (0.0, 0.0, 1.0); glVertex3f (-0,5, 0,5, -0,5); // P3 синий glColor3f (1.0, 0.0, 1.0); glVertex3f (-0,5, -0,5, -0,5); // P4 фиолетовый glEnd (); // Белая сторона - НАЗАД glBegin (GL_POLYGON); glColor3f (1.0, 1.0, 1.0); glVertex3f (0,5, -0,5, 0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glEnd (); // Фиолетовая сторона - ПРАВА glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 1.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, -0,5, 0,5); glEnd (); // Зеленая сторона - ЛЕВАЯ glBegin (GL_POLYGON); glColor3f (0,0, 1,0, 0,0); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); // Синяя сторона - TOP glBegin (GL_POLYGON); glColor3f (0,0, 0,0, 1,0); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, 0,5); glEnd (); // Красная сторона - НИЖНИЙ glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); glFlush (); glutSwapBuffers (); } // ----------------------------------------------- ----------- // Функция обратного вызова specialKeys () // ------------------------------ ---------------------------- void specialKeys (int key, int x, int y) {// Стрелка вправо - увеличить поворот на 5 градус if (key == GLUT_KEY_RIGHT) rotate_y + = 5; // Стрелка влево - уменьшить поворот на 5 градусов иначе if (key == GLUT_KEY_LEFT) rotate_y - = 5; иначе, если (ключ == GLUT_KEY_UP) rotate_x + = 5; иначе, если (клавиша == GLUT_KEY_DOWN) rotate_x - = 5; // Запросить обновление дисплея glutPostRedisplay (); } // ----------------------------------------------- ----------- // основная функция // ------------------------------- --------------------------- int main (int argc, char * argv ) {// Инициализируем GLUT и обрабатываем пользовательские параметры glutInit (& argc, argv); // Запрос окна истинного цвета с двойной буферизацией с Z-буфером glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Создаем окно glutCreateWindow ("Awesome Cube"); // Включить проверку глубины Z-буфера glEnable (GL_DEPTH_TEST); // Функции обратного вызова glutDisplayFunc (display); glutSpecialFunc (specialKeys); // Передаем управление событиям GLUT glutMainLoop (); // Возврат в ОС return 0; }