OpenGL в Delphi

       

Теперь просверлены два отверстия, обратите внимание на их пересечения




Теперь в квадрате просверлены два отверстия, пересекающиеся друг с другом, причем области пересечения дырок заполнены материалом Параметры операций с буфером трафарета задаются один раз - при инициализации работы приложения:

glStencilFunc(GL_EQUAL, 0, 1);
// в следующей команде важны первый и третий аргументы
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
glEnable(GL_STENCIL_TEST); // разрешаем тест трафарета

Комбинируя значения последних двух аргументов команды glstencilFunc, вы можете получать самые различные эффекты при вырезке отверстий. Отверстие в площадке получается с помощью манипуляций с цветом:

glClear(GL_COLOR_BUFFER_BIT or GL_STENCIL_BUFFER_BIT);
glPushMatrix;
glPushMatrix;
glColor3f(1. 0, 0. 0, 0. 0); // сфера красного цвета
glTranslatef (45. 0, 40. 0, -150. 0);
gluSphere (qObj, 50. 0, 20, 20);
glPopMatrix;
If fRot then glRotatef(theta, 1. 0, 1. 0, 0. 0); // поворот площадки
glColorMask(False, False, False, False); // отключить работу с цветом
glPushMatrix;
// первая дырка
glTranslatef(45. 0, 45. 0, 0. 0);
gluDisk(qObj, 15. 0, 20. 0, 20, 20);
// вторая дырка
glTranslatef(20. 0, 20. 0, 0. 0);
gluDisk(qObj, 15. 0, 20. 0, 20, 20);
glPopMatrix;
glColorMask(True, True, True, True); // включить работу с цветом
glColor3f(1. 0, 1. 0, 0. 0); // задаем цвет желтым
// площадка
glBegin(GL_QUADS);
glNormal3f(0. 0, 0. 0, 1. 0);
glVertex3f(0. 0, 0. 0, 0. 0);
glVertex3f(100. 0, 0. 0, 0. 0);
glVertex3f(100. 0, 100. 0, 0. 0);
glVertex3f(0. 0, 100. 0, 0. 0);
glEnd;
glPopMatrix;

Смысл примера состоит в том, что для выделяемой области, т. e области отверстий, мы заносим в буфер кадра значение, соответствующее цвету фона Задание маски цвета из четырех отрицаний соответствует тому, что ни один компонент палитры цвета не будет записываться для области отверстий - отключается работа с буфером кадра Этот прием мы часто будем использовать.
Можно и не использовать буфер трафарета, а основываться только на буфе-Ре кадра и буфере глубины. Проект из подкаталога Ex35 содержит пример, функционирующий подобно предыдущему, но не использующий буфер шаблона.
Каждое отверстие рисуется два раза, чуть ниже и чуть выше площадки, но на время их воспроизведения отключается работа с буфером цвета:

glColorMask(False, False, False, False); // отключается работа с цветом
glPushMatrix;
// первая дырка
glTranslatef(45. 0, 45. 0, 0. 01); // над площадкой
gluDisk(qObj, 15. 0, 20. 0, 20, 20);
glTranslatef(0. 0, 0. 0, -0. 02); // под площадкой
gluDisk(qObj, 15. 0, 20. 0, 20, 20);
// вторая дырка
glTranslatef(20. 0, 20. 0, 0. 02); // над площадкой
gluDisk(qObj, 15. 0, 20. 0, 20, 20);
glTranslatef(0. 0, 0. 0, -0. 02); // под площадкой
gluDisk(qObj, 15. 0, 20. 0, 20, 20);
glPopMatrix;
glColorMask(True, True, True, True); // возвращается работа с цветом
glColor3f(1. 0, 1. 0, 0. 0);
// площадка желтого цвета
glBegin(GL_QUADS);
glNormal3f(0. 0, 0. 0, 1. 0);
glVertex3f(0. 0, 0. 0, 0. 0);
glVertex3f(100. 0, 0. 0, 0. 0);
glVertex3f(100. 0, 100. 0, 0. 0);
glVertex3f(0. 0, 100. 0, 0. 0);
glEnd;
glPopMatrix;

Отверстия приходится рисовать по два раза потому, что иначе через них местами проглядывает площадка.
Я уже однажды говорил об этом, но сейчас еще раз напомню в рассматриваемых примерах на сцене присутствует не больше пяти объектов, поэтому не заметно, насколько сильно тормозит приложение интенсивная работа с буферами Если требуется только прорезать отверстия в поверхностях, эффективнее самостоятельно разбить поверхность на отдельные зоны и нарисовать дырку подобно тому, как это делалось в примерах главы 2. В главе 5 мы рассмотрим еще один пример того, как создать дырявую поверхность.
Следующий пример, проект из подкаталога Ех30, относится к разряду классических, в работе над ним моя заслуга состоит только в переносе программы на Delphi.
Рисунок 4. 24 иллюстрирует работу приложения - на экране два тора, в середине экрана прорезано квадратное отверстие, сквозь которое проглядывает синяя сфера.



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