Лучшие вопросы
Таймлайн
Чат
Перспективы

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

Из Википедии, свободной энциклопедии

Remove ads

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

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

Суммиров вкратце
Перспектива

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

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

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

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

Remove ads

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

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

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

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

Remove ads

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

Суммиров вкратце
Перспектива

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

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

где

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

 — падающий луч (направление на источник света)

 — отраженный луч (направление идеально отраженного от поверхности луча)

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

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

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

Remove ads

Освещение в 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
Remove ads

Примечания

Ссылки

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads