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

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

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

Гладкое затенение[править | править вики-текст]

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

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

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

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

Модель освещения[править | править вики-текст]

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

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

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

Способ расчёта освещения[править | править вики-текст]

Расчёт освещения по Фонгу требует вычисления цветовой интенсивности трёх компонент освещения: фоновой (ambient), рассеянной (diffuse) и глянцевых бликов (specular). Фоновая компонента — грубое приближение лучей света, рассеянных соседними объектами и затем достигших заданной точки; остальные две компоненты имитируют рассеивание и отражение прямого излучения.

Иллюстрация различных компонент, соединённых в модели Фонга

где

 — вектор нормали к поверхности в точке

 — направление проецирования (направление на источник света)

 — направление на наблюдателя

 — коэффициент фонового освещения

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

 — коэффициент диффузного освещения

Освещение в OpenGL[править | править вики-текст]

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

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

Вершинный шейдер[править | править вики-текст]

1 varying vec3 n;
2 varying vec3 v;
3 
4 void main(void)
5 {
6     v = vec3(gl_ModelViewMatrix * gl_Vertex);
7     n = normalize(gl_NormalMatrix * gl_Normal);
8     gl_Position = ftransform();
9 }

Фрагментный шейдер[править | править вики-текст]

 1 varying vec3 n;
 2 varying vec3 v;
 3 
 4 void main(void)
 5 {
 6     vec4 result = vec4(0.0);
 7     for (int li = 0; li < gl_MaxLights; ++li)
 8     {
 9         vec3 viewPos = gl_LightSource[li].position.w * v;
10         vec3 l = normalize(gl_LightSource[li].position.xyz - viewPos);
11         vec3 e = normalize(-v);
12         vec3 r = normalize(-reflect(l, n));
13 
14         vec4 Iamb = gl_FrontLightProduct[li].ambient;
15 
16         vec4 Idiff = gl_FrontLightProduct[li].diffuse * max(dot(n, l), 0.0);
17         Idiff = clamp(Idiff, 0.0, 1.0);
18 
19         vec4 Ispec = gl_FrontLightProduct[li].specular
20                      * pow(max(dot(r, e), 0.0),
21                            gl_FrontMaterial.shininess);
22         Ispec = clamp(Ispec, 0.0, 1.0);
23 
24         result += Iamb + Idiff + Ispec;
25     }
26 
27     gl_FragColor = gl_FrontLightModelProduct.sceneColor + result;
28 }

Где величина

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.

Ссылки[править | править вики-текст]