Буфер глубины что это

Z-буфер или метод глубинного буфера

При просмотре изображения, содержащего непрозрачные объекты и поверхности, невозможно увидеть те объекты из вида, которые находятся позади объектов ближе к глазу. Чтобы получить реалистичное изображение на экране, удаление этих скрытых поверхностей является обязательным. Идентификация и удаление этих поверхностей называется проблемой скрытой поверхности.

Метод Z-буфера сравнивает глубины поверхности в каждой позиции пикселя на плоскости проекции. Обычно ось z представлена как глубина. Алгоритм метода Z-буфера приведен ниже:

Алгоритм:

Давайте рассмотрим пример, чтобы лучше понять алгоритм. Предположим, что данный полигон имеет следующий вид:
Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

В начале предположим, что глубина каждого пикселя бесконечна.

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Поскольку значение z, т. Е. Значение глубины в каждом месте данного многоугольника, равно 3, при применении алгоритма результат будет следующим:

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Теперь давайте изменим значения z. На приведенном ниже рисунке значения z изменяются от 0 до 3.

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

При запуске глубина каждого пикселя будет бесконечной как:

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Теперь значения z, сгенерированные на пикселе, будут другими, как показано ниже:
Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

В этом методе используются 2 буфера:

Расчет глубины:
Как известно, уравнение плоскости имеет вид:

Расчет каждой глубины может быть очень дорогим, но вычисление может быть уменьшено до одного сложения на пиксель с использованием метода приращения, как показано на рисунке ниже:
Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Обозначим глубину в точке A как Z, а в точке B — как Z ‘. Следовательно :

Следовательно, вычисление глубины может быть выполнено путем записи уравнения плоскости каждого многоугольника в (нормализованной) системе координат просмотра, а затем с использованием инкрементного метода для определения глубины Z.
Таким образом, чтобы подвести итог, можно сказать, что этот подход сравнивает глубины поверхности в каждой позиции пикселя на плоскости проекции. Глубина объекта обычно измеряется от плоскости обзора вдоль оси z системы наблюдения.
Пример :

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Пусть S1, S2, S3 — поверхности. Поверхность, ближайшая к плоскости проекции, называется видимой поверхностью. Компьютер запускается (произвольно) с поверхности 1 и помещает его значение в буфер. Это сделало бы то же самое для следующей поверхности. Затем он будет проверять каждый перекрывающийся пиксель и проверять, какой из них ближе к зрителю, а затем отображать соответствующий цвет. Как и в положении плоскости обзора (x, y), поверхность S1 имеет наименьшую глубину от плоскости обзора, поэтому она видна в этом положении.

Нужно помнить:
1) Z-буферный метод не требует предварительной сортировки полигонов.
2) Этот метод может быть выполнен быстро даже со многими полигонами.
3) Это может быть реализовано аппаратно для преодоления проблемы со скоростью.
4) Сравнение объектов с объектами не требуется.
5) Этот метод может быть применен к неполигональным объектам.
6) Аппаратная реализация этого алгоритма доступна на некоторых графических рабочих станциях.
7) Метод прост в использовании и не требует дополнительной структуры данных.
8) Значение z многоугольника можно вычислить постепенно.
9) Нельзя наносить на прозрачные поверхности, т. Е. Только на непрозрачные поверхности. Например:

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

10) Если нужно визуализировать только несколько объектов в сцене, то этот метод менее привлекателен из-за дополнительного буфера и накладных расходов, связанных с обновлением буфера.
11) Потеря времени может произойти из-за рисования скрытых объектов.

Источник

Буферы глубины

Буфер глубины или z-буфер хранит сведения о глубине для управления тем, какие области многоугольников отображаются, а какие скрываются в текущем отображении.

Средств

Буфер глубины, часто также называемый z-буфером или w-буфером, — это свойство устройства, в котором хранятся сведения о глубине, используемые в Direct3D. При отрисовке сцены на поверхности цели Direct3D может использовать память на связанной поверхности буфера глубины как рабочую область, чтобы определить, как пиксели преобразованных в растровый формат многоугольников закрывают друг друга. Direct3D использует поверхность Direct3D вне экрана в качестве цели, куда записываются окончательные значения цветов. Поверхность буфера глубины, связанная с поверхностью цели отрисовки, используется для хранения сведений о глубине, которые используются в Direct3D, чтобы определить глубину отображения каждого пикселя в сцене.

Когда сцена преобразуется в растровый формат с включенной буферизацией глубины, каждая точка на поверхности отрисовки проверяется. Значения в буфере глубины могут быть координатой z точки или ее однородной координатой w на основе координат расположения точки (x,y,z,w) в пространстве проекции. Буфер глубины, в котором используются значения z-координаты, часто называется z-буфером, а тот, в котором используются значения w-координаты, — w-буфером. У каждого типа буфера глубины есть преимущества и недостатки, которые будут подробно описаны далее.

В начале теста в буфере глубины установлено максимально возможное для сцены значение глубины. В качестве значения цвета на поверхности отрисовки используется либо значение цвета фона, либо значение цвета текстуры фона в этой точке. Каждый полигон в сцене проверяется на предмет пересечения с текущей координатой (x,y) на поверхности отрисовки.

Если он пересекается, значение глубины, которое будет координатой z в z-буфере и координатой w в w-буфере, в текущей точке проверяется, чтобы определить, меньше ли оно значения глубины, хранящегося в буфере глубины. Если значение глубины полигона меньше, оно сохраняется в буфер глубины, а значение цвета полигона записывается в текущую точку на поверхности отрисовки. Если значение глубины полигона в этой точке больше, проверяется следующий полигон в списке. Этот процесс показан на следующей схеме.

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Методы буферизации

Хотя в большинстве приложений эта функция не используется, вы можете изменить сравнение, используемое в Direct3D для определения того, какие значения следует поместить в буфер глубины и в дальнейшем на поверхность цели отрисовки. На некоторых видах оборудования при изменении функции сравнения может отключиться иерархическая проверка z-буферов.

Почти все представленные на рынке ускорители поддерживают z-буферизацию, поэтому z-буферы — один из самых распространенных типов буферов глубины на сегодняшний день. Но несмотря на широкую распространенность, у z-буферов есть определенные недостатки. Из-за особенностей выполняемых математических операций генерируемые z-значения в z-буфере часто не распределяются равномерно в диапазоне z-буфера (как правило, от 0,0 до 1,0 включительно).

В частности, соотношение между дальней и ближней плоскостями отсечения сильно влияет на неравномерность распределения z-значений. Если соотношение между расстояниями до дальней и ближней плоскостей равно 100, 90% диапазона буфера глубины занимается первыми 10% диапазона глубины сцены. В обычных приложениях для развлечения или визуального моделирования с внешними сценами часто требуется соотношение между расстояниями до дальней и ближней плоскостей в диапазоне от 1 000 до 10 000. При соотношении 1 000 98% диапазона занимается первыми 2% диапазона глубины, а при повышении соотношения равномерность распределения падает. Это может привести к скрытым артефактам поверхности дальних объектов, особенно при использовании 16-разрядных буферов глубины, наиболее широко поддерживаемой глубине.

С другой стороны, w-буфер глубины обычно обеспечивает более равномерное распределение между ближней и дальней плоскостями отсечения, чем z-буфер. Главное преимущество заключается в том, что соотношение расстояний до дальней и ближней плоскостей отсечения больше не доставляет проблем. За счет этого приложения могут поддерживать большие максимальные диапазоны, при этом обеспечивая относительно точную буферизацию глубины вблизи базовой точки визуализации сцены. W-буфер глубины не идеален и иногда может приводить к возникновению скрытых артефактов поверхности ближних объектов. Еще один недостаток использования w-буфера связан с поддержкой оборудования: w-буферизация не так широко поддерживается на оборудовании, как z-буферизация.

Для использования z-буфера требуются дополнительные ресурсы при отрисовке. Существуют различные методы оптимизации отрисовки с использованием z-буферов. Приложения могут работать быстрее при использовании z-буферизации и текстурирования за счет отрисовки сцен от передней части к задней. Текстурированные примитивы с z-буферизацией предварительно проверяются в сравнении с z-буфером на основе строк развертки. Если строка развертки скрыта ранее отрисованным полигоном, система быстро и эффективно отклоняет ее. Z-буферизация может повысить производительность, но этот метод особо эффективен при многократном отображении одних и тех же пикселей в сцене. Точные расчеты в этом случае сделать сложно, но можно добиться довольно точного приближения. Если одни и те же пиксели отображаются менее двух раз, максимальную производительность можно обеспечить путем отключения z-буферизации и отрисовки сцены от задней части к передней.

Фактическая интерпретация значения глубины зависит от конкретного обработчика.

Источник

Буфер глубины (Z-buffer)

Буфер глубины (Z-buffer, depth buffer) — двумерный массив данных, дополняющий двумерное изображение, где для каждого пикселя (фрагмента) изображения сопоставляется «глубина» (расстояние от наблюдателя до поверхности изображаемого объекта).

Буфер глубины применяется для одного из методов отсечения невидимой геометрии, который широко используется при построении изображений в ускорителях 3д графики.

Если для отрисовки нужен буфер трафарета, то данные для него будут расположены вместе с данными буфера глубины. Например, при использовании 24-битного буфера глубины на один фрагмент изображения будет приходиться 32 бита данных (не считая цвета), 8 бит которых будут представлять данные буфера трафарета.

Проверка видимости этим методом на современных видеокартах может проводиться в двух местах:
а) До выполнения фрагментного шейдера (early Z test), если фрагментный шейдер не изменяет глубину фрагмента (впрочем, вполне могут быть и другие условия, по причине которых early Z test проводиться не будет). Дополнительно к этому, современные видеокарты могут отбрасывать сразу целые блоки фрагментов, что ещё более повышает производительность.
б) После выполнения фрагментного шейдера.

Полученное значение z’ затем нормализуется в диапазон [0; 1], где 0 — у ближней плоскости отсечения, и 1 — у дальней.
Значения глубины точки не находятся в линейной зависимости от расстояния до камеры. Значения у ближней плоскости расположены очень плотно, а с увеличением дальности к дальней плоскости отсечения всё более редко. По этой причине нужно следить за расстояниями, на которых вы ставите плоскости отсечения: ближнюю плоскость не стоит ставить слишком близко! В противном случае можно получить множество артефактов изображения вдали, в особенности z-fighting, когда небольшое изменение ракурса камеры может изменить видимость близко расположенных треугольников.

Что такое Буфер глубины (Z-buffer)?

Источник

DevBurn

О разработке и не только…

WebGL Урок 8 — Буфер глубины, прозрачность и смешивание

12 thoughts on “ WebGL Урок 8 — Буфер глубины, прозрачность и смешивание ”

А почему прозрачность сохраняется при вращении куба? Грани рисуются в одном и том же порядке, а куб поворачивается. Это значит, целевая грань то спереди, то сзади, почему же эффект не меняется?

Всё дело в освещении. Передние грани лучше видно, потому что на них падает свет, их цвета получаются более насыщенными. Поэтому прозрачность выглядит довольно реалистичной.
Попробуйте установить направленному освещению Z=1. Тогда лучше будут видны дальние грани и реалистичность пропадёт.
Ещё попробуйте убрать освещение через соответствующую галку, все грани будет видно одинаково и реалистичный эффект прозрачности снова потеряется.

А почему передние грани освещены, а задние нет, когда тест глубины отключён? Кажется, что свет должен проходить без помех до задних граней.

// Back face
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0

Интересно, спасибо:) То есть, оно их затемняет (освещение)

Вы не знаете, как сменить функцию смешивания по ходу дела? Я рисую что-то в текстуру, используя функцию gl.blendFunc(gl.ONE, gl.ONE);
Затем эту текстуру хочу вывести в канвас, используя функцию gl.blendFunc(gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA);
Ничего не выводит, белый экран. Такая же реакция на любую другую функцию, кроме gl.blendFunc(gl.ONE, gl.ONE); (тогда нормально смешивается с канвасом).

Да, в прозрачности множество подводных камней. Для того, чтобы вам могли помочь, выкладывайте код на каком-нибудь ресурсе, иначе очень сложно понять, что за проблема возникла.

Здравствуйте!
А вообще возможно расположить один объект внутри другого, но внутренний объект был непрозрачным, а внешний был прозрачным?

Отмечу несколько важных моментов:
— необходимо включить смешивание gl.enable(gl.BLEND) и установить функцию смешивания gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
— нужно залить задний фон чёрным цветом, чтобы он не влиял на смешивание цветов объектов gl.clearColor(0.0, 0.0, 0.0, 1.0)
— сначала необходимо отрисовать внутренний куб, затем уже внешний, иначе при включенном gl.DEPTH_TEST мы никогда не увидим внутреннего куба, даже если внешний будет на 100% прозрачный

Пробовал разные варианты. Доходило до того, что поверх непрозрачного тела проецировалось внешнее прозрачное тело с его тыльной стороной. В Вашем варианте у прозрачного тела возникают артефакты.

Тогда другой вариант. Для более «настоящей» прозрачности я разбил куб на отдельные грани — так каждая грань будет отрисовываться как отдельный объект и будет вносить вклад в итоговый цвет. Предварительно грани необходимо отсортировать по удалённости — сначала отрисовываются более отдалённые грани, затем более близкие.

Источник

Иерархический буфер глубин

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Краткий обзор

Иерархический буфер глубин — это многоуровневый буфер глуби (Z-буфер), используемый как ускоряющая структура (acceleration structure) для запросов глубин. Как и в случае mip-цепочек текстур, размеры каждого уровня обычно являются результатами деления на степени двойки размеров буфера полного разрешения. В этой статье я расскажу о двух способах генерации иерархического буфера глубин из буфера полного разрешения.

Сначала я покажу, как генерировать полную mip-цепочку для буфера глубин, сохраняющую точность запросов глубин в пространстве координат текстуры (или NDC) даже для размеров буферов глубин, не равных степеням двойки. (В Интернете мне встречались примеры кода, не гарантирующие этой точности, что усложняет выполнение точных запросов на высоких mip-уровнях.)

Затем для случаев, в которых требуется только один уровень даунсэмплинга, я продемонстрирую, как сгенерировать этот уровень при помощи одного вызова вычислительного (compute) шейдера, использующего атомарные операции в общей памяти рабочей группы. Для моего приложения, где требуется только разрешение 1/16 x 1/16 (mip-уровень 4), способ с вычислительным шейдером в 2-3 раза быстрее, чем обычный подход с даунсэмплингом mip-цепочки в несколько проходов.

Введение

Иерархические глубины (также называемые Hi-Z) — это часто используемая в 3D-графике техника. Она используется для ускорения усечения невидимой геометрии (occlusion culling) (в CPU, а также в GPU), вычислений отражений в экранном пространстве, объёмного тумана и многого другого.

Кроме того, в GPU Hi-Z часто реализуется как часть конвейера растеризации. Быстрые операции поиска Hi-Z в кэшах на чипе позволяют целиком пропускать тайлы фрагментов, если они полностью закрыты ранее отрендеренными примитивами.

Базовая идея Hi-Z заключается в ускорении операций запросов глубин благодаря считыванию из буферов меньшего разрешения. Это быстрее, чем считывание из буфера глубин полного разрешения, по двум причинам:

Буферы Hi-Z чаще всего запрашиваются почти сразу на выходе, чтобы избежать дальнейшей обработки и выполнения более точных операций поиска в буфере полного разрешения. Например, если мы храним значения max для неинвертированного буфера глубин (в которых чем больше значение глубины, тем дальше находится объект), то можем быстро совершенно точно определить, перекрыта ли конкретная позиция в экранном пространстве буфером глубин (если её координата Z > значения (max), сохранённого в какой-то более высоком уровне (то есть с пониженным разрешением) буфера Hi-Z).

Благодаря этому тест глубин для видимых частиц в общем случае становится малозатратной операцией. (Для перекрытых геометрией частиц он более затратен, но это нас устраивает, потому что это не вызывает затрат на рендеринг, поэтому частицы по-прежнему требуют мало вычислений.)

Благодаря тому, что поиск сначала выполняется в буфере глубин пониженного разрешения (как сказано выше), время рендеринга частиц снижается максимум на 35% по сравнению со случаем, когда поиск выполняется только в буфере полного разрешения. Поэтому для моего приложения Hi-Z очень выгоден.

Теперь мы рассмотрим две техники генерирования иерархического буфера глубин.

Техника 1: генерация полной Mip-цепочки

Во многих областях использования Hi-Z требуется создание полной mip-цепочки буфера глубин. Например, при выполнении occlusion culling с помощью Hi-Z ограничивающий объём проецируется в экранное пространство и спроецированный размер используется для выбора подходящего mip-уровня (чтобы в каждой проверке перекрытия участвовало фиксированное количество текселов).

Однако в случае буферов глубин, размеры которых не соответствуют степеням двойки, всё сложнее. Так как Hi-Z для буферов глубин часто строится из стандартных разрешений экрана (которые редко являются степенями двойки), нам нужно найти надёжное решение этой задачи.

Итак, что же конкретно будет означать получаемое нами значение отдельного тексела на mip-уровне N? Это должно быть минимальное значение ( min ) из всех текселов полноэкранного буфера глубин, занимающего то же пространство в (нормализованном) пространстве координат текстуры.

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Пример чётных размеров уровней: 6 текселов на этом уровне уменьшаются до 3 на более высоком уровне. Размеры координат текстур каждого из трёх текселов высокого уровня точно накладываются на каждые два тексела нижнего уровня. (Точки — это центры текселов, а квадраты — это размеры координаты текстуры при использовании фильтрации ближайших соседей.)

В случае нечётных размеров уровней (а у буферов полного разрешения, размер которых не является степенью двойки, будет хотя бы один уровень с нечётным размером) всё становится сложнее. Для уровня N-1 нечётного размера Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что эторазмер следующего уровня (N) будет равен Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это, то есть Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это.

Это означает, что теперь у нас нет чёткого сопоставления «2 к 1» текселов уровня N-1 к текселам уровня N. Теперь размер координаты текстуры каждого тексела на уровне N накладывается на размер 3 текселов на уровне N-1.

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Пример нечётных размеров уровня: 7 текселов этого уровня уменьшаются до 3 текселов на следующем уровне. Размеры координаты текстуры трёх текселов высокого уровня накладываются на размеры трёх текселов из нижнего уровня.

Описание выше для простоты было представлено всего в одном измерении. В двух измерениях, если обе размерности уровня N-1 являются чётными, то область текселов 2×2 на уровне N-1 сопоставляется с одним текселом на уровне N. Если одна из размерностей нечётна, то область 2×3 или 3×2 на уровне N-1 сопоставляется с одним текселом на уровне N. Если нечётны обе размерности, то следует также учитывать «угловой» тексел, то есть область 3×3 на уровне N-1 сопоставляется с одним текселом на уровне N.

Пример кода

Показанный ниже код шейдера на GLSL реализует описанный нами алгоритм. Он должен выполняться для каждого последующего mip-начиная с уровня 1 (уровень 0 — это уровень полного разрешения).

Изъяны этого кода

Производительность

Я использовал приведённый выше фрагментный шейдер для генерации двух полных mip-цепочек для двух (по одному на каждый глаз) буферов глубин в своём VR-движке. В тесте разрешение для каждого глаза составляло 1648×1776, что привело к созданию 10 дополнительных уменьшенных mip-уровней (а значит, 10 проходов). На генерацию полной цепочки для обоих глаз потребовалось 0,25 мс на NVIDIA GTX 980 и 0,30 мс на AMD R9 290.

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что это

Mip-уровни 4, 5 и 6, сгенерированные из буфера глубин, соответствующего показанному выше цветовому буферу. (Стоит учесть, что бОльшая часть сцены прозрачна, а значит, не влияет на буфер глубин.) Mip-уровень 4 — первый, в котором размеры (103×111) не делятся нацело на 2.

Альтернативный способ генерации mip-цепочки

Задача описанного выше алгоритма заключается в сохранении точности запросов глубины в пространстве координат текстуры (или NDC). Для полноты (и потому, что я отказался от этой гарантии в представленной ниже технике 2) я хотел бы продемонстрировать ещё один способ, который мне встречался (например, в этой статье).

Учтите, что, как и предыдущий, этот альтернативный способ предназначен для работы с буферами полного разрешения, размеры которых не являются степенями двойки (но, разумеется, они работают и с размерами, равными степеням двойки).

В этом альтернативном способе при даунсэмплинге уровня с нечётной шириной (или высотой) вместо добавления для каждого выходного тексела дополнительного столбца (или строки) текселов из предыдущего (нижнего) уровня, мы выполняем эту операцию только для выходных текселов с максимальными индексами («крайних» текселов). Единственное, что это изменяет в представленном выше фрагментном шейдере — задание значений shouldIncludeExtraColumnFromPreviousLevel и shouldIncludeExtraRowFromPreviousLevel :

Из-за этого крайние текселы с наибольшим индексом становятся очень «толстыми», так как каждое деление на 2 нечётной размерности приводит к тому, что они занимают пропорционально всё больший интервал нормализованного пространства координат текстуры.

Недостаток такого подхода заключается в том, что становится сложнее выполнять запросы глубин высоких mip-уровней. Вместо того, чтобы просто использовать нормализованные координаты текстуры, мы сначала должны определить тексел полного разрешения, соответствующий этим координатам, а затем перенести координаты этого тексела на координаты соответствующего mip-уровня, запрос которого выполняется.

Показанный ниже фрагмент кода выполняет перенос из пространства NDC Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что этов координаты текселов на mip-уровне higherMipLevel :

Техника 2: генерация одного уровня Hi-Z при помощи вычислительного шейдера

Генерация полной mip-цепочки выполняется довольно быстро, но меня немного напрягало то, что моё приложение генерирует все эти уровни, а использует только один из них (уровень 4). Кроме устранения этой небольшой неэффективности, мне также хотелось посмотреть, насколько можно всё ускорить, если использовать для генерации только нужного мне уровня один вызов вычислительного шейдера (compute shader). (Стоит заметить, что моё приложение может останавливаться на уровне 4 при использовании решения с многопроходным фрагментным шейдером, поэтому в конце этого раздела я использовал его как основу для сравнения времени выполнения.)

В большинстве случаев использования Hi-Z требуется только один уровень глубин, поэтому я считаю, что такая ситуация встречается часто. Я написал вычислительный шейдер под собственные специфические требования (генерирование уровня 4, имеющего разрешение 1/16 x 1/16 от исходного). Похожий код можно использовать для генерации разных уровней.

Вычислительный шейдер хорошо подходит для решения этой задачи, потому что он может использовать общую память рабочей группы для обмена данными между потоками. Каждая рабочая группа отвечает за один выходной тексел (уменьшенного даунсэмплингом буфера), а потоки рабочей группы разделяют работу по вычислению min соответствующих текселов полного разрешения, обмениваясь результатами через общую память.

Я попробовал два основных решения на основе вычислительных шейдеров. В первом каждый поток вызывал atomicMin для одной переменной общей памяти.

Самым быстрым из всех этих протестированных решений с atomicMin и на NVIDIA, и на AMD оказалось решение с блоками потоков 4×4 (при котором каждый поток сам получает область текселов размером 4×4). Я не совсем понимаю, почему этот вариант оказался самым быстрым, но возможно, он отражает компромисс между конкуренцией атомарных операций и вычислениями в независимых потоках. Стоит также заметить, что размер рабочей группы 4×4 использует всего 16 потоков на warp/wave (а возможно использовать ещё и 32 или 64), что любопытно. В показанном ниже примере реализован этот подход.

В качестве альтернативы использованию atomicMin я попытался выполнять параллельное уменьшение при помощи техник, использованных в этой активно цитируемой презентации NVIDIA. (Основная идея заключается в использовании массива общей памяти того же размера, что и количество потоков в рабочей группе, а также Буфер глубины что это. Смотреть фото Буфер глубины что это. Смотреть картинку Буфер глубины что это. Картинка про Буфер глубины что это. Фото Буфер глубины что этопроходов для последовательного совместного вычисления min минимумов каждого потока, пока не будет получен окончательный минимум всей рабочей группы.)

Пример кода

При таком способе проще всего не стараться поддерживать соответствие в нормализованном пространстве координат текстуры между текселами уменьшенных буферов и полного разрешения. Можно просто выполнять преобразования из координат текселов полного разрешения в координаты текселов уменьшенного разрешения:

В моём случае (генерирование эквивалента mip-уровня 4) downscalingFactor равен 16.

Как сказано выше, этот вычислительный шейдер GLSL реализует решение с atomicMin с размером рабочих групп 4×4, где каждый поток получает из буфера полного разрешения область текселов размером 4×4. Получившийся уменьшенный буфер глубин значений min равен 1/16 x 1/16 от размера буфера полного разрешения (с округлением вверх, когда размеры полного разрешения не делятся на 16 нацело).

Производительность

Я использовал приведённый выше вычислительный шейдер для обработки буфера глубин полного разрешения с теми же размерами, которые использовались для генерации полной mip-цепочки (буферы 1648×1776 для каждого глаза). Он выполняется за 0,12 мс на NVIDIA GTX 980 и за 0,08 мс на AMD R9 290. Если сравнивать со временем генерации только mip-уровней 1–4 (0,22 мс на NVIDIA, 0,25 мс AMD), то решение с вычислительным шейдером оказалось на 87% быстрее у GPU NVIDIA и на 197% быстрее, чем у GPU AMD.

В абсолютных величинах ускорение не такое уж и большое, но важны каждые 0,1 мс, особенно в VR 🙂

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *