Скачиваний:
161
Добавлен:
22.06.2014
Размер:
1.3 Mб
Скачать

4.2 Практика

4.2.1 Общее задание

Создать OpenGL проект с именем «KGLab4» на основе шаблона проекта «Basis» (см. прил. Б). Включить рабочие файлы проекта «Basis» в новый проект с именем «KGLab4.сpp» «KGLab4.h». Установить любой цвет фона и заголовок окна, скомпоновать и запустить программу на выполнение.

Продемонстрировать работу теста отсечения и теста прозрачности в применении к объектам, созданным в лабораторной работе №3. (Задать собственный прямоугольник отсечения. Задать собственные значения альфа для некоторых частей составных фигур.)

5 Лабораторная работа №5 Трафареты и глубина

Цель работы: приобрести практический навык работы с тестами трафареты и глубина.

5.1 Теоретические положения

5.1.1 Трафарет

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

Тест трафарета позволяет отбросить фрагмент, базируясь на результате сравнения значения в буфере трафарета с задаваемым ссылочным значением. Выполнение теста разрешается и блокируется командами glEnable/glDisable с аргументом GL_STENCIL_TEST. Для проведения этого тестирования в OpenGL предусмотрены две команды, одна из которых отвечает за сравнение – glStencilFunc, а вторая позволяет определить действия, базирующиеся на результате проверки трафарета, – glStencilOp.

Рассмотрим каждую из них.

void glStencilFunc(

GLenum func,

Glint ref,

GLuint mask)

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

Таблица 5.1

Константа

Тест завершается положительно

GL_NEVER

GL_LESS

GL_EQUAL

GL_LEQUAL

GL_GREATER

GL_NOTEQUAL

GL_GEQUAL

GL_ALWAYS

Никогда

Если (ref&mask)<(stencil&mask)

Если (ref&mask)=(stencil&mask)

Если (ref&mask)<=(stencil&mask)

Если (ref&mask)>(stencil&mask)

Если (ref&mask)≠(stencil&mask)

Если (ref&mask)>=(stencil&mask)

Всегда

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

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

void glStencilOp(

GLenum fail,

GLenum zfail,

GLenum zpass)

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

Таблица 5.2

Константа

Действие

GL_KEEP

GL_ZERO

GL_REPLACE

GLINCR

GLDECR

GLINVERT

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

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

Установить значение буфера трафарета значению ref, определенному командой glStencilFunc

Увеличить текущее значение буфера трафарета и привести в соответствие с максимально допустимым значением 2m-1, где m – число плоскостей в буфере трафарета

Уменьшить текущее значение буфера трафарета и привести в соответствие с нулем

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

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

Предположим, что нужно «вырезать» в окружности прямоугольное окно, чтобы открыть доступ к находящемуся за ней изображению, аналогично тому, что изображено на рис 5.1.

Рис. 5.1 Трафарет

Каковы должны быть наши действия? Рассмотрим один из возможных вариантов.

Определить значение в буфере трафарета для фона, например, glClearStencil(0x01).

Нарисовать окружность, изменив для нее значение в буфере трафарета, например 0x02.

Определить прямоугольник «вырезки» , установив для него значение в буфере трафарета равным 0x01 – такое же, как у фона.

Нарисовать желаемый рисунок, определив в качестве параметров для успешного прохождения теста трафарета значение 0x01.

Таким образом, в буфере трафарета должно быть нарисовано что-то аналогичное рис. 5.2.

Рис. 5.2 Пример буфера трафарета

Фрагмент программы:

static void Int (void)

// Определяем цвет фона и создаем массивы вершин и цветов окружности

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

/* Это значение для фона */ glClearStencil(Oxl);

/* Определяем значение маски трафарета */ glStencilMask(OxFF);

}

static void CALLBACK DrawScene (GLenum mode)

// Разрешаем проведение теста трафарета для изображения

//в правой части окна

if (mode == GLJTRUE)

glEnable(GL_STENCIL_TEST);

// Определяем функцию и значения для сравнения; окружность рисуется всегда

glStencilFunc(GL_ALWAYS, 0x02, 0x02);

// Определяем действия, которые будут выполняться в случае положительного результата – второй и третий аргумены; первый нас не интересует, т.к. тест всегда проходит; в результате замены для окружности в буфере трафарета будет храниться значение 0x02 – значение второго аргумента предыдущей команды

glStencilOp(GL_KEEP, GL_REPLACE,GL_REPLACE) ;

// Воспроизводим окружность

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

// Важно только изменить для него значение в буфере трафарета на 0x01

glStencilFunc(GL_ALWAYS, 0x01, 0x01);

// Определяем область вырезки

glBegin(GL_QUADS);

glEnd();

//Еще раз меняем параметры теста; следующий объект будет рисоваться только в тех oбластях, для которых значение в буфере трафарета равно 0x01

glStencilFunc(GL_EQUAL, 1, 1);

// Рисуем ромб

glShadeHodel(GL_FLAT);

glBegin(GL_QUADS);

glEnd();

glShadeModel(GL_SMOOTH);

// Блокируем тест трафарета

glDisable(GL_STENCIL_TEST);

}

static void CALLBACK Draw(void)

{// Очищаем не только буфер цвета, но и буфер трафарета

glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

// Рисуем в левой части окна тест трафарета заблокирован

DrawScene(GL_FALSE);

// Рисуем в правой части окна тест трафарета разрешен

glcolor3f(0.5f, 0.0f, 0.5f);

DrawScene(GL TRUE);

}

Соседние файлы в папке Задание