Добавление к вашей игре отражающих предеметов может значительно добавить ей реалистичности.
Прямых средств для создания таковых в OpenGL нет. В этой главе будет описанно как заставить
отражать все окружающее плоские предметы. Примерами таких плоских зеркал могут являться
лужи, полированные поверхности, обычные стекла.
Механизм получения отражения следующий: сначала прорисовывается перевернутая сцена,
далее на каком-то расстоянии рисуется псевдо-зеркальная поверхность, затем на таком же
расстоянии оригинал сцены.
Теперь о том как реализовать это в OpenGL. Для создания отражений используется буффер
трафарета. Это делается для того, чтобы отраженные предметы не выходили за пределы зеркала.
Итак, для начала прорисовываем поверхность только в буффере трафарета:
glTranslatef(0,0,-2);
glEnable(GL_STENCIL_TEST); //Включаем буффер трафарета
glClear(GL_STENCIL_BUFFER_BIT); //Очищаем
//При прорисовке фрагмента для трафарета
//устанавливаем значение 1
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
//В любом случае разрешаем прорисовку фрагмента
glStencilFunc(GL_ALWAYS, 1, 1);
//Разрешаем рисовать только в буффере трафарета
glColorMask(FALSE,FALSE,FALSE,FALSE);
glDepthMask(FALSE);
//Рисуем пол в буффер трафарета
glBegin(GL_QUADS);
glVertex3f(-5, -5, 0);
glVertex3f( 5, -5, 0);
glVertex3f( 5, 5, 0);
glVertex3f(-5, 5, 0);
glEnd();
//Разрешаем рисовать везде
glDepthMask(TRUE);
glColorMask(TRUE,TRUE,TRUE,TRUE);
//Разрешаем прорисовку фрагмента только если
//трафарет в этом месте равен 1
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Теперь у нас есть загатовка, которая разрешает рисовать только в тех местах, где будет находиться
отражающая поверхность. То что нужно! Рисуем эмуляцию отражения, т.е сцену вверх ногами:
glPushMatrix(); //Запоминаем ситуацию
glTranslatef(0,0,-2);
glScalef(1,1,-1); //Переворачиваем сцену вверх ногами
glRotatef((float)pScene->Phase, 0, 1, 1);
glRotatef(2*(float)pScene->Phase, 1, 0, 0);
glCallList(LS_FIGURE);
glPopMatrix(); //Восстанавливаем ситуацию
glDisable(GL_STENCIL_TEST); //Трафарет больше не нужен
Теперь необходимо нарисовать само псевдо-зеркало. Просто рисуем полупрозрачную поверхность,
при этом чем больше показатель непрозрачности, тем хуже будет отражать зеркало, например
для лужи лучше взять 0.3f, а для стола 0.7f. Если вы используете поверхность с текстурой
не забудьте вызвать glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE )
для возможности использования прозрачности.
Примечание №1: Если зеркало не расположено в одной из ортогональных плоскостей вместо
glScalef(1,1,-1) используйте поворот на удвоеный угол между зеркалом и ортогональной
плоскостью.
Примечание №2: Использование текстур на прозрачной поверхности довольно дорогое (в плане
скорости) удовольствие. Два раза рисовать одно и то же тоже получается не очень быстро. А
потому старайтесь использовать отражение с умом, а то тормозить начнет.
Примечание №3: Вместо текстур на прозрачной поверхности лучше используйте текстуры со
своим собственным, готовым Alpha каналом.
Ну и взавершении, конечно же, демка плоского зеркала.