Помощь в учёбе, очень быстро...
Работаем вместе до победы

Работа с буфером трафарета

РефератПомощь в написанииУзнать стоимостьмоей работы

Еще одним буфером, поддерживаемым OpenGL, является буфер трафарета {stencil). Этот буфер для каждого пиксела окна хранит некоторое небольшое количество бит (обычно 8 бит). При выводе примитива мы можем задать тест, который должен выполняться для фрагментов, полученных при растеризации, и по результатам которого фрагмент может быть отброшен. Также мы можем задать правило изменения значения… Читать ещё >

Работа с буфером трафарета (реферат, курсовая, диплом, контрольная)

Еще одним буфером, поддерживаемым OpenGL, является буфер трафарета {stencil). Этот буфер для каждого пиксела окна хранит некоторое небольшое количество бит (обычно 8 бит). При выводе примитива мы можем задать тест, который должен выполняться для фрагментов, полученных при растеризации, и по результатам которого фрагмент может быть отброшен. Также мы можем задать правило изменения значения в буфере трафарета при выводе пиксела. Это оказывается довольно мощным и широко используемым инструментом.

Первое, что нужно для работы с буфером трафарета, — это указать его поддержку при вызове функции glutlnitDisplayMode:

glutlnitDisplayMode (GLUT_RGBA | GLUT_DEPTH |.

GLUT_STENCIL | GLUT_DOUBLE);

Также обратите внимание на необходимость очистки буфера трафарета наряду с другими буферами. Буферу трафарета в команде glClear соответствует значение GL_STENCIL_BUFFER_BIT.

Для задания теста, выполняемого над значениями в буфере трафарета, служит функция gIStencilFunc:

void gIStencilFunc (GLenum func, GLint ref, GLuint mask);

В этой функции параметр func задает операцию сравнения и принимает одно из следующих значений: GL_NEVER (тест никогда не выполнен); GL_ALWAYS (тест всегда выполнен); GL_LESS (тест выполнен, если (ref & mask) < (stencil & mask)); GL_LEQUAL (тест выполнен, если (ref & mask) (stencil & mask)); GL_GEQUAL (тест выполнен, если (ref & mask) >= (stencil & mask)); GL_EQUAL (тест выполнен, если (ref & mask) == (stencil & mask)); GL_NOTEQUAL (тест выполнен, если (ref & mask) ≠ (stencil & mask)). Здесь через stencil обозначено значение из буфера трафарета, соответствующее данному пикселу.

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

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

glEnable (GL_STENCIL_TEST);

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

void gIStenilOp (GLenum fail, GLenum zfail, GLenum pass);

Параметр fail задает, что нужно сделать со значением в буфере трафарета, когда тест трафарета не выполнен. Параметр zfail задает, что нужно сделать со значением в буфере трафарета, когда тест трафарета выполнен, но не выполнен тест глубины. И, наконец, параметр pass задает, что нужно сделать, когда оба теста выполнены.

Возможными значениями для всех этих параметров являются GL_KEEP (оставить текущее значение без изменений), GL_ ZERO (записать 0), GL_REPLACE (заменить значение на параметр ref из gIStencilFunc), GLJNCR (увеличить значение на единицу), GL_DECR (уменьшить значение на единицу) и GLJNVERT (побитово проинвертировать значение).

Одним из основных применений буфера трафарета является возможность пометить определенные пикселы на экране. Изучим одно из применений этой возможности — рендеринг отражения. Пусть у нас есть плоская грань, которая должна отражать сцену, причем здесь речь идет именно о «правдивом» отражении. Рассмотрим, как это можно сделать.

Представим сначала более простой случай: есть бесконечная зеркальная плоскость и есть камера (наблюдатель), смотрящая на сцену, и ее отражение в этой плоскости. Сначала мы выводим всю сцену, без зеркальной плоскости, затем нужно построить отражение сцены в этой плоскости.

Самый простой способ построения отражения — отразить каждый объект относительно зеркальной плоскости и вывести отраженные объекты. Однако это требует явного отражения каждого объекта. Как мы знаем, отражение объекта относительно плоскости — это аффинное преобразование, следовательно, его можно выразить как матрицу 4×4. Поэтому, вместо того чтобы явно отражать каждый объект, просто домножим модельно-видовую матрицу на матрицу отражения и повторно выведем все объекты сцены (после чего восстановим модельно-видовую матрицу). Все это можно выразить следующим фрагментом кода:

mirror = getMirrorMatrix (); gIMatrixMode (GL_MODELVIEW); gIPushMatrix (); drawScene ();

gIMultMatrixf (mirror.data ()); drawScene (); gIPopMatrix ();

Теперь рассмотрим случай зеркальной грани: все отличие от бесконечной плоскости заключается в том, что нам нужно ограничить отражение только видимыми пикселами, соответствующими зеркальной грани. Для этого сначала выведем зеркальную грань, изменяя при этом только буфер трафарета: для каждого пиксела, соответствующего видимой части зеркальной грани, запишем в буфер трафарета 1. Этого можно добиться с помощью следующего фрагмента кода:

// разрешаем тест трафарета glEnable (GL_STENCIL_TEST);

// тест трафарета всегда пройден, ref = 1 gIStencilFunc (GL.ALWAYS, 1,0);

// при успехе ref записывается в буфер трафарета gIStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);

// выводим зеркало drawMirrorPolygon ();

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

// строим матрицу отражения mat4 mirror = getMirrorMatrix ();

// тест трафарета пройден, только если значение // в буфере трафарета равно 1 gIStencilFunc (GL_EQUAL, 1, OxFFFFFFFF);

// не меняем значения в буфере трафарета gIStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);

// будем менять модельно-видовую матрицу glMatrixMode (GLJVIODELVIEW); gIPushMatrix (); drawScene О;

// домножаем модельно-видовую матрицу на матрицу // отражения.

gIMultMatrixf (mirror.data ());

// выводим отражение сцены drawScene ();

// восстанавливаем модельно-видовую матрицу gIPopMatrix ();

Заключительным шагом будет отключение теста трафарета:

gIDisable (GL_STENCIL_TEST);

Показать весь текст
Заполнить форму текущей работой