Я смотрел на отображение теней и вижу, как некоторые записывают квадратное расстояние до текстуры глубины в проходе тени, в то время как некоторые используют фактические значения глубины. Есть ли причина отдавать предпочтение одному другому? Кажется быстрее, просто использовать фактические значения глубины?
В комментариях к одному из ответов я заметил, что вы сослались на другой ответ, который я написал, и я хотел убедиться, что вы поняли оригинальный контекст этого ответа.
Хотя ответы до сих пор были сосредоточены на сложности самого фактического сравнения, они не учитывают, какое влияние оказывает изменение значения, хранящегося в аппаратном буфере глубины, на производительность построения карты теней. Вы обеспокоены последствиями раннего отклонения Z, и это действительная проблема, но она повлияет только на производительность карты теней строительство как я объясню ниже.
Кроме того, имейте в виду, что ответ, на который вы ссылаетесь относится к теневым картам на основе кубических карт. У них есть свой собственный набор проблем, с которыми приходится сталкиваться из-за уникального способа их построения и выборки, и поэтому сравнение немного отличается от того, что вы увидите в других контекстах.
Это сжатие не экономит место для хранения (на самом деле, оно добавляет немного дополнительной памяти), но оно позволяет много более быстрый буфер очищает и выбирает. Вместо того, чтобы записывать один и тот же цвет или глубину для каждого пикселя в буфере, каждый фрагмент может быть помечен как «чистый» и задан чистый цвет / глубина. Когда приходит время выбрать цвет / глубину для пикселя, первое, что происходит, — это то, что плитка, к которой принадлежит пиксель, просматривается, если вся плитка чистая, то цвет плитки возвращается вместо того, чтобы проходить через проблему извлечения. фактический пиксель из памяти.
Много, на самом деле. Эта иерархическая структура памяти прекрасно подходит для одновременного отклонения больших групп фрагментов, потому что минимальная / максимальная глубина для всей величины пикселей в пикселях может быть определена в одной специализированной операции памяти. Это означает, что запись в буфер цвета / глубины намного сложнее (необходимо обновить флаги и т.п. для каждого фрагмента), но аппаратное обеспечение специально разработано для такой работы, и большую часть времени вам не нужно делать ничего особенного, чтобы извлечь из этого пользу.
Теперь, хотя растеризатор выполняет простую работу с фиксированными функциями, он делает довольно умные вещи, когда применима иерархическая Z-буферизация (Hi-Z). Учитывая тот факт, что все примитивы являются плоскими, если растеризатор может гарантировать, что фрагментный шейдер не собирается изменять глубину, он может выполнять грубую обработку (например 1 тест на плитку в сжатом буфере глубины) тест глубины с использованием значения глубины мин / макс и уничтожение нескольких фрагментов перед затенением / смешиванием. Если этот крупнозернистый тест пройден или фрагментный шейдер записывает свою собственную глубину, то каждый фрагмент должен быть закрашен и затем впоследствии проверяется на глубину буфера на индивидуальной основе. Теперь, в вашем случае, фрагментный шейдер довольно прост, поэтому затраты на излишнее затенение фрагментов не будут такими большими, как обычно, а смешивание также не является фактором при проходе только на глубину.
Тем не менее, необходимость выполнения поздней проверки глубины для фрагментов, которые полностью закрыты, является пустой тратой времени, которого Hi-Z мог бы избежать. Измеримые затраты на рендеринг только по глубине на самом деле связаны с нагрузкой на ЦП внешнего интерфейса, вызванной самими вызовами отрисовки (проверка состояния, сериализация команд и т. Д.). Предполагая, что ваш проход только по глубине будет группироваться эффективно, вы можете выжать немного больше производительности, сделав тест глубины более эффективным. Просто не ожидайте увидеть огромное улучшение производительности, есть несколько причин, описанных выше, почему Hi-Z лучше работает для более традиционного рендеринга.
Кстати, если вам нужна визуальная сводка большинства из того, что я только что объяснил, посмотрите Вот.
В конце концов, правильное использование иерархической Z-буферизации во время построения вашей карты теней не даст огромный прирост производительности, но он может перевесить полученный при сокращении количества арифметических команд, необходимых для сравнения глубины. Это в основном зависит от того, как часто вы обновляете свою карту теней. С одной стороны, действительно не имеет значения, насколько эффективно оборудование заполняет вашу карту теней, если вы делаете это только один раз (статично). С другой стороны, если вам придется рисовать 6 независимых карт теней для каждого источника света, будет существенное улучшение производительности, если вы сможете уменьшить количество времени, необходимое для прорисовки каждой из них.
Слон в комнате здесь, который не рассматривается, — это количество времени, необходимое для извлечения глубины из карты теней в первую очередь (гораздо больше времени, чем вы сравниваете). Вы можете ускорить построение и сравнение теневых карт, но некоторые из самых больших преимуществ — улучшение повторное строительство (выборочная) производительность.
Например, сглаживание теней VSM может быть выполнено с использованием традиционной фильтрации текстур вместо множества извилистых выборок и сравнений, которые вы должны выполнить для других методов. Это делает сглаженную реконструкцию из VSM более эффективной. Поскольку VSM основан на дисперсии, он не требует хранения глубины перспективы … вы можете использовать линейное расстояние, если хотите, для этого алгоритма нет разницы. Хотя строительство (хранение д и д2) сложнее, если вам нужно сглаживание, оно может быть более эффективным.
Ясно, что не существует универсального подхода, который вы сохраняете на своей карте теней в значительной степени зависит от вашего алгоритма.
На самом деле использование квадратов значений требует меньше вычислительных усилий. Чтобы определить длину вектора вы делаете sqrt(r·r)
, Если вы сравните длину двух векторов, это будет sqrt(r_0·r_0) > sqrt(r_1·r_1)
но sqrt
строго монотонная функция, так r_0·r_0 > r_1·r_1
то есть сравнение значений в квадрате в равной степени верно, но оно сохраняет вычисление квадратных корней.
Что касается квадрата расстояния по сравнению с фактической глубиной, это просто зависит от ваших требований, исходя из моего опыта: если я использую что-либо, включающее квадратные корни, я предпочитаю использовать квадраты значений, так как квадратные корни требуют больших вычислительных ресурсов, тогда как квадраты дешевы. С другой стороны, если у меня нет математики с квадратными корнями, я использую прямые значения глубины. Я постараюсь изложить немного:
Перед рендерингом сцены: визуализируйте ее на этапе предварительной обработки с камерой в положении источника света, чтобы сгенерировать сцену из POV источника света. Все пиксели, которые видны с этой позиции, не могут быть в тени, поэтому при удалении все остальные пиксели должны быть в тени.
Было бы легко, если бы мы могли как-то пометить все пиксели, которые достигаются светом, однако это может быть громоздким и занимать много памяти.
Метод 1: (проверка глубины)
Таким образом, мы храним расстояние каждого освещенного пикселя до источника света в буфере глубины. При рендеринге сцены мы рассчитываем расстояние любого визуализированного пикселя до положения освещения. Если это расстояние равно сохраненной глубине в той позиции пикселя, мы знаем, что тот же самый пиксель был виден от света и, следовательно, освещен. Если расстояние больше, мы знаем, что этот пиксель не был виден с точки зрения света и находится в тени.
Метод 2: (карта теней)
Теперь, в зависимости от деталей реализации, вы можете хранить данные пикселей для карты теней, используя плавающие точки или упакованные в целые числа для карты цветов (ссылка 1) и использовать алгоритм, подобный тому, что приведен в связанной книге GPUGems, однако для обычного отображения глубины теста глубины можно избежать простых расстояний (ссылка 2).
Все сводится к тому, насколько детально вы хотите отобразить карты теней, и сколько вычислений вы хотите выполнить: для рендеринга в реальном времени (игры, простой рендеринг САД и т. Д.) Меньше времени тратится на тонкости и дополнительные лучше, поэтому мы используем трюки, такие как квадратные значения, а не квадратные корни (в википедии есть хороший порядок сложности базового текста (я знаю, что обычно его не используют в качестве источника) Вот).
Я старался сделать это как можно более кратким, поэтому, возможно, что-то пропустил, дайте мне знать, если вы хотите получить больше информации, или если мое мнение не имеет смысла, и я буду обновлять с более подробной информацией / разъяснениями 🙂