GPU Gems 3, Chapter 12. High-Quality Ambient Occlusion
В этой главе мы продемонстрируем проблемы, которые возникают в этой методике на практике Кроме того, мы покажем, как небольшие изменения в алгоритме увеличивают полезность и улучшают его устойчивость к обобщенным моделям, которые существуют на данный момент. В итоге получаем быстрый, высококачественный алгоритм ambient occlusion, который позволяет создавать очень убедительные, гладкие, мягкие тени и реалистичные, контрастные детали местного окружения.12.1 Обзор
В первоначальном варианте использовались полигональные сетки с набором аппроксимирующих дисков. Диск связан с каждой вершинной сетки примитива и прилегающим полигоном. Алгоритм вычисляет оcclusion на каждой вершине путем суммирования теней от всех дисков .Это происходит путем вычисления форм-фактора –геометрического объема, который пропорционален размерам диска и обратно пропорционален расстоянию. где он расположен.Тем не менее, этот метод не учитывает видимость – диски, которые не видны, не должны вносить вклад в расчета теней. Алгоритм решает эту проблему в следующем порядке. Во-первых. Он вычисляет оcclusion на каждом диске и сохраняет вычисления. Однако, вклад тени от каждого диска оценивается, он умножается на оcclusion этого диска. Таким образом алгоритм приравнивает видимость к оcclusion.Если мы повторим этот метод , то решение сводиться к результату. который удивительно походит на ambient occlusion. Вычисление пары таких дисков может быть достаточно ресурсоемким. В самом деле, Сложность самой простой реализации этого метода пропорциональна O (N^2), что является расточительством на практике. Вместо этого, Bunnell отметил, что вкладом теней от удаленных поверхностей можно пренебрегать, а от ближайших вычислять более точно. Мы можем аппроксимировать близко расположенные диски в один сложный. Полученные диски будем группировать в более сложные структуры. пока не получим диск, который будет представлять собой приближенную модель.
Таким образом, алгоритм создает иерархическое дерево дисков, в котором на вершине будет представлена грубая приближенная модель, а внизу более детальная. Когда нам нужно оценить оcclusion на одном диске, мы начнем с самой вершины дерева.В зависимости от расстояния между диском и текущем положением в дереве, мы можем решить, что данное приближение еще не достаточно для использования Если это так , то заменим вклад теней одного диска(потомок) на множество ,из которого он аппроксимировался. Если опять не устраивает приближение, то мы спускаемся вглубь дерева, суммируя тени от своих потомков. Такой адаптивный алгоритм превращает расчет вычислений как функцию от O (N 2) в эффективный O ( N LOG(N) ).Такой метод настолько эффективен, что можно производить просчет геометрии деформации в режиме реального времени на GPU GeForce 6800.Более подробное описание читатель может увидеть на Bunnell 2005
12.2 Проблемы.
Оригинальная методика эффективно используется для вычисления мягкой occlusion, которая может быть получена линейной интерполяции треугольников. Тем не менее, было бы хорошо , если бы мы могли оценить вычисление occlusion в любой произвольной точке. Например. ресурсоемкий рендеринг нуждается в оценке ambient occlusion во избежание линейной интерполяции артефактов, которые вытекают из вершинной интерполяции.
Рисунок 1 Артефакты на клетчатой сетке с малой плотностью. Кроме того, некоторые элементы ambient occlusion имеют не гладкие границы. Например, важным элементом создания реализма является контактные тени, которые возникают между двумя соприкасающимися поверхностями. На левой стороне Рисунок 1 показаны артефакты линейной интерполяции и пропавшие тени из-за применения этого метода на pervertex rates.
Мы могли попытаться избежать артефактов интерполяции, увеличив плотность клетки сетки путем простого добавления новых треугольников. Но это не правильно, так как создает излишние нагрузки на автора mesh и повышает затраты на хранения mesh –структуры Так же повышение частоты выборки в таком методе приводит к появлению артефактов. На рисунке 2 на обратной стороне кролика виден такой эффект.
Рисунок 2 Артефакты на клетчатой сетке с высокой плотностью
Вместо увеличения tessellation density of the mesh ,мы могли бы увеличить the sampling density in screen space. То есть, применить occlusion шейдеров on a per-fragment basis. К сожалению, Применение такого способа приводит нас ко второй проблеме, что делает этот способ непригодным для использования в таком виде. Эти артефакты проиллюстрированы на рисунках 1 и 2 (правая часть).Кроме того увеличение выборочной плотности диск-образные артефакты проявляются в полной мере.
12.2.1 Диск-образные артефакты
Прежде чем мы продемонстрируем, как решить эти проблемы, было бы полезны понять причину их возникновения. Во-первых, рассмотреть вопрос о диск-образных артефактах. Они появляются на границе светлого и темного участка поверхности. Предположим, что мы вычисляем occlusion некоторых дисков в точке на одной стороне границы. Чем ближе к границе мы затемняем точки ,тем меньше становиться расстояние до диска. Наконец-то, мы достигнем точки на границе, где по критерию расстояния мы выбирем диск с наилучшим приближением mesh.На данный момент, мы опустились по дереву на уровень ниже и суммировали occlusion, полученную от потомков.Здесь мы добились дискретного перехода приближения, но ожидаем что тени становятся гладкими. На самом деле, нет никакой гарантии, что значение occlusion диска на одной стороне границы будет суммой значений occlusion потомков на другой стороне. Мы получили разрыв в тени. Так как чем ниже предок, тем лучше приближение, полученное от потомков, мы можем создавать такие разрывы произвольным образом. Конечно, мы увеличиваем наши затраты при углубление в дерево. Мы бы предпочли решение, которое является более эффективным.
12.2.2 Артефакты, связанные с шероховатостями.
Далее мы рассмотрим артефакты, связанные с шероховатостями. Предположим, мы затемним точку, которая находится на нижнем уровне иерархии. Когда мы вычислим occlusion от этого диска, его вклад будет превосходить все остальные вычисления от других дисков .Эта проблема усугубиться, когда будем вычислять тень близко к границе, так как occlusion обратно пропорциональна расстоянию. По сути мы разделим на число , которое становиться очень малым в окрестности точки на диске.Одно из решений это игнорировать диски, которые близко расположены к точке, которую мы затеняем. К сожалению, мы не знаем , что для нас близко. Благодаря такой стратегии появляются разрыва вокруг проигнорированных дисков. Кроме того, геометрия окрестности имеет решающее значение для рендеринга резких деталей, таких как контрастные тени и изгибов. Мы бы хотели найти решение, которое работало во всех случаях.
12.3 Надежное решение
В этом разделе мы рассмотрим надежное решение проблемы артефактов, возникающих в первоначальной версии алгоритма. Суть алгоритма останется прежней, но несколько ключевых изменений значительно повысят надежность результатов.12.3.1 Сглаживание разрывы
Во-первых, мы расскажем наше решение проблемы разрывов диск-образных теней. Напомним, что нет никаких гарантий того, что в любой конкретной точке мы получим тень от одного из родителей диска, который в точности будет равен сумме своих потомков. Тем не менее, мы можем сделать переход гладким между тенями по обе стороны границы. Для этого мы определим зоны вокруг перехода границы, где occlusion будет плавно интерполированы между значением вклада диска и его потомков.Рисунок 3 Геометрия переходной зоной
Внутри этой зоны , мы вычислим occlusion этого диска и рассмотрим occlusion одного из его родителей. Код представлен ниже
Пример 1. Сглаживание разрывов
- // Compute shadow contribution from the current disk.
- float contribution = . . .
- // Stop or descend?
- if(d2 < tooClose * (1.0 + r))
- {
- // Remember the parent's contribution.
- parentContribution = contribution;
- // Remember the parent's area.
- parentArea = area;
- // Compute parent's weight: a simple linear blend.
- parentWeight = (d2 – (1.0 – r) * tooClose)/(2.0 * r * tooClose);
- // Traverse deeper into hierarchy.
- . . .
- }
- else
- {
- // Compute the children's weight.
- childrenWeight = 1.0 – parentWeight;
- <strong>
- <em>// Blend contribution:
- // Parent's contribution is modulated by the ratio of the child's
- // area to its own.</em>
- </strong>
- occlusion += childrenWeight * contribution;
- occlusion += parentWeight * parentContribution * (area/parentArea);
- }
Позже мы завершим наш проход вниз дерева и вычисление occlusion .На данном этапе мы применяем сочетание. Кроме того, вклад теней от родителей представляет собой соотношение между площадями ребенка и его родителей. Чтобы понять, почему этот шаг необходим, напомним, что площадью родителей диска равен сумме своих детей. Поскольку мы будем суммировать occlusion каждого ребенка, удостоверимся, что мы не превысим родительский вклад путем введения этого коэффициента.
Заметим. что выполняя такие действия, мы предполагаем, что спустились на одну и ту же глубину для каждого потомка. Вполне возможно, что переход в глубину к потомкам может быть не одинаков. За счет этого можно более правильно реализовать этот метод . В нашем эксперименте, мы компенсировали это предположение за счет увеличения глубины обхода.
12.3.2 Удаление шероховатостей и детализация сцены
Наша методика по удалению шероховатостей состоит из двух частей. Посмотрим на расположение дисков на последнем уровне дерева. В первоначальной версии диск представлял собой приближенное значение между соседними вершинами сетки. Для точек вблизи этих вершин эти диски являются очень слабым приближением к фактической поверхности. Для точек вокруг района с большой кривизной результат будет плохой в связи с ошибочными значениями теней.Вместо использования таких дисков мы предлагаем ставить их на центр каждой сетки. Это будет гораздо лучшее приближение поверхности сетки и этот способ уберет большое количество шероховатостей.
Такие диски представляют собой лучшее приближение, но они могут не отражать истинную картину. В результате, контрастные тени в областях с высокой детализацией практически отсутствуют. Для предотвращения такой ситуации мы делаем еще один шаг приближения. На самом низком уровне в иерархии мы аналитически вычисляем форм фактор треугольников сетки.
Это оказывается проще, чем кажется. Мы можем аналитически оценить форм фактор полигона по отношению к точке с помощью следующего уравнения:
Это уравнение вычисляет форм-фактор от полигонального источника A в точку p с нормалью n. Для каждого ребра ei мы связываем единичный вектор Gi. Gi образуется путем суммы вектора ei и .вектора, образованного между точкой p и началом вектора ei. Для каждого ребра источника A мы имеем вектор Gi c нормалью n и сумму этих векторов.
Рисунок 4 иллюстрирует этот подход.
Рисунок 4 Точка-Полигон Форм-фактор
Это уравнение предполагает, что весь полигон виден. В нашем случае мы должны определить видимую часть полигона путем отсечения плоскостью, проходящей через затеняемую точку и ее нормалью. Без выполнения этого отсечения мы не сможем правильно оценить форм фактор и не избавимся от артефактов. Рисунок 5 показывает геометрию этого отсечения.
Рисунок 5 Отсеченный треугольник и видимый четырехугольник.
Отсечение треугольника плоскостью приводит к одному из трех случаев:
- Весь треугольник находится под плоскостью и его не видно
- Часть треугольника лежит под плоскостью сечения, а другая часть видна. В этом случае мы производим отсечение треугольника, получая видимый четырехугольник.
- Весь треугольник лежит над плоскостью сечения и полностью виден.
Комментариев нет:
Отправить комментарий