Как стать автором
Обновить

OpenGL ES: рисование базовых фигур (треугольники)

Время на прочтение6 мин
Количество просмотров27K
Автор оригинала: Simon Maurice
Базовые фигуры (примитивы) — основные элементы, из которых при рисовании выстраиваются сложные объекты. В OpenGL ES такими примитивами выступают объекты Point (Точка), Line (Линия), Triangle (Треугольник). Думаю, их названия говорят сами за себя.

В этом уроке мы будем анализировать код, на основании которого впоследствии можно будет создавать собственные проекты.

Примитив №1 — треугольники


Треугольники — самые сложные из базовых фигур, но они настолько удобны и полезны, что с них мы и начнем. Чтобы нарисовать треугольник, необходимо указать OpenGL три координаты трехмерного пространства — остальное программа сделает сама.

Первым делом создайте копию проекта из урока "OpenGL ES: настройка проекта в Xcode" или загрузите исходный код отсюда. Открыв проект в Xcode, перейдите к файлу "EAGLView.m" и найдите метод "drawView". Начинается настоящее волшебство!

Первым шагом зададим параметры треугольника. Сразу обращаю внимание на то, что мы будем работать с координатами двух типов: Model и World. Координаты Model относятся к отрисовываемому примитиву, а координаты World сообщают OpenGL о его местонахождении относительно зрителя (который в пространстве World всегда находится в точке (0.0, 0.0, 0.0)).

Итак, задаем координаты треугольника в пространстве Model через три трехмерные координаты (X, Y, Z):

const GLfloat triangleVertices[] = {
0.0, 1.0, -6.0,// Верхняя центральная точка треугольника
-1.0, -1.0, -6.0,// нижняя левая
1.0, -1.0, -6.0,// нижняя правая
};


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

Хотя наш урок посвящен технологии iPhone OpenGL ES, для новичков я вкратце остановлюсь на трехмерной системе координат. Взгляните на рисунок:

worldspace

Отвлечемся от моих художественных способностей и посмотрим, как выглядит пространство Model (или World). Представьте себе, что это компьютерный монитор, где X и Y — соответственно, горизонтальная и вертикальная оси, а Z — глубина. Центральная точка соответствует координатам (0.0, 0.0, 0.0).

Если теперь рассмотреть треугольник в применении к этим осям, то первая точка (0.0, 1.0, -6.0) будет его центром на оси Y, смещенная вверх на один пункт и на шесть пунктов в глубину экрана. Вторая координата находится на один пункт правее оси Y, ниже оси X (поскольку значение Y составляет -1.0) и на шесть пунктов в глубину экрана (-6.0). Точно по такому же принципу анализируется и третья координата.

Величина Z сделана отрицательной, чтобы отодвинуть объект назад и сделать его видимым (не забывайте, что «камера» находится в точке (0.0, 0.0, 0.0), поэтому в ином случае объект не пройдет тест OpenGL на глубину и не будет визуализирован).

Кое-кто сразу заметит: «Так ведь сказано было, что мы работаем с координатами Model, а не World!» Это действительно так, но когда мы доберемся до визуализации треугольника, OpenGL сразу поместит объект в точку (0.0, 0.0, 0.0). Поэтому уже сейчас отодвигаем его в глубину экрана, делая видимым. Позже, рассматривая трансформации (перемещение, вращение и пр.), что добиться такого результата можно, не прибегая к отрицательным величинам. А до тех пор оставим для координаты Z значение -6.0.

Код рисования


Теперь мы готовы описывать треугольник, сообщив OpenGL, где хранятся данные и как рисовать примитив. Для этого нам хватит нескольких строк кода. Вернитесь к методу "drawView" и реализуйте его, как показано ниже:

- (void)drawView {

const GLfloat triangleVertices[] = {
0.0, 1.0, -6.0, // Верхняя центральная точка треугольника
-1.0, -1.0, -6.0, // нижняя левая
1.0, -1.0, -6.0 // нижняя правая
};

[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);

// -- НАЧАЛО НОВОГО КОДА

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glVertexPointer(3, GL_FLOAT, 0, triangleVertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);

// -- КОНЕЦ НОВОГО КОДА

glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];

[self checkGLError:NO];
}


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

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


Эта строка очищает экран. Управляющие биты сообщают OpenGL о необходимости использовать черный цвет, заданный на прошлом уроке в методе "setupView", и очистить буфер глубины. Если буфер подключить, не сделав этого, сцена визуализирована не будет. Если буфер не подключать, в передаче glClear() сообщения GL_DEPTH_BUFFER_BIT необходимости нет.

Итак, мы очистили все, что прежде рисовалось в буфере (Не забыли о двойной буферизации? В одном буфере рисуем, другой отображаем).

glVertexPointer(3, GL_FLOAT, 0, triangleVertices);


Функция сообщает OpenGL о местонахождении данных и их формате. У нее четыре параметра, которые максимально просты:

1. Размер: число значений в каждой координате. В нашем случае их три (X, Y, Z). При рисовании двухмерных объектов без глубины (т.е. величины Z) будет указана цифра 2.
2. Тип данных: GL_FLOAT означает величину с плавающей запятой. При желании допустимы и целые числа, но в трехмерных пространствах без плавающих точек не обойтись.
3. Величина шага вычислений: сообщает OpenGL об игнорировании определенного количества байт между координатами. Пусть этот параметр пока не волнует — оставьте его равным нулю. Работать с ним будете при загрузке данных по вершинам из файла, формат которого предусматривает заполняющую пробелы информацию или данные по цвету, например, из 3D-приложения Blender.
4. Указатель данных — собственно, сами данные.

Итак, мы предложили OpenGL очистить буфер, указали данные для объекта и сообщили его формат. Настало время крайне важного сообщения.

glEnableClientState(GL_VERTEX_ARRAY);


OpenGL работает с состояниями. Это означает, что функции активируются и отключаются соответствующими командами. Выше мы применили команду "glEnable()", работающую с «серверным» режимом OpenGL. Команда "glEnableClientState()" включает «программный» режим (т.е. клиентское состояние). На текущий момент мы сообщили OpenGL, что данные по вершинам находятся в отдельном массиве и активировали функцию OpenGL для рисования вершины. Теоретически, вершина может быть массивом цвета (в этом случае стоит обратиться к "glEnableClientState(GL_COLOR_ARRAY)") или массивом текстурных координат при наложении текстур (хватит вздыхать! чтобы накладывать текстуры, нужно для начала освоить основы!).

По мере освоения OpenGL нам предстоит работа с разными клиентскими состояниями, поэтому время на разбор данной темы еще будет.

Настало время команды для визуализации треугольника:

glDrawArrays(GL_TRIANGLES, 0, 3);


При вызове данной функции OpenGL обрабатывает полученную из двух предыдущих функций информацию. На экране появится треугольник с белой заливкой (белый — цвет по умолчанию при рисовании). Треугольники — объекты с заливкой. Для рисования пустого треугольника понадобится иная техника.

Разбираем три аргумента данной функции:
1. Метод рисования: в данном случае "GL_TRIANGLES", название которого само по себе достаточно красноречиво. Возможность оценить потенциал первого аргумента нам представится позже, когда с помощью этой функции мы будем рисовать квадрат.
2. Первая вершина: наш массив состоит всего из трех точек. Мы хотим, чтобы OpenGL отталкивался от первой точки в массиве, указанной как ноль (стандартный доступ к массиву). Если бы в массиве вершин содержалось несколько примитивов, было бы уместным смещение. Подробнее об этом — в последующих уроках, где речь пойдет о создании сложных объектов. Пока пусть будет ноль.
3. Количество вершин: сообщает OpenGL, сколько в массиве рисуемых вершин. Для треугольника их, само собой, три, для квадрата — 4, для линии — 3 (и более), для точки — одна (и более при визуализации многочисленных точек).

После того, как код набран, а метод "drawView" приведен к указанному выше виду, кнопкой "Build and Go" запустите проект в симуляторе. Результат будет выглядеть примерно так, как и предполагалось — белый треугольник в центре экрана.

triangle

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

Для нескольких строк кода пояснений получилось немало, но, думаю, это того стоило. Надеюсь, что те, кому уже приходилось спотыкаться о «типовые» уроки по OpenGL, уже поняли разницу между OpenGL и OpenGL ES.

Исходный код к уроку можно скачать здесь.
Теги:
Хабы:
Всего голосов 31: ↑27 и ↓4+23
Комментарии6

Публикации

Истории

Работа

iOS разработчик
20 вакансий
Swift разработчик
27 вакансий

Ближайшие события