Герасимчук Капшивый

advertisement
Фотореалистичная визуализация
Изображение хранится в памяти как двумерная матрица пикселей.
Однако, считается, что изображение предметов реального мира это не просто
набор пикселей. Авторы [6] склонны рассматривать изображение как
непрерывную двумерную функцию. То, что мы видим на экране –
приближение этой функции, ее дискретизованное в заданном разрешении
представление. Трассировка лучей в самом общем понимании - это метод,
позволяющий восстановить значения этой функции с помощью точечных
сэмплов, то есть значений этой функции в точках. В данной работе не
рассматриваются вопросы восприятия изображения человеческим глазом,
обработка информации мозгом и вопросы фильтрации изображений.
Сосредоточимся лишь на том, как получать значения функции изображения в
точках.
Каждой точке в двухмерном пространстве экрана соответствует точка
на
некоторой
поверхности
(эту
точку
можно
найти
с
помощью
прослеживания пути луча, выпущенного из виртуального глаза через точку
экрана в сцену; назовем ее точкой x). Освещенность точке поверхности x
вычисляется при помощи интеграла следующего вида:
Рисунок 1. Интеграл освещенности.
Вычисляемая интегрированием интенсивность освещения в точке I(φr,
θr) является не числом, а функцией. Другими словами, она дает значения
интенсивности света, отражаемой поверхностью под разными углами. Таким
образом, выполняя интегрирование по полусфере приходящего (падающего)
в точку освещения L c учетом свойств поверхности R, мы получаем новую
функцию
распределения
освещения
в
пространстве,
обусловленную
свойствами отражения поверхности (материала) в точке x. Хотя если мы
рассматриваем луч, который трассировали через пиксел из виртуального
глаза, то направление конечно одно и задано этим лучом.
Рисунок 2. Двулучевая Функция Отражательной Способности - ДФО
(Bidirectional Reflectance Distribution Function - BRDF).
Формула (рис. 1) берется их тех соображений, что освещенность в
точке поверхности складывается из света, падающего на поверхность со всех
направлений и отражающегося по какому-то определенному закону (какому
именно, устанавливает функция ДФО). Эта формула не более чем
математическая модель и она верна не всегда. Например, в случае стекла
нужно учитывать свет, приходящий из под поверхности и проводить
интегрирование по полной сфере. В случае кожи ситуация еще сложнее, так
как необходимо учитывать такой эффект как подповерхностное рассеивание.
Существуют различные способы вычисления интеграла. Одни из них
более точные, другие менее точные, но более быстрые. Рассмотрим их по
порядку.
Распределенная трассировка лучей
Чтобы получить такие эффекты как мягкие тени и визуализировать
материалы из реальной жизни, обладающие нетривиальными свойствами,
необходимо использовать более сложную модель, чем обратная трассировка
лучей.
В реальности источники света часто не точечные (имеют размер), а
материалы не всегда отражают всю энергию в одном направлении по закону
“угол падения равен углу отражения”. Такое свойство может быть связано с
микрорельефом поверхности или особыми свойствами краски и т.д.
Из-за того что источник света имеет размер, границы перехода светтень получаются нечеткими, потому что на этих границах затеняющим
объектом закрыта только часть источника света. Чтобы вычислить, какая
часть источника света закрыта, до него трассируют несколько теневых лучей,
выбирая каждый раз случайную точку на источнике освещения для задания
направления луча. К сожалению, если тень сильно размыта, может
понадобиться до нескольких сотен теневых лучей на одну точку, чтобы
устранить шум, который неизменно проявляется при использовании
случайных чисел.
Аналогично поступают, если у материала сложные отражающие
свойства. Нужно испускать несколько отраженных лучей в разных
направлениях, сэмплируя BRDF материала в максимумах [8]. Обычно, BRDF
по всем направлениям не сэмплируют, так как это очень долго, но в теории
так делать можно. Ключевым моментом распределенной трассировки лучей
является сэмплирование. Сэмплирование – это просто способ вычисления
некоторой функции на множестве с помощью ее значений в точках –
сэмплах. Самый простой способ – вычислить N значений в случайных точках
и усреднить их. Чем больше сэмплов, тем точнее вычисляется функция.
Благодаря сэмплированию, распределенная трассировка лучей позволяет
получить следующие эффекты:
 сэмплирование пиксела устраняет ступенчатость;
 сэмплирование линз камеры создает эффект размытия по глубине
(depth of field);
 сэмплирование во времени приводит к размытию в движение
(motion blur);
 сэмплирование
отражений
дает
нечеткие отражения
(glossy reflections);
 сэмплирование преломлений размывает прозрачность;
 сэмплирование источников света дает мягкие тени (penumbras);
 сэмплирование длин волн света позволяет рассчитывать дисперсию
Распределенная
трассировка
лучей -
довольно
медленный,
но
реалистичный метод визуализации. Одним из ключевых моментов, от
которого зависит скорость и качество получаемой картинки - правильный
выбор количества и направления (в 3D) сэмплов.
Трассировка путей (Path tracing)
Этот алгоритм вычисляет интеграл освещенности с помощью метода
Монте-Карло в самом общем случае. Из глаза виртуального наблюдателя
выпускается луч. Каждый раз, когда луч ударяется о поверхность,
выпускается случайный теневой и случайный отраженный луч (рис. 3).
Рисунок 3. Алгоритм трассировки путей.
Причем, существует несколько способов выбора отраженных лучей.
Самый простой способ – равномерное распределение отраженных лучей по
сфере. Но этот способ крайне несовершенен, потому что он испускает равное
количество лучей во все стороны, даже в те, где BRDF близка к нулю и
неэффективно
использует
вычислительные
ресурсы.
Другой
способ
заключается в том, чтобы испускать больше лучей по тем направлениям, для
которых BRDF имеет большие значения, а нулевые области вообще не
учитывать (в англоязычной литературе этот метод известен как importance
sampling).
Ключевой момент трассировки путей тот же, что и в распределенной
трассировке лучей – выбор сэмплов. Отличие заключается в том, что
усреднение результата производится на самом верхнем уровне и отсутствует
рекурсия (что позволяет легко реализовать этот алгоритм на GPU).
Трассировка путей, вычисляющая интеграл освещенности в самом
общем случае, даже при ‘умном’ сэмплировании BRDF, очень медленно
сходится и дает характерный высокочастотный шум, что очень сильно
заметно человеческим глазом. Трассировка путей имеет сходимость корень
квадратный из числа просчитанных путей. То есть для того, чтобы
уменьшить уровень шума в m раз, необходимо выпустить m*m лучей. Для
среднестатистической сцены, даже при 1000 лучей на пиксел, шум может
быть всё ещё заметен глазом.
Рисунок 4. Шум, получаюшийся в результате трассировки путей.
Огромное
преимущество
алгоритма
по
сравнению
со
стандартной распределенной трассировкой лучей заключается в том, что
можно визуализировать промежуточный результат. Картинка рассчитывается
постепенно и если она устраивает пользователя, алгоритм можно остановить.
Двунаправленная трассировка путей и Metropolis Light
Transport
В рассмотренных алгоритмах вычисление пути света начиналось всегда
с обратной стороны, то есть из виртуального глаза. Но существуют
алгоритмы, где прослеживание пути световых лучей ведется из источника
света, или с обеих сторон. Наиболее совершенным из них считается алгоритм
“Metropolis light transport”. Идея этого алгоритма чем-то похожа на идею
генетических алгоритмов. Для каждого пиксела и источника света алгоритм
выбирает некий случайный начальный путь X0, по которому свет может
дойти от источника света до глаза. Затем, генерируется последовательность
путей X0X1.. Xn. В этой последовательности каждый следующий путь получен
из предыдущего с помощью случайных мутаций. При этом, мутации могут
приниматься или отвергаться – в зависимости от того какой вклад вносит
результирующий путь Xi+1 в изображение по сравнению с Xi.
Рисунок 5.
На рис. 5. функция AcceptProb(Y|X) является оценочной функцией и
говорит, насколько хорош новый путь относительно старого пути x.
Фотонные карты
Фотонные карты – один из самых универсальных и реалистичных
алгоритмов, решающих задачу вычисления интеграла освещенности в самом
общем случае. Фотонные карты сложны как в реализации, так и в
вычислительном плане. Алгоритм состоит из трех частей: трассировка
фотонов, построение фотонной карты и сбор освещенности.
Трассировка фотонов
Фотоны в данном методе – это частицы, переносящие некоторую
небольшую порцию световой энергии. На начальном этапе фотоны
испускаются из источника света в соответствие с распределением световой
энергии у данного источника. Например, известно, что точечный или
сферический источник света (такой как солнце) испускают свет равномерно
во всех направлениях. Площадные источники света имеют косинусоидальное
распределение, имеющее максимум по направлению, совпадающему с
нормалью к плоскости источника и нуль по направлениям, лежащим в этой
плоскости.
Рисунок 6. Процесс трассировки фотонов.
В процессе трассировки фотоны ударяются о различные поверхности.
В зависимости от свойств материала, с ними могут происходить разные
события: фотон может отразиться диффузно (то есть в случайном
направлении), зеркально, пройти через поверхность или полностью
поглотиться. При диффузном отражении и поглощении, запись о фотоне
сохраняется (просто в списке или массиве), причем решение о том, какое из
событий происходит с фотоном, принимается на основании “Русской
рулетки”.
Построение фотонной карты
После того, как трассировка фотонов завершена, производится
построение фотонной карты в виде некоторой структуры пространственного
разбиения. Этот этап вспомогательный и служит для того, чтобы на
следующем шаге в произвольной точке пространства можно было найти k
ближайших фотонов. Если бы фотоны просто сохранялись в массиве, то k
ближайших каждый раз пришлось бы вычислять перебором, что очень
медленно.
Авторы использовали специализированный вариант kd дерева для
хранения фотонов. Kd дерево – это бинарное дерево, разбивающее
пространство
плоскостями,
параллельными
осям
координат.
Детали
построения, балансировки и поиска в kd деревьях описаны в соответствущем
разделе.
Сбор освещенности
После того, как фотонная карта построена, и мы имеем возможность
выполнять быстрый поиск в ней, начинается этап сбора освещенности. Здесь
возможны различные варианты. Вопрос в том, в каких точках собирать
освещенность. Самый реалистичный метод: использовать распределенную
трассировку лучей с тем отличием, что каждый раз при ударе луча о
поверхность, необходимо выполнить сбор освещенности в этой точке, найдя
k ближайших фотонов, суммировав их энергию (в самом простом случае) и
поделив полученную энергию на площадь поверхности сферы, радиус
которой равен расстоянию до самого дальнего фотона. Алгоритм, таким
образом, динамически выбирает радиус сбора: там где фотонов много,
радиус сбора маленький, где мало - большой. Поэтому уровень шума
одинаков для всего изображения.
Рисунок 7. Сбор k ближайших фотонов динамически выбирает радиус
сферы.
Можно использовать константный радиус сбора и искать не k
ближайших фотонов, а собирать освещение со всех фотонов, попавших в
сферу заданного радиуса. Но такой метод дает больший шум. На практике
фотонные карты применяют для вычисления каустиков и вторичной
освещенности с использованием КЭШа излучения и финального сбора.
Рисунок 8. Спектральные каустики, вычисленные с
помощью фотонных карт. На скриншоте вместо поиска k ближайших
используется сбор со всех фотонов попавших в сферу заданного радиуса.
Для вычисления интеграла освещенности непосредственно их обычно
не применяют, так как это дорого по вычислительным ресурсам (нужно
очень много фотонов для получения приемлемого результата – как минимум
несколько миллионов), изображение получается шумное и наблюдается
характерный артефакт – потемнение краев. Потемнение краев наблюдается
потому что на границах поверхности сбор освещенности происходит только с
половины сферы, а результат делится на площадь поверхности всей сферы.
Чтобы устранить шум и убрать темные края, необходимо применять метод
финального сбора или алгоритм “convex hull”, который еще в несколько раз
замедляет скорость фотонных карт [10].
Рисунок 9. Интеграл освещенности посчитан непосредственно с
помощью фотонных карт (Визуализация фтонной карты напрямую).
Характерен низкочастотный шум и потемнение краев. Также использован
упрощенный метод сбора (радиус сферы сбора константный).
Финальный сбор
При
использовании
этого
метода
сами
фотонные
карты
задействуются только для вычисления непрямой освещенности. Тени,
отражения и другие эффекты (кроме каустиков, разумеется, для которых
финальный
трассировки
сбор
не
лучей
нужен) считают
или
какого-то
при
помощи
другого
распределенной
метода.
Вместо
непосредственного сбора освещенности с фотонов, в методе финального
сбора из заданной точки испускается некоторое число лучей по полусфере и
освещенность собирается уже в тех местах, куда попали лучи. Это позволяет
значитеьно снизить шум. Как правило нужно трассировать меньше лучей,
чем в Монте-Карло трассировке (расределенной трассировке лучей или
трассировке путей).
Lightcut
Этот алгоритм служит немного для других целей, нежели трассировка
путей или фотонные карты, но может быть с успехом применен для
вычисления непрямой освещенности при соответствующей модификации.
Основная цель алгоритма – ускорение вычисления прямого освещения при
очень большом количестве источников света. На первом этапе все источники
света представляются как набор очень большого количества точечных
источников. После строится дерево источников света. В вершине дерева
всегда находится один точечный источник, который аппроксимирует все
источники, лежащие ниже его по иерархии. Расчет освещения выполняется
следующим образом: вычисляем освещение одним корневым источником и
двумя дочерними. Изначально текущий уровень дерева - нулевой уровень,
корень дерева. Если разница между результатом, полученным на текущем
уровне и результатом, полученным на следующем уровне дерева не
превышает установленный порог, расчет освещения в точке прекращается.
Иначе, для каждого узла рекурсивно переходим на следующий уровень
дерева (рис 10).
Рисунок 10. работа алгоритма Lightcut
Расставляя искусственные источники света на поверхностях объектов,
можно вычислять непрямое освещение с помощью этого алгоритма.
Излучательность (Radiosity)
Алгоритм излучательности рассматривает частный случай решения
уравнения
освещенности,
когда
материалы
являются
диффузными.
Материал называется диффузным, если вся энергия, отраженная от его
поверхности рассеивается равномерно по всем направлениям. ДФО
диффузных материалов равняется константе, поэтому интеграл в уравнении
освещенности принимает более простой вид. На практике материалы далеко
не
всегда
являются
диффузными,
возможен
случай
существования
нескольких максимумов ДФО (в англоязычной литературе такие материалы
называются glossy materials – см. Рис. 11).
Рис. 11. Различные модели ДФО.
Другим важным ограничением является требование замкнутости
системы, т.е. суммарная энергия в системе должна сохраняться (что, вообще
говоря, обязательно в уравнении освещенности). Поэтому если Вам
необходимо смоделировать сцену, где все материалы заданы при помощи
модели Фонга, то алгоритм излучательности не подойдет по двум причинам.
Первая – в общем случае материалы не будут диффузными. Вторая – модель
Фонга не сохраняет энергию. Перейдем к рассмотрению классической схемы
метода излучательности.
На первом этапе алгоритма все поверхности сцены делятся на патчи.
Патч – это элементарная единица поверхности. Дискретизация поверхности
на патчи позволяет заменить интеграл в уравнении освещенности на
конечную сумму интегралов специального вида. Каждый такой интеграл,
называемый форм-фактором, задает взаимное влияние двух отдельных
патчей (т.е. сколько энергии переходит от одного патча к другому). Если мы
знаем значение каждого форм-фактора (для каждой пары патчей), то процесс
синтеза
изображений
сводится
к
решению
системы
линейных
алгебраических уравнений. Основная трудность в алгоритме – расчет формфакторов.
Далее
приведены
некоторые
подкрепляющие словесное описание алгоритма.
математические
выкладки,
Как было упомянуто выше, для алгоритма излучательности необходим
метод расчета форм-фактора. Для начала рассмотрим алгоритм полукуба
(hemicube algorithm). Алгоритм основан на т.н. аналогии Нуссельта.
Согласно
этой
аналогии
форм-фактор
можно
рассчитать
чисто
геометрическим способом. Рассмотрим некоторый дифференциальный патч
(элемент разбиения патча) и некоторую сферу с центром в этом патче.
Возьмем теперь второй патч, от которого мы будем рассчитывать формфактор, и спроецируем его на эту сферу. Полученную проекцию
спроецируем на плоскость первого патча и поделим на площадь окружности.
Проведя эти действия для всех дифференциальных патчей, и просуммировав
результаты, мы получим значение форм-фактора. В алгоритме полукуба для
ускорения расчета проекции патча на сферу, сфера заменяется на
аппроксимирующий ее куб. Это позволяет существенно повысить скорость
алгоритма на имеющейся аппаратуре, однако иногда при этом страдает и
качество.
Рис. 12. Аналогия Нуссельта (красным помечена область, площадь которой
численно равна форм-фактору дифференциального патча и патча A).
Рис. 13. Аппроксимация сферы кубом в разрезе (слева) и возникающие
при этом артефакты (справа).
Для того чтобы решить проблему полукуба Волтон предложил метод
расчета форм-факторов на основе трассировки лучей. Один из патчей
принимается за источник света (площадный), а второй патч выступает в
качестве
поверхности–приемника
лучей.
Площадь
патча-источника
подразбивается на более мелкие независимые патчи (фактически это
дифференциальные патчи). Из каждого подпатча испускаются лучи. При
увеличении числа лучей точность расчета форм-фактора увеличивается.
Обычно процесс испускания лучей заканчивается, когда значение формфактора практически перестает изменяться. Рассмотренный алгоритм дает
намного лучшие результаты, чем метод полукуба, ценой более высокой
вычислительной сложности. Этот алгоритм еще интересен тем, что в нем
используется интересный прием отождествления отражающей поверхности с
новым источником света. Позднее этот прием применяется в алгоритме
Lightcut для расчета вторичного освещения.
Существуют и гибридные методы для расчета форм-фактора, которые
ликвидируют недостатки метода полукуба и работают быстрее метода
трассировки.
На последнем этапе метода излучательности происходит решение
системы линейных алгебраических уравнений. Обычно решение ищется
каким-то из итерационных методов (например, методом Зейделя), т.к.
сложность таких методов на порядок ниже, чем у прямых (N2 по сравнению с
N3).
Стоит отметить еще один недостаток алгоритма – сложность
моделирования мягких теней, т.е. теней от протяженных источников. При
моделировании мягких теней возникают т.н. блочные тени. Блочные тени
образуются из-за того, что минимальной единицей расчета освещения
является патч. Единственный способ побороться с подобными артефактами
– произвести подразбиение патчей в области мягкой тени.
Рис. 14. Результаты метода излучения (справа особенно заметна
проблема блочных теней).
REYES
REYES
– Алгоритм
основан
на
субпиксельной
тесселяции
на
микрополигоны с последующим затенением каждого микрополигона любым
из методов, рассчитывающих интеграл освещения в точке. После чего идет
сэмплирование цвета для каждого пиксела исходя из того, какие
микрополигоны попадают в него. Собственно интеграл освещенности для
микрополигонов рассчитывается одним из известных методов или их
комбинацией. Используется в программах Pixar RenderMan, 3dlight, Air,
Houndi (mantra) и других, включая OpenSource.
Кэш излучения (Irradiance cache)
Кэш излучения (irradiance cache) – это не способ вычисления интеграла
освещенности. Это лишь способ ускорения вычисления этого интеграла на
множестве точек. Основная идея заключается в том, что вторичное
освещение разделяется на две компоненты – низкочастотную (диффузную) и
высокочастотную
(отражающую).
Низкочастотная
компонента
на
изображении меняется плавно, поэтому ее можно вычислить каким-либо из
методов
лишь
в
очень
небольшом
числе
точек,
а
в
остальных
интерполировать.
Рисунок 15. Изображение со вторичным освещением.
Рисунок 16. Точки, в которых вторичное освещение было рассчитано.
Высокочастотная
компонента
обычно
обусловлена
резкими
максимумами BRDF, поэтому она может быть вычислена сэмплированием с
помощью относительно небольшого числа лучей только в максимумах
BRDF (importance sampling).
Различают
кэш
излучения
в
трехмерном
пространстве
сцены
(world space) и кэш в экранной плоскости (screen space). Реализация кэша в
экранной плоскости проще и эффективнее т.к. втоиричное освещение
вычисляется целиком для пиксела. Интерполяция также производится в
пространстве экрана. Однако, кэш излучения в пространстве экрана может
быть использован по понятным причинам только для первично видимых
поверхностей.
Как правило, кэш излучения вычисляется на лету. Каждый раз при
вычислении вторичного диффузного освещения делается попытка выборки
из кэша. Если значение может быть выбрано так, что ошибка меньше
допустимой величины, оно получается как результат интерполяции
ближайших точек кэша. Если ошибка больше допустимой величины,
значение честно вычисляется с помощью трассировки лучей по всем
направлениям (или финального сбора из фотонной карты) и полученная
точка сохраняется в КЭШе.
Алгоритм кэширования вторичного освещения содержит 2 узких места
- расчет собственно вторичного освещения в точках кэша и финальный
алгоритм интерполяции освещения во всех остальных точках. Оба узких
места могут быть существенно ускорены на графических процессорах.
Вычисление вторичного освещения
В предлагается вычислять вторичную освещенность в точках с
помощью растеризации в кубическую текстурную карту. Данная операция
может производиться очень быстро т.к. имеет аппаратную поддержку даже в
довольно старых видеокартах (обычно используется для симуляции
отражений на объектах).
Рисунок 17. Пример кубической текстурной карты.
Несмотря на преимущество по скорости, недостаток этого алгоритма в
том, что он не может учитывать зеркальных отскоков света и может быть в
ряде случаев медленнее трассировки лучей на больших сценах. Причина
заключается в том, что при растеризации вся геометрия обрабатывается
графическим процессором. Она проходить весь графический конвейер:
преобразование
вершин,
возможно
тесселяцию
и
геометрические
преобразования над примитивами, интерполяция атрибутов вершин и
вычисление значений освещенности в пикселах.
Допустим, геометрия – это некоторое здание, разделенное на комнаты.
Всё здание содержит 2 миллиона вершин. Пусть виртуальный наблюдатель
находится в одной из комнат. Несмотря на то, что комната может составлять
10-20% всей геометрии, при вычислении освещения в точке каждый раз
потребуется пропускать через графический конвейер все 2 миллиона вершин.
Тот факт что 90% сцены может быть закрыто стеной или каким-то
близкорасположенным объектом никак не используется. В то же время,
трассировка лучей учитывает такие вещи. Так как трассировка лучей
использует бинарный поиск, скорость вычисления освещенности будет
зависеть сублинейно (обычно логарифмически) от размера входных данных,
а не линейно, как в случае растеризации.
Интерполяция
Исторически, для хранения точек иррадианс кэша использубт
специальное октодерево со множественными ссылками (multiple reference
octree). Точки кэша излучения в таком октодереве хранятся не только в
листьях, но и во все остальных узлах. Точка сохраняется в узле, если
расстояние от центра узла до этой точки меньше определенной величины.
Если это не так, то точка должна пройти на один или несколько дочерних
уровней дерева.Основной плюс этого октодерева в том, что возможно
осуществить простой нерекурсивный поиск от корня к листу. Однако
эффективность этого решения сомнительна. Для того чтобы упростить поиск
при построении такого дерева (или вставке новых точек в него), каждую
точку необходимо добавлять во все дочерние узлы, с которыми пересекается
сфера с центром в этой точке и радиусом, равным радиусу поиска.
Рисунок 18. Multiple reference octree.
В результате на одну и ту же точку иррадианс-кэша может приходится
несколько ссылок из разных мест окто-дерева. Это ведет к неэфективному
использованию кэша (особенно текстурного, если предполагается реализация
на GPU), т.к. число ссылок может значительно превышать число самих точек
иррадианс-кэша. Очевидно, что для поиска ближайших точек можно
использовать любую другую ускоряющую структуру, например kd-дерево.
В предлагается реализовать такую интерполяцию при помощи
растеризации сплатов – дисков или сфер некоторой небольшой величины.
Рисунок 19. Интерполяция освещения при помощи растеризации
сплатов.
Недостаток этого метода в том, что он может быть применен только
при
вычислении
освещения
на
первично-видимых
поверхностях.
Преимущество – высокая скорость за счет аппаратной поддержки
растеризации.
Резюме
Кэширование вторичного освещения - крайне эффективная техника
ускорения
вычисления
глобально
освещения,
позволяющая
снизитиь
количество необходимых вычислений практически на 3 порядка (для
больших разрешений). Допустим, имеется изображение размером 1024x1024
пиксела. Если вычислять вторичное освещение в каждой точке, то
потребуется суммарно протрассировать порядка 109 лучей только для
вычисления вторичной освещенности. Используя кэш излучения количество
точек,
в
которых
необходимо
вычислить
вторичную
освещенность
сокращается с миллиона до нескольких тысяч. Соответственно, число лучей
падает с 109 до 106.
Download