q zfail — То же, но для случая, когда трафаретный тест (stencil test) прошел, а тест глубины — нет.
q zpass — То же, но для случая, когда оба теста прошли (или тест глубины выключен).
Все три параметра имеют тип перечисления и могут принимать одно из 6 значений:
GL_KEEP |
Оставить текущее значение |
GL_ZERO |
Обнулить значение в stencil buffer |
GL_REPLACE |
Установить значение ref в stencil buffer |
GL_INCR |
Увеличить текущее значение в stencil buffer |
GL_DECR |
Уменьшить текущее значение в stencil buffer |
GL_INVERT |
Побитово инвертировать текущее значение в stencil buffer |
Если трафаретный тест не прошел, то изображение (то есть значения буфера цвета и буфера глубины) не изменяются. При этом, однако могут произойти изменения в самом stencil buffer. Параметр fail как раз их и определяет. Другие два параметра glStencilOp определяют, что делать, если stencil test прошел. Теперь все решает тест глубины (прошел он или не прошел).
Логика использования трафарета не проста, она требует повышенного внимания, поэтому лучше обратиться к примеру. Прежде всего вставьте в функцию Init строку кода, которая задает начальное значение трафаретного буфера.
glClearStencil (0);
Далее в нашем примере будут использованы такие настройки этого буфера.
glColorMask (0, 0, 0, 0); // Set Color Mask
glEnable (GL_STENCIL_TEST);
glStencilFunc (GL_ALWAYS, 1, 1);
glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
Вызов glColorMask с нулями (а точнее, с FALSE) запрещает записывать в буфер кадра все три компоненты цвета. Это надо понимать как подготовку к заполнению stensil-буфера. Теперь все рисование пойдет не в буфер кадра, а в буфер трафарета. Вызов glEnable очевиден. Вызов glStencilOp с таким набором параметров означает, что в stencil-буфер попадет (см. GL_REPLACE) единица, если пройдет stencil test, а он пройдет всегда, благодаря установке GL_ALWAYS. Эти команды (все вместе) являются подготовкой к тому, что последует дальше. Следующие команды изобразят в буфере трафарета поверхность пола. Более точно, они лишь обозначат поверхность в буфере (единицами).
glDisable (GL_DEPTH_TEST);
DrawFloor(); // Draw the floor to the stencil buffer. We only want to mark it in the stencil buffer
glEnable (GL_DEPTH_TEST);
Финт с glDisable, glEnable позволяет использовать третий параметр функции glStencilOp. Итак поверхность пола обозначена в буфере трафарета. Далее надо создать отражение мяча. Оно должно располагаться в этой самой поверхности (только там и нигде более). Именно для этой цели и служит трафарет. Он отсечет все попытки отражения изобразиться где-либо еще (вне пределов пола). Эти попытки будут происходить, так как мяч и его отражение перемещается пользователем. Следующие команды создают отражение мяча.
glColorMask (1, 1, 1, 1);
glStencilFunc (GL_EQUAL, 1, 1); // We draw only where the stencil is 1 (i.e. where the floor was drawn)
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); // Don't change the stencil buffer
glPushMatrix();
glScalef (1,-1, 1); // Mirror Y Axis
glTranslatef (0, height, 0); // Position The Ball
glRotatef (angleX, 1, 0, 0);
glRotatef (angleY, 0, 1, 0);
DrawBall(); / Reflection of the ball
glPopMatrix();
glDisable (GL_STENCIL_TEST); // We don't need the stencil buffer any more
Вызов glColorMask с единицами (а точнее, с TRUE) вновь разрешает записывать в буфер кадра все три компоненты цвета. Это — подготовка к нормальному рисованию, а не заполнению stensil-буфера. Но это нормальное рисование будет происходить с учетом трафарета, так как он остался включенным. Команда glStencilFunc (GL_EQUAL, 1, 1); говорит OpenGL, что новые пикселы пройдут в буфер кадра только если они совпадут с трафаретом. Следующий вызов glStencilOp говорит о том, что сам буфер трафарета не будет изменяться.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.