Сегодня мы поговорим о том, как рисовать примитивы средствами OpenGL.
Откроем пример прошлого урока, у нас есть 5 процедур, которые рисуют, точки, линии, треугольник, квадрат и полигон. Пожалуй, это и есть основные примитивы, которые используются в OpenGL. Итак, разберем процесс их создания.
Начало и конец рисования примитивов
Все примитивы в OpenGL задаются с помощью команд, которые расположены между командами glBegin и glEnd – начало и конец рисования примитивов.
procedure glBegin (mode: GLenum);
Процедура содержит параметр mode, который задает флаг примитива.
Параметр mode может содержать один из следующих флагов
- GL_POINTS – точки
- GL_LINES, GL_LINE_LOOP – линии
- GL_TRIANGLES, GL_LINE_STRIP, GL_TRIANGLE_FAN – треугольники
- GL_QUADS, GL_QUAD_STRIP – квадраты
- GL_POLYGON – полигоны
Команда glEnd не содержит параметров.
Команды рисования примитивов
Рисование примитивов в OpenGL осуществляется с помощью команд задания вершин: glVertex*. И команд задания их атрибутов: glColor* - цвета, glNormal* - нормали, glTexCoord* - текстурные координаты. Так как атрибуты glNormal* и glTexCoord* нам пока не нужны, остановимся на командах задания вершин и цветов.
Команды задания вершин
Команда glVertex задает координаты вершин и может принимать следующие виды
Для двухмерной системы координат
procedure glVertex2d (x,y: GLdouble);
procedure glVertex2dv (v: PGLdouble);
procedure glVertex2f (x,y: GLfloat);
procedure glVertex2fv (v: PGLfloat);
procedure glVertex2i (x,y: GLint);
procedure glVertex2iv (v: PGLint);
procedure glVertex2s (x,y: GLshort);
procedure glVertex2sv (v: PGLshort);
Для трехмерной системы координат
procedure glVertex3d (x,y,z: GLdouble);
procedure glVertex3dv (v: PGLdouble);
procedure glVertex3f (x,y,z: GLfloat);
procedure glVertex3fv (v: PGLfloat);
procedure glVertex3i (x,y,z: GLint);
procedure glVertex3iv (v: PGLint);
procedure glVertex3s (x,y,z: GLshort);
procedure glVertex3sv (v: PGLshort);
Для четырехмерной системы координат
procedure glVertex4d (x,y,z,w: GLdouble);
procedure glVertex4dv (v: PGLdouble);
procedure glVertex4f (x,y,z,w: GLfloat);
procedure glVertex4fv (v: PGLfloat);
procedure glVertex4i (x,y,z,w: GLint);
procedure glVertex4iv (v: PGLint);
procedure glVertex4s (x,y,z,w: GLshort);
procedure glVertex4sv (v: PGLshort);
Все эти команды задают координаты вершин в различной вариации, в зависимости от числа после glVertex и типов данных параметров. Если в команде после glVertex стоит число 2 то команда задает координаты X и Y вершины. Если число 3, то X, Y и Z. Если 4, то X, Y, Z, W. Если в конце стоит символ v, то он означает векторную команду. То есть, параметр задается с помощью указателя на 2, 3 или 4 координаты, которые могут храниться, например, в одномерном массиве.
Но, не смотря на разнообразие команд все координаты, в конечном итоге, будут преобразованы OpenGL к четырехмерной системе.
Скажем, если вы задаете вершины с помощью glVertex2*, то все Z координаты будут равны нулю, а все координаты W будут равны единице. То же самое будет с координатой W при использовании команд glVertex3*.
Команды установки цвета вершин
Команда glColor может принимать следующие виды
Режим RGB
procedure glColor3b (red, green, blue: GLbyte);
procedure glColor3bv (v: PGLByte);
procedure glColor3d (red, green, blue: GLdouble);
procedure glColor3dv (v: PGLdouble);
procedure glColor3f (red, green, blue: GLfloat);
procedure glColor3fv (v: PGLfloat);
procedure glColor3i (red, green, blue: GLint);
procedure glColor3iv (v: PGLint);
procedure glColor3s (red, green, blue: GLshort);
procedure glColor3sv (v: PGLshort);
procedure glColor3ub (red, green, blue: GLubyte);
procedure glColor3ubv (v: PGLubyte);
procedure glColor3ui (red, green, blue: GLuint);
procedure glColor3uiv (v: PGLuint);
procedure glColor3us (red, green, blue: GLushort);
procedure glColor3usv (v: PGLushort);
Режим RGBA
procedure glColor4b (red, green, blue, alpha: GLbyte);
procedure glColor4bv (v: PGLbyte);
procedure glColor4d (red, green, blue, alpha: GLdouble);
procedure glColor4dv (v: PGLdouble);
procedure glColor4f (red, green, blue, alpha: GLfloat);
procedure glColor4fv (v: PGLfloat);
procedure glColor4i (red, green, blue, alpha: GLint);
procedure glColor4iv (v: PGLint);
procedure glColor4s (red, green, blue, alpha: GLshort);
procedure glColor4sv (v: PGLshort);
procedure glColor4ub (red, green, blue, alpha: GLubyte);
procedure glColor4ubv (v: PGLubyte);
procedure glColor4ui (red, green, blue, alpha: GLuint);
procedure glColor4uiv (v: PGLuint);
procedure glColor4us (red, green, blue, alpha: GLushort);
Как и в случае с командами вершин все цвета задаются в зависимости от типов параметров glColor*. Тройка после glColor означает, что команда имеет 3 параметра, red, green и blue (красный, зеленый и синий). Четверка – red, green, blue и alpha (красный, зеленый, синий и альфа), соответственно. Символ v в конце означает векторный тип данных (указатель на 3 или 4 параметра). Команда glColor4* имеет смысл только тогда, когда включен режим прозрачности.
Не зависимо от того, как мы задаем цвет все параметры будут преобразованы OpenGL в, красный, зеленый, синий и альфа каналы. При указании цвета с помощью команд glColor3* альфа будет равно единице.
Рассмотрим следующий пример
glColor3ub(255, 0, 0);
glColor3ub($FF, $00, $00);
glColor3f(1, 0, 0);
Все строки задают один и то же красный цвет разными способами.
В первой строке цвет задан с помощью десятичных чисел, размером в 1 байт. Во второй строке используется та же команда, только цвет задан с помощью шеснадцатиричных чисел. В третьей стоке цвет задан с помощью чисел с плавающей точкой. В данной команде цвет задается с помощью трех параметров, каждый из которых должен лежать в пределах от 0 до 1.
Аналогичным способом можно задать синий и зеленый цвета
glColor3ub(0, 255, 0);
glColor3ub($00, $FF, $00);
glColor3f(0, 1, 0);
glColor3ub(0, 0, 255);
glColor3ub($00, $00, $FF);
glColor3f(0, 0, 1);
Чтобы задать другие цвета следует комбинировать red, green и blue.
А сейчас вернемся к примеру прошлого урока. Цвета вершин там заданы с помощью типизированных констант.
CL_RED: Integer = $0000FF; // Красный
CL_GREEN: Integer = $00FF00; // Зеленый
CL_BLUE: Integer = $FF0000; // Синий
CL_YELLOW: Integer = $00FFFF; // Желтый
Чтобы задать цвет достаточно вызвать команду glColor3ubv с указателем на нужную константу. Например
glColor3ubv(@CL_YELLOW);
Данный способ является достаточно удобным и наглядно демонстрирует установку цвета.
Порядок указания вершин. Направление граней
В OpenGL все вершины должны задаваться в определенном направлении, особенно если вы рисуете плоские примитивы. Существует два направления по часовой стрелке и против часовой стрелки. По умолчанию в OpenGL принято направление против часовой стрелки. Это значит, что все грани, нарисованные против часовой стрелки, будут наружными. Грани, которые будут нарисованы по часовой стрелке будут считаться внутренними и могут отсекаться.
Для указания направления граней существует команда glFrontFace
procedure glFrontFace (mode: GLenum);
Где параметр mode может принимать значения: GL_CCW – ориентация против часовой стрелки и GL_CW – ориентация по часовой стрелке.
Если вершины примитивов у вас заданы по часовой стрелке, то следует вызвать команду glFrontFace с параметром GL_CW.
Рисование точек
Рассмотрим процедуру Points
procedure TForm1.Points;
begin
glBegin(GL_POINTS);
glColor3ubv(@CL_RED);
glVertex2f(-1, -1);
glColor3ubv(@CL_GREEN);
glVertex2f(1, -1);
glColor3ubv(@CL_BLUE);
glVertex2f(1, 1);
glColor3ubv(@CL_YELLOW);
glVertex2f(-1, 1);
glEnd;
end;
Здесь, между командами glBegin и glEnd вызывается 4 команды glVertex2f, которые и указывают точки. Команда glBegin с параметром GL_POINTS включает рисование точек. Перед указанием каждой вершины (glVertex2f) указаны цвета этих вершин, (команда glColor3ubv). В результате, у нас получилось 4 точки, закрашенные в, красный, зеленый, синий и желтый цвета (см. рисунок).
Рисование линий
Рассмотрим процедуру Lines
procedure TForm1.Lines;
begin
glBegin(GL_LINES);
glColor3ubv(@CL_RED);
glVertex2f(-1, -1);
glVertex2f(1, -1); glColor3ubv(@CL_GREEN);
glVertex2f(1, -1);
glVertex2f(1, 1); glColor3ubv(@CL_BLUE);
glVertex2f(1, 1);
glVertex2f(-1, 1); glColor3ubv(@CL_YELLOW);
glVertex2f(-1, 1);
glVertex2f(-1, -1); glEnd;
end;
Команда glBegin с параметром GL_LINES включает рисование линий. Для рисования линии нужно указать 2 вершины. Но можно указать и большее количество. Тогда OpenGL нарисует n линий подряд. Наша же процедура рисует 4 линии, закрашенные в красный, синий, зеленый и желтый цвета соответственно (см. рисунок).
Рисование треугольников
Рассмотрим процедуру Triangle
procedure TForm1.Triangle; begin
glBegin(GL_TRIANGLES);
glColor3ubv(@CL_RED);
glVertex2f(-1, -1);
glColor3ubv(@CL_GREEN);
glVertex2f(1, -1);
glColor3ubv(@CL_BLUE);
glVertex2f(0, 1);
glEnd;
end;
Для включения рисования треугольников мы вызываем команду glBegin с параметром GL_TRIANGLES. Рисуем треугольник с помощью трех команд glVertex2f, которые задают его вершины. Если вам нужно нарисовать 2 или более треугольников, то вы можете указать все вершины подряд, как в случае с линиями. Обратите внимание на цвета вершин треугольника. Перед указанием каждой вершины (glVertex2f) мы вызываем glColor3ubv каждый раз с новым цветом. В результате у нас получается треугольник с вершинами, которые закрашены в, красный, зеленый и синий цвета, плавно перетекающие друг в друга (см. рисунок).
Данный способ заливки может применяться ко всем плоским примитивам, а также к линиям.
Рисование квадратов
Рассмотрим процедуру Quad
procedure TForm1.Quad; begin
glBegin(GL_QUADS);
glColor3ubv(@CL_RED);
glVertex2f(-1, -1);
glColor3ubv(@CL_GREEN);
glVertex2f(1, -1);
glColor3ubv(@CL_BLUE);
glVertex2f(1, 1);
glColor3ubv(@CL_YELLOW);
glVertex2f(-1, 1); glEnd;
end;
Чтобы начать рисование квадратов вызываем glBegin с параметром GL_QUADS. Рисование квадратов почти ничем не отличается от рисования треугольников, только вместо трех здесь четыре вершины. И, также, как в случае с треугольником мы можем нарисовать более одного квадрата между glBegin и glEnd.
Рисование полигонов
Рассмотрим процедуру Polygon
procedure TForm1.Polygon; begin
glBegin(GL_POLYGON);
glColor3ubv(@CL_RED);
glVertex2f(0.586, -0.81);
glColor3ubv(@CL_GREEN);
glVertex2f(0.948, 0.31);
glColor3ubv(@CL_BLUE);
glVertex2f(0.0, 1.0);
glColor3ubv(@CL_YELLOW);
glVertex2f(-0.948, 0.31);
glColor3ubv(@CL_GREEN);
glVertex2f(-0.58, -0.81); glEnd;
end;
Для рисования полигона вызываем команду glBegin с параметром GL_POLYGON. В отличии от всех вышеперечисленных примитивов, здесь между glBegin и glEnd, можно нарисовать только один полигон. Рисовать можно от 3 до n вершин, что дает возможность рисовать более сложные формы. Наш же пример рисует пятиугольник, с вершинами, закрашенными в разные цвета.
Следует отметить, что OpenGL рисует только выпуклые полигоны. Это значит, что отдельные вершины не должны заходить за соседние. Таким образом, попытка нарисовать, например, пятиконечную звезду с помощью полигона не приведет к корректному результату.
Если вам нужно раскрасить один либо несколько примитивов одним цветом, то вы можете вызвать команду glColor, с нужными параметрами, всего один раз и все последующие вершины/примитивы будут раскрашены этим цветом.
|