Мы рассмотрели все десять примитивов, имеющихся в нашем распоряжении. Код практических построений, включающих сотни и тысячи отдельных
примитивов, подчас чересчур громоздок, большая часть его в таких случаях — сотни и тысячи строк с вызовом команды glVertex.
Библиотека OpenGL располагает средством сокращения кода, базирующимся на использовании массивов вершин. В массиве вершин, т. e. массиве вещественных чисел, задаются координаты опорных вершин, по которым вызовом одной команды glDrawArrays строится последовательность примитивов заданного типа.
У команды glDrawArrays три аргумента: тип примитива и характеристики используемого массива.
Для использования этой функции надо, как минимум, задать массив вершин, по которым будет строиться множество примитивов. Ссылка на массив вершин создается командой glVertexPointer, также являющейся расширением стандарта. Помимо массива вершин, для украшения картинки будем также использовать массив цвета вершин, ссылка на который задается командой glColorPointer, тоже не входящей в стандарт. Прибавив окончание Ехт к именам этих команд, можно получить контекстную подсказку, по которой легко разобраться с их аргументами. Но, к сожалению, для использования массива вершин полученной информации недостаточно, необходимо еще использовать, как минимум, команду glEnableClientState, справку по которой уже невозможно получить никакими ухищрениями. Эта команда аналогична glEnable, но применяется только в контексте массивов вершин. У нее имеется парная команда — glDisableClientState, отключающая использование массива вершин.
В заголовочном файле opengl.pas, поставляемом с Delphi, отсутствуют прототипы команд, не входящих в стандарт OpenGL, a также отсутствует описание констант, используемых такими командами, что немного затруднит наше изучение этой библиотеки.
Массив с именем vertex содержит координаты четырех точек — углов квадрата, а в массиве цветов Colors содержатся соответствующие вершинам значения RGB:
Vertex : Array [0..3, 0..1] of GLFloat; Colors : Array [0..3, 0..2] of GLFloat;
Код рисования выглядит так:
glVertexPointer(2, GL_FLOAT, 0, @Vertex); // указатель на массив вершин glColorPointer(3, GL FLOAT, 0, @Colors); // указатель на массив цветов
glEnableClientState(GL_VERTEX_ARRAY); // массив вершин - включаем режим
glEnableClientState(GL_COLOR_ARRAY); // массив цветов — включаем режим
glDrawArrays(GL_POLYGON, 0, 4); // рисование множества полигонов
glDisableClientState(GL_COLOR_ARRAY); // выключаем режимы (в этом
glDisableClientState(GL_VERTEX_ARRAY); // примере не обязательно)
Значение первого аргумента команды glVertexPointer равно двум, поскольку вершины заданы указанием двух координат. To есть этот аргумент задает, по сколько вещественных чисел считывать для каждой точки.
Результат работы программы показан на рисунке
Для использования команд-расширений программу пришлось дополнить строками с описанием прототипов процедур:
procedure glVertexPointer (size: GLint; atype: GLenum;
stride: GLsizei; data: pointer); stdcall; external OpenGL32;
procedure glColorPointer (size: GLint; atype: GLenum; stride: GLsizei;
data: pointer); stdcall; external OpenGL32;
procedure glDrawArrays (mode: GLenum; first: GLint; count: GLsizei);
stdcall; external OpenGL32;
procedure glEnableClientState (aarray: GLenum); stdcall; external OpenGL32;
procedure glDisableClientState (aarray: GLenum); stdcall; external OpenGL32;
Здесь openGL32- константа, определяемая в модуле opengl.pas.
Потребовалось также задать значение констант, используемых этими процедурами:
const
GL_VERTEX_ARRAY = $8074; GL COLOR ARRAY = $8076;
Значения констант и информацию о типах аргументов процедур можно почерпнуть из заголовочных файлов сторонних разработчиков. Информация о команде glEnableClientstate взята из описания OpenGL фирмы SGI.
Первым аргументом glDrawArrays может быть любая константа, которую допускается использовать в glBegin.
В примере по массиву вершин строится множество полигонов вызовом команды
glDrawArrays(GL_POLYGON, 0, 4); // рисование множества полигонов
Эта команда является сокращением следующей последовательности команд
glBegin (GL_POLYGON);
glArrayElement(0) ;
glArrayElement(1);
glArrayElement(2);
glArrayElement(3) ;
glEnd;
Используемая здесь функция glArrayElement (также расширение стандарта) берет в качестве вершины примитива элемент массива с заданным индексом. Индекс, как видно из примера, начинается с нуля.Вы, возможно, задаетесь вопросом, почему в заголовочном файле, поставляемом с Delphi, отсутствуют прототипы процедур, хоть и не входящих в стандарт OpenGL, но документированных разработчиком библиотеки. Ответ на этот вопрос заключается, по-видимому, в том, что этот файл является трансляцией заголовочных файлов gl.h и glu.h, опубликованных SGI, и в него вошло только то, что документировано в этих файлах. Как явствует из заголовка файла, за основу положены файлы версии 1993 года.
Помимо массивов вершин и массива цветов вершин, имеется массив границ — аналог команды glEdgeFlag применительно к массивам вершин. В этом случае необходимо использовать команду glEdgeFlagPointer. Прибавив суффикс Ехт, вы можете получить справку по этой команде. В ней, в частности, говорится, что включение режима использования массива границ осуществляется так:
glEnable (GL_EDGE_FLAG_ARRAY_EXT);
Однако это указание, по-видимому, является ошибочным. Можно воспользоваться массивом флагов границ только с использованием следующего кода:
glEnableClientState(GL_EDGE_FLAG_ARRAY);
To же самое можно сказать по поводу аргументов команды.