Затенение по Фонгу

Поделись знанием:
Перейти к: навигация, поиск

Затенение по Фонгу — модель расчёта освещения трёхмерных объектов, в том числе полигональных моделей и примитивов, а также метод интерполяции освещения по всему объекту.





Гладкое затенение

Модели обычно задаются набором плоских выпуклых граней, хотя большинство реальных трёхмерных предметов имеют гладкие криволинейные поверхности. Таким образом, криволинейная поверхность рисуется как ребристая полигональная сетка; для того, чтобы эта сетка выглядела гладкой, используется тот или иной метод интерполяции освещённости вершин полигональной сетки.

Если используется затенение по Гуро, то расчёт цвета производится в каждой вершине каждой грани, а затем рассчитанный цвет интерполируется по всей грани. В результате блики, которые должны проявиться в середине полигона, нарисованы не будут — при интерполяции цветов вершин более яркое освещение центра многоугольника невозможно.

При затенении по Фонгу интерполируется вектор нормали[1]. Для нахождения вектора нормали в произвольной точке поверхности используют нормированную взвешенную сумму векторов нормали граней, которым эта точка принадлежит:

<math>n=\frac{a_1 n_1+...+a_k n_k}{\left \Vert a_1 n_1+...+a_k n_k\right\|}</math>

Вычислительные затраты на затенение по Гуро или по Фонгу зависят соответственно от числа вершин и от числа фрагментов изображения. Современное графическое оборудование использует второй способ, вычисляя цвет каждого фрагмента (т.е. пикселя), а не каждой вершины.

Модель освещения

Освещение по Фонгу включает в себя также и модель освещения Фонга, т.е. алгоритм расчёта освещения в заданной точке. Это локальная модель освещения, т.е. она учитывает только свойства заданной точки и источников освещения, игнорируя эффекты рассеивания, линзирования, отражения от соседних тел.

Затенение по Фонгу требует сравнительно мало ресурсов, но большинство оптических явлений игнорируются либо рассчитываются с грубым приближением.

Другие модели освещения могут лучше учитывать свойства материала (локальные модели Орена-Наяра, Кука-Торренса, анизотропные модели) или сложные оптические явления (глобальные модели), но ведут к росту накладных расходов.

Способ расчёта освещения

Расчёт освещения по Фонгу требует вычисления цветовой интенсивности трёх компонент освещения: фоновой (ambient), рассеянной (diffuse) и глянцевых бликов (specular). Фоновая компонента — грубое приближение лучей света, рассеянных соседними объектами и затем достигших заданной точки; остальные две компоненты имитируют рассеивание и отражение прямого излучения. <math>I=K_aI_a+K_d(\vec{n},\vec{l})+K_s(\vec{n},\vec{h})^p</math>

где

<math>\vec{n}</math> — вектор нормали к поверхности в точке

<math>\vec{l}</math> — направление проецирования (направление на источник света)

<math>\vec{h}</math> — направление на наблюдателя

<math>K_a</math> — коэффициент фонового освещения

<math>K_s</math> — коэффициент зеркального освещения

<math>K_d</math> — коэффициент диффузного освещения

Освещение в OpenGL

В конвейере OpenGL цветовая интенсивность фрагмента рассчитывается для каждого источника света в отдельности, затем результаты складываются и добавляется свет, излучаемый телом (GL_EMISSION).

Алгоритм расчёта освещения по Фонгу можно проиллюстрировать с помощью следующих шейдеров:

Вершинный шейдер

varying vec3 n;
varying vec3 v;

void main(void)
{
    v = vec3(gl_ModelViewMatrix * gl_Vertex);
    n = normalize(gl_NormalMatrix * gl_Normal);
    gl_Position = ftransform();
}

Фрагментный шейдер

varying vec3 n;
varying vec3 v;

void main(void)
{
    vec4 result = vec4(0.0);
    for (int li = 0; li < gl_MaxLights; ++li)
    {
        vec3 viewPos = gl_LightSource[li].position.w * v;
        vec3 l = normalize(gl_LightSource[li].position.xyz - viewPos);
        vec3 e = normalize(-v);
        vec3 r = normalize(-reflect(l, n));

        vec4 Iamb = gl_FrontLightProduct[li].ambient;

        vec4 Idiff = gl_FrontLightProduct[li].diffuse * max(dot(n, l), 0.0);
        Idiff = clamp(Idiff, 0.0, 1.0);

        vec4 Ispec = gl_FrontLightProduct[li].specular
                     * pow(max(dot(r, e), 0.0),
                           gl_FrontMaterial.shininess);
        Ispec = clamp(Ispec, 0.0, 1.0);

        result += Iamb + Idiff + Ispec;
    }

    gl_FragColor = gl_FrontLightModelProduct.sceneColor + result;
}
Где величина
gl_FrontLightModelProduct.sceneColor
эквивалентна выражению
gl_FrontMaterial.emission + gl_FrontMaterial.ambient * gl_LightModel.ambient

Напишите отзыв о статье "Затенение по Фонгу"

Примечания

  1. Д. Роджерс. Алгоритмические основы машинной графики = Procedural Elements for Computer Graphics. — М.: Мир, 1989. — С. 394. — 512 с. — ISBN 0-07-053534-5.

Ссылки

  • [www.compgraphics.info/3D/lighting/phong_reflection_model.php Модель отражения Фонга]
  • [www.compgraphics.info/3D/lighting/shading_model.php Модели затенения. Плоская модель. Затенение по Гуро и Фонгу]
  • [www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php Попиксельное освещение]

Отрывок, характеризующий Затенение по Фонгу


Неожиданное известие о переходе французами Немана было особенно неожиданно после месяца несбывавшегося ожидания, и на бале! Государь, в первую минуту получения известия, под влиянием возмущения и оскорбления, нашел то, сделавшееся потом знаменитым, изречение, которое самому понравилось ему и выражало вполне его чувства. Возвратившись домой с бала, государь в два часа ночи послал за секретарем Шишковым и велел написать приказ войскам и рескрипт к фельдмаршалу князю Салтыкову, в котором он непременно требовал, чтобы были помещены слова о том, что он не помирится до тех пор, пока хотя один вооруженный француз останется на русской земле.
На другой день было написано следующее письмо к Наполеону.
«Monsieur mon frere. J'ai appris hier que malgre la loyaute avec laquelle j'ai maintenu mes engagements envers Votre Majeste, ses troupes ont franchis les frontieres de la Russie, et je recois a l'instant de Petersbourg une note par laquelle le comte Lauriston, pour cause de cette agression, annonce que Votre Majeste s'est consideree comme en etat de guerre avec moi des le moment ou le prince Kourakine a fait la demande de ses passeports. Les motifs sur lesquels le duc de Bassano fondait son refus de les lui delivrer, n'auraient jamais pu me faire supposer que cette demarche servirait jamais de pretexte a l'agression. En effet cet ambassadeur n'y a jamais ete autorise comme il l'a declare lui meme, et aussitot que j'en fus informe, je lui ai fait connaitre combien je le desapprouvais en lui donnant l'ordre de rester a son poste. Si Votre Majeste n'est pas intentionnee de verser le sang de nos peuples pour un malentendu de ce genre et qu'elle consente a retirer ses troupes du territoire russe, je regarderai ce qui s'est passe comme non avenu, et un accommodement entre nous sera possible. Dans le cas contraire, Votre Majeste, je me verrai force de repousser une attaque que rien n'a provoquee de ma part. Il depend encore de Votre Majeste d'eviter a l'humanite les calamites d'une nouvelle guerre.
Je suis, etc.
(signe) Alexandre».
[«Государь брат мой! Вчера дошло до меня, что, несмотря на прямодушие, с которым соблюдал я мои обязательства в отношении к Вашему Императорскому Величеству, войска Ваши перешли русские границы, и только лишь теперь получил из Петербурга ноту, которою граф Лористон извещает меня, по поводу сего вторжения, что Ваше Величество считаете себя в неприязненных отношениях со мною, с того времени как князь Куракин потребовал свои паспорта. Причины, на которых герцог Бассано основывал свой отказ выдать сии паспорты, никогда не могли бы заставить меня предполагать, чтобы поступок моего посла послужил поводом к нападению. И в действительности он не имел на то от меня повеления, как было объявлено им самим; и как только я узнал о сем, то немедленно выразил мое неудовольствие князю Куракину, повелев ему исполнять по прежнему порученные ему обязанности. Ежели Ваше Величество не расположены проливать кровь наших подданных из за подобного недоразумения и ежели Вы согласны вывести свои войска из русских владений, то я оставлю без внимания все происшедшее, и соглашение между нами будет возможно. В противном случае я буду принужден отражать нападение, которое ничем не было возбуждено с моей стороны. Ваше Величество, еще имеете возможность избавить человечество от бедствий новой войны.
(подписал) Александр». ]


13 го июня, в два часа ночи, государь, призвав к себе Балашева и прочтя ему свое письмо к Наполеону, приказал ему отвезти это письмо и лично передать французскому императору. Отправляя Балашева, государь вновь повторил ему слова о том, что он не помирится до тех пор, пока останется хотя один вооруженный неприятель на русской земле, и приказал непременно передать эти слова Наполеону. Государь не написал этих слов в письме, потому что он чувствовал с своим тактом, что слова эти неудобны для передачи в ту минуту, когда делается последняя попытка примирения; но он непременно приказал Балашеву передать их лично Наполеону.
Выехав в ночь с 13 го на 14 е июня, Балашев, сопутствуемый трубачом и двумя казаками, к рассвету приехал в деревню Рыконты, на французские аванпосты по сю сторону Немана. Он был остановлен французскими кавалерийскими часовыми.