|
Июн
19
|
Я и обещал в прошлом уроке, устав от примитивных белых объектов на экране, начнем добавлять к ним цвета (помните исходный шаблон Apple, который мы удалили?) Просьба отнестись к этому уроку крайне внимательно, поскольку некоторые из представленных здесь концепций позже пригодятся нам в наложении текстур (да-да, осталось совсем немного).
В OpenGL ES цвет можно задавать сплошной заливкой для целого объекта, а можно раскрашивать объект, добавляя к нему полутона (когда цвета спектра плавно переходят один в другой). Начнем с самого простого — раскрасим наши объекты в один цвет.
Смена цвета, как обычно, переводит OpenGL в определенное «состояние»: все последующие операции рисования будут выполняться данным цветом, даже если вызвать для “сброса” функцию “glLoadIdentity()” (а все потому, что она работает только с вершинами). Поэтому с помощью всего одной строки кода мы можем окрасить наши объекты в любой цвет — пока остановимся на синем.
Запустите Xcode и перейдите к методу “drawView“. После первого вызова “glLoadIdentity()” добавьте обращение к следующей функции GL:
1 2 | glLoadIdentity(); glColor4f(0.0, 0.0, 0.8, 1.0); |
Вызов функции “glColor4f()” сообщает OpenGL о необходимости рисовать (и заполнять) объекты определенным цветом — в данном случае синим. Ее параметры:
glColor4f( GLfloat red,
GLfloat green,
GLfloat blue,
GLfloat alpha);
В OpenGL ES цвета указываются именно с этими четырьмя параметрами (т.е., RGBA), вариантов с RGB-цветами здесь не предусмотрено. На случай, если кто-то еще не в курсе, сообщаю, что альфа — уровень прозрачности, варьирующийся от 1.0 (полностью непрозрачный) до 0.0 (полностью прозрачный).
Красный, зеленый и синий параметры — значения с плавающей запятой в диапазоне 0.0–1.0 (0.0 — нулевая интенсивность, 1.0 — полная интенсивность). Соответственно, белый цвет выглядит как (1.0, 1.0, 1.0, 1.0).
Добавив строку, щелкните на кнопке “Build and Go“. Объекты примут следующий вид:

Лучше, чем белый, но особого энтузиазма не вызывает. Психоделические цвета вращающегося квадрата Apple были интереснее — давайте, попробуем создать такие и мы.
Разноцветные объекты
Сделать объект разноцветным не так уж и сложно. Как и в случае с вершинами, понадобится массив, из которого OpenGL будет брать цвета. Каждый цвет в массиве цветов соответствует цвету вершины (точки) в массиве вершин объекта.
Предлагаю прояснить ситуацию, раскрасив квадрат. Ниже приведен код массива цветов, идущий вместе с массивом вершин:
1 2 3 4 5 6 7 8 9 10 11 12 13 | const GLfloat squareVertices[] = { -1.0, 1.0, 0.0, // Верхняя левая -1.0, -1.0, 0.0, // Нижняя левая 1.0, -1.0, 0.0, // Верхняя правая 1.0, 1.0, 0.0 // Нижняя правая }; const GLfloat squareColours[] = { 1.0, 0.0, 0.0, 1.0,// Красный — сверху слева — цвет для "squareVertices[0]" 0.0, 1.0, 0.0, 1.0, // Зеленый — снизу слева — для "squareVertices[1]" 0.0, 0.0, 1.0, 1.0, // Синий — снизу справа — для "squareVerticies[2]" 0.5, 0.5, 0.5, 1.0 // Серый — сверху справа — для "squareVerticies[3]" }; |
Надеюсь, теперь понятно, что каждый присвоенный цвет представляет собой вершину квадрата. Чтобы реализовать это на практике, понадобится дополнительный код для раскрашивания квадрата.
1 2 3 4 5 6 7 8 9 | glLoadIdentity(); glTranslatef(1.5, 0.0, -6.0); glRotatef(rota, 0.0, 0.0, -1.0); glVertexPointer(3, GL_FLOAT, 0, squareVertices); glEnableClientState(GL_VERTEX_ARRAY); glColorPointer(4, GL_FLOAT, 0, squareColours); // НОВОЕ glEnableClientState(GL_COLOR_ARRAY); // НОВОЕ glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_COLOR_ARRAY); // НОВОЕ |
Перед нами три новых строки кода. Разберем их поочередно:
1 | glColorPointer(4, GL_FLOAT, 0, squareColours); |
По сути это аналог функции, вызываемой для настройки массива координат вершин, с четырьмя параметрами:
- Размер: количество цветов в массиве.
- Формат данных: здесь мы использовали “GL_FLOAT“, поскольку массив вершин содержит числа с плавающей запятой. При указании цветов в формате 0-255 допустимы и байты.
- Шаг по индексу: напоминаю, что он сообщает OpenGL о необходимости пропускать определенное количество байт между значениями, если данные содержат постороннюю информацию.
- Массив точек: место хранения данных.
Обратите внимание на то, что в указании формата данных “GL_FLOAT” — параметр формата (перечень), сообщающий формат OpenGL; “GLfloat” — тип данных, декларирующий для OpenGL число с плавающей запятой.
Следовательно, функция сообщает OpenGL, где и в каком формате находятся данные. Однако, как и в случае с передающим OpenGL координаты объекта массивом координат вершин, OpenGL нужно сначала перевести в нужное “состояние”, чтобы при визуализации программа использовала наши цвета.
Запрос
1 | glEnableClientState(GL_COLOR_ARRAY); |
активирует нужное состояние OpenGL. Вместо передачи “GL_VERTEX_ARRAY” мы сообщаем OpenGL о наличии массива цветов в “GL_COLOR_ARRAY“.
Теперь осталось нарисовать квадрат, после чего отключить массив цветов. (Иначе нарисованный следующим треугольник будет раскрашен, как квадрат.)
Вызываем:
1 | glDisableClientState(GL_COLOR_ARRAY); |
В результате массив цветов исчезает из текущего состояния OpenGL. Если этого не сделать, первое обращение к методу “drawView” даст синий треугольник, а второе — задействует массив цветов для его раскраски. Поскольку количество вершин в массиве координат “(triangleVerticies[])” ограничено тремя, задействованными окажутся лишь три первых цвета.
После внесения изменений в “drawView“, т.е. добавив три перечисленные выше новых строки кода, щелкните на кнопке “Build and Go“, получив вот такой результат:

При желании можно отключить вращение (прокомментируйте запрос функции “glRotatef()“), чтобы увидеть, как соотносятся вершины квадрата из массива вершин с массивом цветов.
Полутона
Заметили, как в квадрате цвета плавно переходят из одного в другой? В OpenGL такой эффект носит название Shading. С полутонами работают сразу две модели: “GL_FLAT“ и “GL_SMOOTH“. Показанный выше результат дают применяемые по умолчанию тона “GL_SMOOTH“.
Чтобы увидеть разницу между моделями, в коде квадрата перед “glLoadIdentity()” вставьте следующую строку:
1 | glShadeModel(GL_FLAT); |
Функция “glShadeModel()” переводит OpenGL в плоскостной режим работы с полутонами, который сохранится, пока не будет указано иное. При желании откорректируйте метод “setupView“. После щелчка на кнопке “Build and Go” картина станет следующей:

Давайте разберемся в происходящем.
Треугольник визуализирован, как обычно. Поскольку цвет плоскостной, полутона к нарисованному треугольнику не применяются. В квадрате четко просматривается два треугольника, из которых OpenGL составил квадрат. Согласно выбранной модели заливки программа применила к каждому треугольнику цвета последних вершин: “squareColours[2]” (синий) и “squareColours[3]” (серый). Тем, кто не понял, почему в визуализации двух составляющих квадрат треугольников последним вершинам соответствуют именно эти цвета, рекомендую вернуться к уроку по рисованию квадрата.
Резюмируем: “GL_SMOOTH” — плавная обработка полутонами. При заливке квадрата OpenGL берет нужный цвет из массива “squareColours[]” для каждой вершины массива “squareVertices[]” и посредством интерполяции каждого пикселя квадрата между вершинами обеспечивает плавный переход цвета между ними. Другими словами, результатом становится представленный первым квадрат.
“GL_FLAT” использует цвет, указанный для последней вершины объекта, заполняя им весь примитив. Поскольку квадрат состоит из двух треугольников, он раскрашивается на две половинки.
Заключение
Надеюсь, урок был полезен. Думаю, что в качестве полутонов лучше оставить “GL_SMOOTH“, поскольку второй вариант больше смахивает на трехмерные ретро-игры времен C64. Поскольку “GL_SMOOTH” — вариант по умолчанию, активировать его не нужно.
Заметьте: рассмотренный при окрашивании вершин принцип применяется и при наложении текстур, поэтому мы к нему еще вернемся.

(6 голосов, средний: 4.83 из 5)
Последние комментарии
Подскажите пожалуйста… Вот...
Код не открывает страницы по простой причине -...