Руководство по работе с графической библиотекой OpenGL. Руководство разработано с учетом опыта чтения курса Компьютерная графика
Скачать 0.66 Mb.
|
G = Zn W Точка, в которой луч, проведенный от источника света через данную точку Р, пересекает плоскость G, определяется параметрами а и Ь, удовлетворяющими следующему уравнению: 8.2. Построение теней 105 {аР + bL)G = 0 Отсюда получаем: a(PG) + b(LG) = 0. Этому уравнению удовлетворяют a = (LG),b = -(PG) Следовательно, координаты искомой точки S = (LG)P — (PG)L. Пользуясь ассоциативностью матричного произведения, получим S = P[(LG)I-GL] (8.1) где / — единичная матрица. Матрица (LG)I — GL используется для получения теней на произвольной плоскости. Рассмотрим некоторые аспекты практической реализации данного метода с помощью OpenGL. Предположим, что матрица floorShadow была ранее получена нами из формулы (LG)I — GL. Следующий код с ее помощью строит тени для заданной плоскости: /* Визуализируем сцену в обычном режиме. */ RenderGeometry () ; /* Делаем тени полупрозрачными с использованием смешивания цветов(blending) */ glEnable (GL_BLEND) ; glBlendFunc (GL_SRC_ALPHA,GL_ONE_MNUS_SRC_ALPHA); glDisable (GL_LIGHTING); glColor4f(0.0, 0.0, 0.0, 0.5); glPushMatrix (); /* Проецируем тень */ glMultMatrixf ((GLfloat *) floorShadow); /* Визуализируем сцену в проекции */ 106 Глава 8. Графические алгоритмы на основе OFENGL RenderGeometry (); glPopMatrix (); glEnable (GL_LIGHTING); glDisable(GL_BLEND); Матрица floorShadow может быть получена из уравнения 8.1 с помощью следующей функции: /* параметры: plane — коэффициенты уравнения плоскости lightpos — координаты источника света возвращает: matrix — результирующая матрица */ void shadowmatrix( GLfloat matrix [4] [4] , GLfloat plane [4] , GLfloat lightpos [4]) { GLfloat dot ; dot = plane [0] * lightpos [0] + plane[l] * lightpos [1] + plane[2] * lightpos [2] + plane [3] * lightpos [3];
0] = dot 0] = O.f 0] = O.f 01 = O.f ] = O.f dot O.f O.f O.f O.f dot O.f lightpos lightpos lightpos lightpos lightpos lightpos lightpos lightpos lightpos lightpos lightpos lightpos
8.2. Построение теней 107 matrix [0][3] = O.f - lightpos [3] * plane[0] matrix[l][3] = O.f - lightpos [3] * plane [1] matrix [2][3] = O.f - lightpos [3] * plane[2] matrix [3][3] = dot - lightpos [3] * plane [3] } Заметим, что тени, построенные таким образом, имеют ряд недостатков: Описанный алгоритм предполагает, что плоскости бесконечны, и не отрезает тени по границе. Например, если некоторый объект отбрасывает тень на стол, она не будет отсекаться по границе, и, тем более, «заворачиваться» на боковую поверхность стола. В некоторых местах теней может наблюдаться эффект «двойного смешивания» (rcblcnding), т.е. темные пятна в тех участках, где спроецированные треугольники перекрывают друг друга. С увеличением числа поверхностей сложность алгоритма резко увеличивается, т.к. для каждой поверхности нужно заново строить всю сцену, даже если проблема отсечения теней по границе будет решена. Тени обычно имеют размытые границы, а в приведенном алгоритме они всегда имеют резкие края. Частично избежать этого позволяет расчет теней из нескольких источников света, расположенных рядом и последующее смешивание результатов. Имеется решение первой и второй проблемы. Для этого используется буфер маски (см. п. 7.2). Итак, задача — отсечь вывод геометрии (тени) по границе некоторой произвольной области и избежать «двойного смеши- 108 Глава 8. Графические алгоритмы на основе OFENGL вания». Общий алгоритм решения с использованием буфера маски таков: очищаем буфер маски значением 0; отображаем заданную область отсечения, устанавливая значения в буфере маски в 1; рисуем тени в тех областях, где в буфере маски установлены значения; если тест проходит, устанавливаем в эти области значение 2. Теперь рассмотрим эти этапы более подробно. 1. /* очищаем буфер маски*/ glClearStencil(OxO) glClear (GL_STENCIL_BUFFER_BIT); /* включаем тест */ gl En able (GL_STENCIL_TEST); |