Буфер глубины , также известный как z-буфер , — это тип буфера данных , используемый в компьютерной графике для представления информации о глубине объектов в трехмерном пространстве с определенной точки зрения . Глубина хранится в виде карты высот сцены, значения которой представляют расстояние до камеры, причем 0 — ближайшее. Схему кодирования можно перевернуть, при этом наибольшее число будет ближайшим к камере значением. Буферы глубины помогают при рендеринге сцены, гарантируя, что правильные полигоны правильно закрывают другие полигоны. Z-буферизация была впервые описана в 1974 году Вольфгангом Штрассером в его докторской диссертации о быстрых алгоритмах рендеринга закрытых объектов. [1] Аналогичным решением для определения перекрывающихся полигонов является алгоритм художника , который способен обрабатывать непрозрачные элементы сцены, хотя и за счет эффективности и неверных результатов.
В конвейере 3D-рендеринга , когда объект проецируется на экран, глубина (z-значение) сгенерированного фрагмента в проецируемом изображении экрана сравнивается со значением, уже сохраненным в буфере ( тест глубины ), и заменяет его, если новое значение ближе. Он работает в тандеме с растеризатором , который вычисляет цветные значения. Фрагмент, выводимый растеризатором, сохраняется, если он не перекрывается другим фрагментом.
При просмотре изображения, содержащего частично или полностью перекрывающиеся непрозрачные объекты или поверхности, невозможно полностью увидеть те объекты, которые находятся дальше всего от зрителя и за другими объектами (т. е. некоторые поверхности скрыты за другими). Если бы не было механизма управления перекрывающимися поверхностями, поверхности визуализировались бы друг на друге, не заботясь о том, должны ли они находиться за другими объектами. Выявление и удаление этих поверхностей называется проблемой скрытых поверхностей . Для проверки на перекрытие компьютер вычисляет z-значение пикселя, соответствующего первому объекту, и сравнивает его со значением z в том же месте пикселя в z-буфере. Если вычисленное z-значение меньше z-значения, уже находящегося в z-буфере (т. е. новый пиксель ближе), то текущее z-значение в z-буфере заменяется вычисленным значением. Это повторяется для всех объектов и поверхностей в сцене (часто параллельно ) . В конечном итоге z-буфер позволит правильно воспроизвести обычное восприятие глубины: близкий объект скрывает более удаленный. Это называется z-отсечением .
Z-буфер имеет ту же внутреннюю структуру данных, что и изображение, а именно 2D-массив, с той лишь разницей, что он хранит одно значение для каждого пикселя экрана вместо цветных изображений, которые используют 3 значения для создания цвета. Это делает z-буфер черно-белым, поскольку он не хранит цветовую информацию. Буфер имеет те же размеры, что и буфер экрана для согласованности.
Первичные тесты видимости (такие как отбраковка задней грани ) и вторичные тесты видимости (такие как проверки перекрытия и обрезка экрана) обычно выполняются на полигонах объектов, чтобы пропустить определенные полигоны, которые не нужны для рендеринга. Z-буфер, для сравнения, сравнительно дорог , поэтому выполнение первичных и вторичных тестов видимости освобождает z-буфер от некоторой нагрузки.
Гранулярность z-буфера оказывает большое влияние на качество сцены: традиционный 16-битный z-буфер может приводить к артефактам (называемым " z-fighting " или сшиванием ), когда два объекта находятся очень близко друг к другу. Более современный 24-битный или 32-битный z-буфер ведет себя намного лучше, хотя проблему нельзя устранить без дополнительных алгоритмов. 8-битный z-буфер почти никогда не используется, поскольку у него слишком малая точность.
Z-буферизация — это метод, используемый почти во всех современных компьютерах, ноутбуках и мобильных телефонах для выполнения 3D-графики . Основное применение сейчас — видеоигры , которые требуют быстрой и точной обработки 3D-сцен. Z-буферы часто реализуются на аппаратном уровне в потребительских видеокартах . Z-буферизация также используется (реализуется как программное обеспечение, а не как оборудование) для создания компьютерных спецэффектов для фильмов. [ необходима цитата ]
Кроме того, данные Z-буфера, полученные при визуализации поверхности с точки зрения источника света, позволяют создавать тени с помощью техники теневого картирования . [2]
Даже при достаточно малой детализации могут возникнуть проблемы с качеством, когда точность значений расстояния z-буфера неравномерно распределена по расстоянию. Более близкие значения намного точнее (и, следовательно, могут лучше отображать более близкие объекты), чем значения, которые находятся дальше. Обычно это желательно, но иногда это приводит к появлению артефактов по мере удаления объектов. Разновидность z-буферизации, которая приводит к более равномерно распределенной точности, называется w-буферизацией (см. ниже).
В начале новой сцены z-буфер должен быть очищен до определенного значения, обычно 1,0, поскольку это значение является верхним пределом (по шкале от 0 до 1) глубины, что означает, что в этой точке через пирамиду видимости нет ни одного объекта .
Изобретение концепции z-буфера чаще всего приписывают Эдвину Кэтмеллу , хотя Вольфганг Штрассер описал эту идею в своей докторской диссертации 1974 года за несколько месяцев до изобретения Кэтмелл. [a]
На более современных видеокартах для ПК (1999–2005 гг.) управление z-буфером использует значительную часть доступной полосы пропускания памяти . Для снижения затрат на производительность z-буферизации использовались различные методы, такие как сжатие без потерь (компьютерные ресурсы для сжатия/распаковки дешевле полосы пропускания) и сверхбыстрая аппаратная z-очистка, которая делает устаревшим трюк «один кадр положительный, один кадр отрицательный» (полный пропуск межкадровой очистки с использованием знаковых чисел для искусной проверки глубины).
В некоторых играх, особенно в нескольких играх, появившихся позже в жизненном цикле N64 , было принято решение либо минимизировать Z-буферизацию (например, сначала отрисовывать фон без Z-буферизации и использовать Z-буферизацию только для объектов переднего плана), либо полностью исключить ее, чтобы снизить требования к пропускной способности памяти и требования к памяти соответственно. Super Smash Bros. и F-Zero X — две игры для N64, в которых Z-буферизация была минимизирована для увеличения частоты кадров. Несколько игр Factor 5 также минимизировали или исключили Z-буферизацию. На N64 Z-буферизация может потреблять до 4 раз больше пропускной способности, чем без использования Z-буферизации. [3]
Mechwarrior 2 на ПК поддерживал разрешения до 800x600 [4] на оригинальном 4 МБ 3DFX Voodoo из-за отсутствия Z-буферизации.
В рендеринге z-culling — это раннее устранение пикселей на основе глубины, метод, который обеспечивает повышение производительности, когда рендеринг скрытых поверхностей является затратным. Это прямое следствие z-буферизации, где глубина каждого пикселя-кандидата сравнивается с глубиной существующей геометрии, за которой он может быть скрыт.
При использовании z-буфера пиксель может быть отброшен (выброшен), как только станет известна его глубина, что позволяет пропустить весь процесс освещения и текстурирования пикселя, который в любом случае не будет виден . Кроме того, для отбракованных пикселей, как правило, не будут выполняться трудоемкие пиксельные шейдеры . Это делает z-отсечение хорошим кандидатом на оптимизацию в ситуациях, когда fillrate , освещение, текстурирование или пиксельные шейдеры являются основными узкими местами .
В то время как z-буферизация позволяет не сортировать геометрию, сортировка полигонов по увеличению глубины (таким образом, используя алгоритм обратного художника ) позволяет отображать каждый пиксель экрана меньшее количество раз. Это может повысить производительность в сценах с ограниченной скоростью заполнения с большим количеством перерисовки, но если не сочетать с z-буферизацией, то возникают серьезные проблемы, такие как:
Таким образом, алгоритм обратного художника не может быть использован в качестве альтернативы Z-отсечению (без напряженной реинжиниринга), за исключением оптимизации Z-отсечения. Например, оптимизация может заключаться в том, чтобы сохранять полигоны отсортированными в соответствии с x/y-расположением и z-глубиной для предоставления границ, в попытке быстро определить, могут ли два полигона иметь взаимодействие окклюзии.
Диапазон значений глубины в пространстве камеры , подлежащий визуализации, часто определяется между значением и .
После перспективного преобразования новое значение , или , определяется как:
После ортографической проекции новое значение , или , определяется как:
где — старое значение в пространстве камеры, иногда называемое или .
Полученные значения нормализуются между значениями -1 и 1, где плоскость имеет значение -1, а плоскость имеет значение 1. Значения за пределами этого диапазона соответствуют точкам, которые не находятся в пирамиде видимости и не должны отображаться.
Обычно эти значения хранятся в z-буфере аппаратного графического ускорителя в формате с фиксированной точкой . Сначала они нормализуются до более общего диапазона, который равен [0, 1], путем подстановки соответствующего преобразования в предыдущую формулу:
Упрощение:
Во-вторых, приведенная выше формула умножается на , где d — глубина z-буфера (обычно 16, 24 или 32 бита), и результат округляется до целого числа: [5]
Эту формулу можно инвертировать и вывести для вычисления разрешения z-буфера (упомянутой ранее «зернистости»). Обратное выше :
где
Разрешение z-буфера в терминах пространства камеры будет инкрементным значением, полученным в результате наименьшего изменения целого числа, хранящегося в z-буфере, которое равно +1 или -1. Следовательно, это разрешение можно рассчитать из производной как функции :
Выражая это обратно в терминах пространства камеры, заменив на приведенное выше :
Это показывает, что значения сгруппированы гораздо плотнее вблизи плоскости и гораздо разреженнее вдали, что приводит к лучшей точности ближе к камере. Чем меньше , тем меньше точность вдали — слишком близкое расположение плоскости является частой причиной нежелательных артефактов рендеринга на более удаленных объектах. [6]
Для реализации z-буфера значения линейно интерполируются по экранному пространству между вершинами текущего многоугольника , и эти промежуточные значения обычно сохраняются в z-буфере в формате с фиксированной точкой .
Для реализации w-буфера [7] старые значения в пространстве камеры или , сохраняются в буфере, как правило, в формате с плавающей точкой . Однако эти значения не могут быть линейно интерполированы по экранному пространству из вершин — обычно их приходится инвертировать , интерполировать и затем снова инвертировать. Результирующие значения , в отличие от , равномерно распределены между и . Существуют реализации w-буфера, которые вообще избегают инверсий.
Какой буфер — z-буфер или w-буфер — обеспечит лучшее качество изображения, зависит от приложения.
Следующий псевдокод демонстрирует процесс z-буферизации:
// Сначала инициализируем глубину каждого пикселя.d(i, j) = бесконечность // Максимальная длина// Инициализируем значение цвета для каждого пикселя в соответствии с цветом фонаc(i, j) = цвет фона// Для каждого полигона выполните следующие шаги:для (каждого пикселя в проекции полигона){ // Найти глубину, т.е. z полигона // в точке (x, y), соответствующей пикселю (i, j) если (z < d(i, j)) { d(i, j) = z; c(i, j) = цвет; }}
{{cite book}}
: CS1 maint: location missing publisher (link)