- •1. Основы программирования 3d графики
- •1.1. Возможности OpenGl
- •1.2. Основные типы данных OpenGl
- •1.3. Рисование геометрических объектов
- •1.3.1. Работа с буферами и задание цвета объектов
- •1.3.2. Задание графических примитивов
- •1.3.3. Рисование точек, линий и многоугольников
- •1.5. Получение проекций
- •1.3.4. Трехмерные фигуры
- •1.4. Преобразование объектов в пространстве
- •1.6. Задание моделей закрашивания
- •1.7. Освещение
- •1.8. Полупрозрачность
- •1.9. Наложение текстуры
1.3. Рисование геометрических объектов
1.3.1. Работа с буферами и задание цвета объектов
OpenGL содержит внутри себя несколько различных буферов. Среди них фрейм буфер (где строится изображение), z-буфер, служащий для удаления невидимых поверхностей, буфер трафарета и аккумулирующий буфер. Для очистки внутренних буферов служит процедура glClear(GLbitfield mask), очищающая буферы, заданные переменной mask. Параметр mask является комбинацией следующих констант:
GL_COLOR_BUFFER_BIT – очистить буфер изображения (фреймбуфер);
GL_DEPTH_BUFFER_BIT – очистить z-буфер;
GL_ACCUM_BUFFER_BIT – очистить аккумулирующий буфер;
GL_STENCIL_BUFFER_BIT – очистить буфер трафарета.
Цвет, которым очищается буфер изображения, задаётся процедурой glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha). Значение, записываемое в z-буфер, при очистке задаётся процедурой glClearDepth(GLfloat depth). Значение, записываемое в буфер трафарета, при очистке задаётся процедурой glClearStencil(GLint s). Цвет, записываемый в аккумулирующий буфер, при очистке задаётся процедурой glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha).
Сама команда glClear очищает одновременно все заданные буферы, заполняя их соответствующими значениями.
Для задания цвета объекта служит процедура:
glColor{3 4}{b s i f d ub us ui}[v](TYPE red, …).
Цифра 3 или 4 указывает на количество требуемых аргументов, а буква, следующая за цифрой, показывает тип аргументов. Например, в процедуру glColor3i будут переданы три параметра целого типа. Если значение параметра не задано, то оно автоматически полагается равным единице. Версии процедуры glColor, где параметры являются переменными с плавающей точкой, автоматически обрезают переданные значения в отрезок [0, 1].
Процедура glFlush() вызывает немедленное рисование ранее переданных команд. При этом ожидания завершения всех ранее переданных команд не происходит. С другой стороны, команда glFinish() ожидает, пока не будут завершены все ранее переданные команды.
Если нужно включить удаление невидимых поверхностей методом zбуфера, то z-буфер необходимо очистить и передать команду glEnable(GL_DEPTH_TEST). Команду glEnable() можно выполнить только один раз при инициализации системных переменных OpenGL. Очистку z-буфера необходимо производить перед началом построения очередного кадра изображения.
1.3.2. Задание графических примитивов
Все геометрические примитивы в OpenGL задаются вершинами (набором чисел, определяющих их координаты в пространстве).
OpenGL работает с однородными координатами (x, y, z, w). Если координата z не задана, то она считается равной нулю. Если координата w не задана, то она считается равной единице.
Под линией в OpenGL подразумевается отрезок, заданный своими начальной и конечной вершинами.
Под гранью (многоугольником) в OpenGL подразумевается замкнутый выпуклый многоугольник с несамопересекающейся границей.
Все геометрические объекты в OpenGL задаются посредством вершин, а сами вершины задаются процедурой:
glVertex{2 3 4}{s i f d}[v](TYPE x, …),
где реальное количество параметров определяется первым суффиксом (2, 3 или 4), а суффикс v означает, что в качестве единственного аргумента выступает массив, содержащий необходимое количество координат. Например:
glVertex2s(1, 2);
glVertex3f(2.3, 1.5, 0.2);
GLdouble vect[] = {1.0, 2.0, 3.0, 4.0};
glVertex4dv(vect);
Для задания геометрических примитивов необходимо как-то выделить набор вершин, определяющих этот объект. Для этого служат процедуры glBegin() и glEnd(). Процедура glBegin(GLenum mode) обозначает начало списка вершин, описывающих геометрический примитив. Тип примитива задаётся параметром mode, который принимает одно из следующих значений:
GL_POINTS – набор отдельных точек;
GL_LINES – пары вершин, задающих отдельные точки;
GL_LINE_STRIP – незамкнутая ломаная;
GL_LINE_LOOP – замкнутая ломаная;
GL_POLYGON – простой выпуклый многоугольник;
GL_TRIANGLES – тройки вершин, интерпретируемые как вершины отдельных треугольников;
GL_TRIANGLE_STRIP – связанная полоса треугольников;
GL_TRIANGLE_FAN – веер треугольников;
GL_QUADS – четвёрки вершин, задающие выпуклые четырёхугольники;
GL_QUAD_STRIP – полоса четырёхугольников.
Процедура glEnd() отмечает конец списка вершин. Между командами glBegin() и glEnd() могут находится команды задания различных атрибутов вершин glVertex(), glColor(), glNormal(), glCallList(), glCallLists(), glTexCoord(), glEdgeFlag(), glMaterial(). Между командами glBegin() и glEnd() все остальные команды OpenGL недопустимы и приводят к возникновению ошибок.
Рассмотрим в качестве примера задание окружности:
glBegin(GL_LINE_LOOP);
for (int i = 0; I < N; i++)
{
float angle = 2 * M_PI * i / N;
glVertex2f(cos(angle), sin(angle));
}
glEnd();
Хотя многие команды могут находится между glBegin() и glEnd(), вершины генерируются при вызове glVertex(). В момент вызова glVertex() OpenGL присваивает создаваемой вершине текущий цвет, координаты текстуры, вектор нормали и т. д. Изначально вектор нормали полагается равным (0, 0, 1), цвет полагается равным (1, 1, 1, 1), координаты текстуры полагаются равными нулю.
