Алгоритм отсечения проверяет положение каждой вершины треугольника относительно плоскости сечения. Точка может быть выше или под плоскостью, но для надежности, мы рассмотрим еще точку, лежащую на плоскости. Для 3 вершин с 3 возможными свободами получаем 3^3 = 27 возможных ситуаций. К счастью, графическая система GeForce 8800 быстро определяет нужную конфигурацию и тестирует в худшем случае 5 случаев.
Пример 2 показывает нашу функцию, которая вычисляет видимые части треугольника. В качестве входных параметров функция принимает секущую плоскость, описанную точкой и нормалью, и 3 вершины треугольника. Она выводит 4 вершины получившейся видимой области треугольника. Если среди 4 получившихся вершин есть две одинаковые, то треугольник полностью виден.А если все 4 одинаковые, то треугольник скрыт за секущей плоскостью.
Мы начнем алгоритм с указанием эпсилон значения, которое будет контролировать процесс сечения. Вершины, которые находятся на расстояние меньше ,чем это значение, будем рассматривать как лежащие на плоскости. Далее мы рассмотрим уравнение плоскости для каждой вершины. В результате получаем расстояние от каждой вершины к плоскости. Точки, находящиеся над плоскостью, будут иметь положительное расстояние; точки –ниже плоскости – отрицательное расстояние. У точек, которые находятся очень близко с плоскости, расстояние будем приближать к нулю.
Пример 2. Нахождение видимой части треугольника
- void visibleQuad(float3 p,
- float3 n,
- float3 v0,
- float3 v1,
- float3 v2,
- out float3 q0,
- out float3 q1,
- out float3 q2,
- out float3 q3)
- {
- const float epsilon = 1e-6;
- float d = dot(n, p);
- // Compute the signed distances from the vertices to the plane.
- float sd[3];
- sd[0] = dot(n, v0) – d;
- if(abs(sd[0]) <= epsilon) sd[0] = 0.0;
- sd[1] = dot(n, v1) – d;
- if(abs(sd[1]) <= epsilon) sd[1] = 0.0;
- sd[2] = dot(n, v2) – d;
- if(abs(sd[2]) <= epsilon) sd[2] = 0.0;
- // Determine case.
- if(sd[0] > 0.0)
- {
- if(sd[1] > 0.0)
- {
- if(sd[2] < 0.0)
- {
- // v0, v1 above, v2 under
- q0 = v0;
- q1 = v1;
- // Evaluate ray-plane equations:
- q2 = v1 + (sd[1]/(sd[1] - sd[2])) * (v2 - v1);
- q3 = v0 + (sd[0]/(sd[0] - sd[2])) * (v2 - v0);
- }
- else
- {
- // v0, v1, v2 all above
- q0 = v0;
- q1 = v1;
- q2 = v2;
- q3 = q3;
- }
- }
- }
- // Other cases similarly
- . . .
12.4 Результаты
Далее, мы сравним результаты улучшенного алгоритма с первоначальным методом. Мы выбрали две фигуры, кролика и машину, чтобы продемонстрировать эффективность нового метода в зависимости от входных значений. Сетка кролика явлется гладкой, хорошо структурированной с равносторонними треугольниками. С другой стороны, у машины имеется куча разнородных деталей с острыми углами и треугольники с различными пропорциями. Рисунки 6 и 7 показывают результаты.
Рисунок 6 Сравнительный анализ Ambient Occlusion на сетке кролика.
Рисунок 7 Сравнительный анализ Ambient Occlusion на сетке машины
Вы можете видеть, что первоначальный алгоритм хорошо подходит для сетки кролика ,благодаря высокой структурированности. Но все же дискообразные и линейной интерполяции артефакты становятся очевидными.
Тем не менее, первоначальный алгоритм плохо подходит для машины. В некоторых частях возникают артефакты линейной интерполяции. Применение шейдеров сглаживают интерполяцию, но добавляют дискообразные разрывы и шероховатости вблизи вершин. Наш алгоритм превосходно справился со всеми артефактами и получил реалистичный результат.
12.5 Показатели
Здесь приведено краткое описание результатов. Во всех экспериментах, мы выставляли эпсилон равный 8, который контролировал обход в глубину. Во-первых, мы измерили производительность на первых шагах затемнения дисков the coarse occlusion hierarchy.Наша реализация этого шага не отличается от первоначальной методы и служит только для сравнения. Далее мы измерили производительность наших новых шейдеров с и без отсечения треугольников и вычислением форм факторов. Мы использовали метод отложенного затенения для обеспечения того, чтобы только видимые фрагменты были заштрихованы. Наконец, мы подсчитали общее количество затененных фрагментов для измерения коэффициента затенения. Таблицы 1 и рисунок 8 показывают наши получившиеся результаты.
Таблица1 Полученные результатов
Модель сетки | Размер треугольника | Всего затененных фрагментов | Всего затененных дисков |
кролик | 69,451 69.451 | 381,046 381.046 | 138,901 138.901 |
машина | 29,304 29.304 | 395,613 395.613 | 58,607 58.607 |
Рисунок 8 Полученные результаты
Мы получили, что производительность затенение дисков будет сопоставима с затемнением фрагментов с высокоточным вычислением форм фактора. Мы заметили, что коэффициент затенения дисков , как правило, гораздо меньше, чем коэффициент затенения фрагментов. Мы считаем, что это из-за меньшего размера партии нежели из-за общего количества затеняемых фрагментов. Высокоточное вычисление форм фактора в шейдере требует большого ветвления и приводит к более низкому коэффициенту затенения. Однако, помимо этого обеспечивает надежный результат.
12.5 Пояснения
Мы рассмотрим некоторые особенности применения нашего алгоритма на практике. Во-первых, как упоминалось выше, наше решение по сглаживанию не может полностью устранить все разрывы. Однако во всех случаях мы смогли сделать менее заметными за счет увеличения глубины обхода. Кроме того, результаты зачастую преувеличены так , как этот алгоритм дает нам только приближенную видимость. Для контроля глубины occlusion мы предоставим некоторые настраиваемые параметры, которые являются полезными для нахождения ошибок или для получения желаемого реалистичного результата.12.6.1 Увеличение сходимости
Напомним, что этот метод приближено получает видимость, путем итеративного использования occlusion метода. В наших экспериментах мы пришли к выводу, что этот алгоритм получает не уникальный решение для обычных сцен. В частности, архитектурные сцены с высокой occlusion получаются 2 решениями. Чтобы избавиться от этого, мы итеративно применим первоначальный occlusion алгоритм для вычисления occlusion диск на диск на несколько ходов, как и раньше. Тогда мы усилим сходимость путем введения взвешенного минимума последних двух результатов для каждого диска. Рисунок 9 представляет полученные результаты, достигнутые таким образом. Пример 3 показывает код.Рисунок 9 Преимущество использования взвешенного минимума
Пример 3. Увеличение сходимости.
- float o0 = texture2DRect(occlusion0, diskLocation).x;
- float o1 = texture2DRect(occlusion1, diskLocation).x;
- float m = min(o0, o1);
- float M = max(o0, o1);
- // weighted blend
- occlusion = minScale * m + maxScale * M;
12.6.2 Настраиваемые параметры
Мы отмечали, что наш метод в целом , как правило, завышает ambient occlusion. В самом деле в полностью закрытых средах получает черную сцену! В общем, ambient occlusion может необязательно получаться такой, в какой мы заинтересованы.В целом, мы могли бы быть заинтересованы в том, что функция предоставляла ambient occlusion для ближайших теней, но гладко уменьшалась с расстоянием. Такая функция будет предоставлять контрастные детали, но не будет полстью затенять окружающую среду. Чтобы контролировать этот эффект вводятся 2 параметра.
Расстояние затухания
Во-первых, мы позволяем, чтобы вклад occlusion одного элемента(будь то диск или треугольник) был обратно пропорционален расстоянию до его расположения. Настройка этого параметра приводит ,как правило, к более яркому результату, рисунок 10 подтверждает это. Пример 4 показывает детали.Рисунок 10 Результат в зависимости от параметров.
Пример 4. Смягчение Occlusion в зависимости от расстояния
- // Compute the occlusion contribution from an element
- contribution = solidAngle(. . .);
- // Attenuate by distance
- contribution /= (1.0 + distanceAttenuation * e2);
Треугольник затухания
Мы также должны уменьшить вклад occlusion от треугольника на высшем уровне иерархии. Напомним, что 2 фактора влияют на видимость точка –треугольник: мы производим отсечение каждого треугольника на плоскость и модулируем форм фактор за счет треугольной occlusion. Сочетание этих двух факторов может не правильно оценить видимость так, как форм фактор отсеченного треугольника уменьшается за счет модуляции. Мы можем компенсировать это за счет повышения силы occlusion треугольника прежде, чем оно умножается на форм фактор и добавляется к сумме. Низкие значения этого параметра подчеркнуть такие особенности , как складки и трещины, которые в ином случае были бы проигнорированы. Высокие значения уменьшат влияние крупных, удаленных треугольников, которые вероятнее всего не видны. В частности, вы можете посмотреть ,как этот параметр оказывает влияние на затенение лестницы на рисунке 10.Пример 5 показывает детали.
Пример 5 Треугольник затухания
- // Get the triangle's occlusion.
- float elementOcclusion = . . .
- // Compute the point-to-triangle form factor.
- contribution = computeFormFactor(. . .);
- // Modulate by its occlusion raised to a power.
- contribution *= pow(elementOcclusion, triangleAttenuation);
12.7 Будущая работа
Мы представили надежный алгоритм вычисления высокого качества ambient occlusion. Мы получали мягкие, плавные тени и резкие контрастные местные детали путем адаптивного приближения теней.
Мы пришли к выводу , что эта адаптивный алгоритм не ограничивается вычислением ambient occlusion. В книге Bunnell’а показано, как это схема может быть использована для расчета рассеянного освещения. Мы также отметим, что основой метода рассеивания может быть создан с такой же иерархической моделью. Как показано на рисунке 12, мы можем осуществить метод многократного рассеивания (Jensen и Bühler 2002) путем вычисления излучения на каждый диск, а затем заменой вызовов функций solidAngle () и multipleScattering (). Пример 6 показывает детали.Рисунок 11 Метод многократного рассеивания чрез Иерархические интеграции.
Пример 5 Реализация многократного рассеивания
- float3 multipleScattering(float d2,
- float3 zr, // Scattering parameters
- float3 zv, // defined in
- float3 sig_tr) // Jensen and Buhler 2002
- {
- float3 r2 = float3(d2, d2, d2);
- float3 dr1 = rsqrt(r2 + (zr * zr));
- float3 dv1 = rsqrt(r2 + (zv * zv));
- float3 C1 = zr * (sig_tr + dr1);
- float3 C2 = zv * (sig_tr + dv1);
- float3 dL = C1 * exp(-sig_tr/dr1) * dr1 * dr1;
- dL += C2 * exp(-sig_tr/dv1) * dv1 * dv1;
- return dL;
- }
12.8 Литература
· Bunnell, Michael. 2005. "Dynamic Ambient Occlusion and Indirect Lighting." In GPU Gems 2, edited by Matt Pharr, pp. 223–233. Addison-Wesley.· Jensen, Henrik Wann, and Juan Buhler. 2002. "A Rapid Hierarchical Rendering Technique for Translucent Materials." In ACM Transactions on Graphics (Proceedings of SIGGRAPH 2002) 21(3).
· Sillion, François X., and Claude Puech. 1994. Radiosity and Global Illumination. Morgan Kaufmann.
Комментариев нет:
Отправить комментарий