Основы программирования OpenGL в Borland С+Builder и Delphi

       

Полигоны


Теперь перейдём к плоским фигурам: треугольникам, четырёхугольникам и произвольным выпуклым многоугольникам. С ними можно делать всё то же, что и с линиями (только сглаживание включается и выключается процедурами glEnable/glDisable с параметром GL_POLYGON_SMOOTH), плюс ещё одна процедура: glPolygonMode(face, mode). Второй параметр – mode – указывает, как будет рисоваться полингон (по русски - многоугольник). Он может принимать значения GL_POINT(рисуются только точки), GL_LINE(только линии) или GL_FILL(заполненный полигон). А первый параметр – face – показывает, какой стороне полигона применяется режим mode: GL_FRONT(к лицевой), GL_BACK(к тыльной) или GL_FRONT_AND_BACK(к обеим).

Давайте нарисуем треугольник. Вот как будет выглядеть функция Draw:

С++

 void TForm1::Draw()

{

glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);



glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

glBegin(GL_TRIANGLES);

glColor3f(1,0,0);

glVertex2f(0,2);

glColor3f(0,1,0);

glVertex2f(8,9);

glColor3f(0,0,1);

glVertex2f(10,4);

glEnd();

SwapBuffers(ghDC);

}

Delphi

 procedure TForm1.Draw;

begin

glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);

glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

glBegin(GL_TRIANGLES);

glColor3f(1,0,0);

glVertex2f(0,2);

glColor3f(0,1,0);

glVertex2f(8,9);

glColor3f(0,0,1);

glVertex2f(10,4);

glEnd;

SwapBuffers(ghDC);

end;

Я уже говорил, что каждая вершина может иметь свой цвет, этим я здесь и воспользовался. И вот что получилось:

Каждой вершине указывать цвет совсем не обязательно. Если вы хотите нарисовать треугольник одного цвета, то этот цвет указывается один раз – перед рисованием самого примитива.

Забегая вперёд, скажу, что плавного перетекания цветов как на рисунке может и не быть, если перед рисованием вызвать процедуру glShadeModel(GL_FLAT), по умолчанию её параметр – GL_SMOOTH. Эта процедура указывает, сглаживать или нет углы между смежными полигонами. Вот картинки для иллюстрации её действия:

 

Раз уж я сказал о штриховке линий, то нужно сказать и о трафарете – штриховке для полигонов. Он включается командой glEnable(GL_POLYGON_STIPPLE). Также как и с линиями, трафарет задаётся массивом, который определяет битовую маску. Размер трафарета - 32x32 бита, т.е. размер массива будет 128 байт.

Мне было лень прописывать каждый из 128 байт маски по отдельности, и я сформировал её в цикле, и вот результат:

С++

 void TForm1::Draw()

{

glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);

// формируем маску

for(int k=0;k<16;k++)

for(int i=0;i<8;i++)

stip[k][i]:=k-i;

glEnable(GL_POLYGON_STIPPLE);

glPolygonStipple(@stip);

glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

glColor3f(1,0,0);

glBegin(GL_TRIANGLES);

glVertex2f(0,2);

glVertex2f(8,9);

glVertex2f(10,4);

glEnd();

SwapBuffers(ghDC);

}

Delphi

 procedure TForm1.Draw;

var

stip:array [1..16,1..8] of GLubyte;

i,k:byte;

begin

glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);

// формируем маску

for k:=1 to 16 do

for i:=1 to 8 do

stip[k][i]:=k-i;

glEnable(GL_POLYGON_STIPPLE);

glPolygonStipple(@stip);

glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

glColor3f(1,0,0);

glBegin(GL_TRIANGLES);

glVertex2f(0,2);

glVertex2f(8,9);

glVertex2f(10,4);

glEnd;

SwapBuffers(ghDC);

end;

Вот результат:

Вообще маска формируется один раз, поэтому, если вы перенесёте код её формирования в другое место (например в FormCreate), то программа будет работать быстрее.

Ещё хотелось бы сказать о массивах OpenGL. Этот метод позволяет хранить все вершины объекта в массиве, причем в этом массиве можно хранить не только координаты вершин, но и их атрибуты (иногда это бывает полезно). Но товарищи из Borland’а решили, что нам это не нужно и не объявили соответствующие процедуры и константы. Без этого легко можно обойтись, но всё-таки обидноL.



Содержание раздела