Top.Mail.Ru

Уроки OpenGL. Часть 3. 2D-фигуры и массивы вершин.

Как и обещал в конце второго урока (ссылка), сегодняшняя статья будет посвящена построению 2D-примитивов в OpenGL при помощи массивов вершин. Поставим такую задачу - реализовать все то, что мы сделали в прошлый раз, но только без использования функций glBegin() / glEnd().

Итак, для решения поставленной задачи нам понадобится создать три массива:

  • массив вершин
  • массив индексов
  • массив цветов

Но для начала разберемся что это такое и зачем вообще эти массивы нужны.

В массивы вершин мы заносим декартовы координаты вершин фигуры, которую мы собираемся нарисовать. С этим все ясно. Но мало знать координаты, необходимо еще определить, в какой последовательности эти вершины нужно соединять линиями. И для этого как раз и нужен массив индексов вершин. Ну а с массивом цветов и так понятно, там мы будем задавать цвета вершин нашей 2D-фигуры. Сейчас напишем небольшой пример, и все сразу станет наглядно видно.

Итак, объявляем массивы:

GLfloat triangleVertexArray[3][3];
GLfloat triangleColorArray[3][3];
GLubyte triangleIndexArray[1][3];

У нашего треугольника три вершины, а у каждой вершины по три координаты, следовательно двумерный массив вершин должен иметь размер - 3 * 3. Аналогично с массивом цветов - три вершины по три составляющие цвета на каждую (RGB). Треугольник у нас будет всего один, поэтому triangleIndexArray имеет размер - 1 * 3. Теперь заполним их данными:

triangleVertexArray[0][0] = 0.0;
triangleVertexArray[0][1] = 0.0;
triangleVertexArray[0][2] = 0.0;

triangleVertexArray[1][0] = 1.0;
triangleVertexArray[1][1] = 1.0;
triangleVertexArray[1][2] = 0.0;

triangleVertexArray[2][0] = 1.0;
triangleVertexArray[2][1] = 0.0;
triangleVertexArray[2][2] = 0.0;

triangleColorArray[0][0] = 0.25;
triangleColorArray[0][1] = 0.87;
triangleColorArray[0][2] = 0.81;

triangleColorArray[1][0] = 0.25;
triangleColorArray[1][1] = 0.87;
triangleColorArray[1][2] = 0.81;

triangleColorArray[2][0] = 0.25;
triangleColorArray[2][1] = 0.87;
triangleColorArray[2][2] = 0.81;

triangleIndexArray[0][0] = 0;
triangleIndexArray[0][1] = 1;
triangleIndexArray[0][2] = 2;

glVertexPointer(3, GL_FLOAT, 0, triangleVertexArray);
glColorPointer(3, GL_FLOAT, 0, triangleColorArray);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, triangleIndexArray);

Задаем все координаты вершин и цвет (цвет треугольника у нас будет однородным, так что все вершины должны иметь одинаковый цвет). В массив индексов просто заносим последовательные номера вершин. С исходными данными на этом все. Двигаемся дальше!

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

Функция glVertexPointer() делает активным созданный массив вершин. Первый параметр функции - количество координат на каждую вершину, у нас их три (x, y, z), хотя строго говоря в нашем примере можно было обойтись и двумя координатами (мы пока работаем в 2D-пространстве). Второй параметр - тип данных, сохраненных в массиве. Третий - определяет шаг (в байтах) между данными с координатами для вершин, у нас данные идут плотно друг за другом, поэтому передаем в функцию аргумент 0. Ну и последний, четвертый, параметр - собственно наш массив вершин.

Полностью аналогичные параметры и у функции glColorPointer().

И, наконец, третья функция - glDrawElements(). В качестве аргументов мы передаем тип рисуемой фигуры, количество элементов в массиве индексов, тип данных и сам массив.

Казалось бы на этом все, но нет, необходимо еще активировать массивы вершин и цветов. Для этого в функции initializeGL() вызовем:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

Напоминаю, что в прошлых статьях курса по OpenGL мы уже создали пустой проект, а потом заполнили его всем необходимым, поэтому в сегодняшней статье я буду комментировать только то, что касается нашей сегодняшней темы. Подразумевается, что все нужное из проекта прошлой статьи перенесено и в этот новый проект. Собираем проект, запускаем и видим:

OpenGL 2D-объекты.

Треугольник на месте, давайте двигаться дальше. Отрисовка одного треугольника на самом деле не позволяет нам в полной мере почувствовать, как используется массив индексов вершин, поэтому давайте нарисуем следующее:

Массивы вершин в OpenGL.

У нас имеется 6 вершин и 3 треугольника. Сразу же меняем размеры массивов:

GLfloat triangleVertexArray[6][3];
GLfloat triangleColorArray[6][3];
GLubyte triangleIndexArray[3][3];

Забиваем координаты вершин, а также цвета. Первоначальные три вершины (0, 1 и 2) оставим прежнего цвета, вершина 3 у нас будет красная, а вершины 4 и 5 - зеленые:

triangleVertexArray[0][0] = 0.0;
triangleVertexArray[0][1] = 0.0;
triangleVertexArray[0][2] = 0.0;

triangleVertexArray[1][0] = 1.0;
triangleVertexArray[1][1] = 1.0;
triangleVertexArray[1][2] = 0.0;

triangleVertexArray[2][0] = 1.0;
triangleVertexArray[2][1] = 0.0;
triangleVertexArray[2][2] = 0.0;

triangleVertexArray[3][0] = 0.0;
triangleVertexArray[3][1] = 1.0;
triangleVertexArray[3][2] = 0.0;

triangleVertexArray[4][0] = 0.75;
triangleVertexArray[4][1] = 0.75;
triangleVertexArray[4][2] = 0.0;

triangleVertexArray[5][0] = 0.25;
triangleVertexArray[5][1] = 0.25;
triangleVertexArray[5][2] = 0.0;

triangleColorArray[0][0] = 0.25;
triangleColorArray[0][1] = 0.87;
triangleColorArray[0][2] = 0.81;

triangleColorArray[1][0] = 0.25;
triangleColorArray[1][1] = 0.87;
triangleColorArray[1][2] = 0.81;

triangleColorArray[2][0] = 0.25;
triangleColorArray[2][1] = 0.87;
triangleColorArray[2][2] = 0.81;

triangleColorArray[3][0] = 1.0;
triangleColorArray[3][1] = 0.0;
triangleColorArray[3][2] = 0.0;

triangleColorArray[4][0] = 0.0;
triangleColorArray[4][1] = 1.0;
triangleColorArray[4][2] = 0.0;

triangleColorArray[5][0] = 0.0;
triangleColorArray[5][1] = 1.0;
triangleColorArray[5][2] = 0.0;

Теперь самое интересное - массив индексов вершин. Необходимо определить, какие именно вершины участвуют при создании наших трех треугольников. Итак:

  • Первый треугольник - вершины 0, 1, 2
  • Второй треугольник - вершины 0, 3, 5
  • Третий треугольник - вершины 1, 3, 4

Так и задаем в массиве индексов, а заодно немного корректируем аргументы функций:

triangleIndexArray[0][0] = 0;
triangleIndexArray[0][1] = 1;
triangleIndexArray[0][2] = 2;

triangleIndexArray[1][0] = 0;
triangleIndexArray[1][1] = 3;
triangleIndexArray[1][2] = 5;

triangleIndexArray[2][0] = 1;
triangleIndexArray[2][1] = 3;
triangleIndexArray[2][2] = 4;

glVertexPointer(3, GL_FLOAT, 0, triangleVertexArray);
glColorPointer(3, GL_FLOAT, 0, triangleColorArray);
glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_BYTE, triangleIndexArray);

Запускаем программу и видим результат, абсолютно совпадающий с нашим заданием ) Значит все сделано правильно, и сегодняшнюю статью на этом заканчиваем, в ближайших уроках по OpenGL начнем строить объемные 3D фигуры и разберемся с текстурами, оставайтесь на связи!

Подписаться
Уведомить о
guest

3 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
Александр
Александр
4 лет назад

Лучшее объяснение этих glмассивов в рунете, СПАСИБО!!!))))

Владимир
Владимир
3 лет назад

Добрый день.
Не раз читал, что использование связки glBegin() / glEnd() - это вроде как устаревший стиль написания. И еще вроде бы это работает несколько медленнее. Здесь увидел работу с массивами вершин индексов и цветов. Но есть же еще функции glNewList() / glEndList() / glCallList(). В какой-то степени это похоже на что-то среднее между первым и вторым вариантом? Или я ошибаюсь? Можно ли как-то сравнить скорость исполнения кода отрисовки с помощью этих функций и с помощью массивов вершин/индексов?

3
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x