≪
≫

РАБОТА С БУФЕРАМИ

За общепринятым понятием "буфер кадра" в OpenGL скрывается не один, а несколько буферов - цвета, трафарета, глубины и аккумулятора (накопления). Это разделение позволяет расширить функциональные возможности OpenGL. Рассмотрим механизмы работы некоторых буферов.

Буфер трафарета

Буфер трафарета предоставляет огромные возможности для творчества. С его помощью реализуются самые разнообразные эффекты, начиная от 66

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

Наложение трафарета разрешает или нет рисование на пиксельном уровне. В качестве трафарета может выступать любой графический примитив. При этом рисование осуществляется в плоскости трафарета. После чего этот буфер используется как маска для вывода графики на экран. Главный механизм работы с трафаретом базируется на тестах трафарета, которые сравнивают значения в буфере трафарета с заданным значением. Если тест проходит, то тестируемый пиксель помещается в буфер кадра для визуализации.

Сам тест разрешается или блокируется командами glEnable/glDisable с аргументом GL_STENCIL_TEST. Очищается буфер трафарета при помощи функции glClear с параметром GL_STENCIL_BUFFER_BIT.

Для проведения трафаретного тестирования предусмотрены команды: glStencilFunc, отвечающая за функцию сравнения, и glStencilOp, определяющая действие на базе проверки трафарета.

Рассмотрим эти команды подробнее:

void glStencilFunc (GLenum/ипс, int ref, GLuint mask)

Данная команда задает правило (параметром fund), по которому будет определяться результат сравнения значений, хранящихся в буфере трафаретов (stencil), с некоторым заданным через параметр ref Сравнение осуществляется по маске mask. Переменная func может принимать одно из следующих значений:

Константа

GL_NEVER GL.LESS GL_EQUAL GL_LEQUAL GLGREATER GLNOTEQEAL GL_GEQUAL GL ALWAYS

Тест ...

He проходит никогда

Проходит, если (ref & mask) < (stencil & mask) Проходит, если (ref & mask) = (stencil & mask) Проходит, если (ref& mask) < (stencil & mask) Проходит, если (ref & mask) > (stencil & mask) Проходит, если (ref & mask) f (stencil & mask) Проходит, если (ref & mask) > (stencil & mask) Проходит всегда

Параметр ref задает значение для сравнения и может принимать любое из диапазона [0, 2" - 1], где п - число битовых плоскостей в буфере трафаретов. Аргумент mask задает маску для значений ref и stencil.

По умолчанию тест трафарета заблокирован. В этом случае модификация буфера трафарета не может произойти и это означает положительный результат теста трафарета.

Команда glStencilOp предназначена для определения действий над пикселем буфера маски в случае положительного или отрицательного результата теста.

void glStencilOp (GLenum fail, GLenum 3/ail, GLenum zpass)

Аргумент fail задает действие в случае отрицательного результата теста, и может принимать следующие значения:

Константа

Действие

GLKEEP

Сохранить текущее значение в буфере трафарета

GL-ZERO

Установить значение буфера трафарета в ноль

GL_REPLACE

Заменить значение буфера трафарета на значение переменной ref, заданной командой glStencilOp

GL_INCR

Увеличить на единицу текущее значение буфера трафарета

GL_DECR

Уменьшить на единицу текущее значение буфера трафарета

GL_INVERT

Поразрядно инвертировать текущее значение трафарета

Параметры zfa.il и zpass определяют действия для отрицательного и положительного, соответственно, завершений теста глубины, которые будут выполнены в случае положительного результата выполнения теста трафарета. Для этих параметров допускаются те же символьные константы, что для параметра/i/z'/.

Рассмотрим простой пример использования буфера трафарета.

Пусть на фоне градиентно-закрашенного квадрата необходимо вывести зеленый треугольник с вырезанным окном в виде треугольника меньшего размера, через который можно видеть базовый квадрат. Квадрат расположен чуть дальше, чем остальные объекты. Рассмотрим поэтапно наши действия:

  • 1. Определяем значение буфера трафарета для фона, например - 1.
  • 2. Рисуем градиентно-закрашенный квадрат.
  • 3. Заполняем в буфере трафаретов треугольное "окно" значениями, например - 2.
  • 4. Выводим зеленый треугольник в тех местах, где значения в буфере трафарета не равны 2.

Рассмотрим фрагмент кода программы, выполняющий поставленную задачу. Комментарии подробно поясняют все выполняемые действия.

GLvoid DrawPrim()

{

II Значение, которым будет заполняться буфер стенсила при его очистке glClearStencil(l);

// Определяем, какие биты могут писаться в стенсил буфер

glStencilMask(OxFF);

// Очищаем все буферы

glClear( GL_COLOR_BUFFER_BIT I GL_STENCIL_BUFFER_BIT);

glBegin(GL_QUADS); // Рисуем градиентно-закрашенный квадрат

glColor3f( l,O,O);glVertex3f( 2.0f, 2.0f, -O.lf);

glColor3f( O,l,O);glVertex3f(-2.Of, 2.0f, -O.lf);

glColor3f( O,O,l);glVertex3f(-2.Of, -2.0f, -O.lf);

glColor3f( l,O,l);glVertex3f( 2.0f, -2.0f, -O.lf);

glEnd();

// Разрешаем проведение теста трафарета для треугольного "окна"

glEnable(GL_STENCIL_TEST);

// Определяем функцию и значение для сравнения,

И треугольник не рисуется

glStencilFunc(GL_NEVER, 2, 0);

// Заменяем значение буфера трафарета на значение 2 glStencilOp(GL_REPLACE, GL_KEEP, GLJKEEP);

glBegin(GLJPOLYGON); // Определяем область "окна"

glVertex3f( O.Of, l.Of, O.Of);

glVertex3f( l.Of, -l.Of, O.Of);

glVertex3f(-1.0f, -l.Of, O.Of);

glEnd();

// Изменяем параметры теста буфера трафарета;

// следующий объект будет рисоваться только в тех местах,

// для которых значение в буфере трафарета не равно 2

glStencilFunc(GL_NOTEQUAL, 2, 255);

glColor3f(0.0f, 1 .Of,O.Of); // Задаем зеленый цвет

glBegin(GL_POLYGON); И Рисуем треугольник

glVertex3f( O.Of, 1.6f, O.Of);

glVertex3f(-1.4f, -1.4f, O.Of);

glVertex3f( 1.4f, -1.4f, O.Of);

glEnd();

}

При работе с буфером трафарета необходимо аккуратно продумывать последовательность действий.

 
Посмотреть оригинал