Буфер глубины (Z-buffer)
Буфер глубины (Z-buffer, depth buffer) — двумерный массив данных, дополняющий двумерное изображение, где для каждого пикселя (фрагмента) изображения сопоставляется «глубина» (расстояние от наблюдателя до поверхности изображаемого объекта).
Буфер глубины применяется для одного из методов отсечения невидимой геометрии, который широко используется при построении изображений в ускорителях 3д графики.
Буфер глубины может иметь различную разрядность данных:
- 16 бит. Устаревший формат с невысокой точностью. На современных видеокартах используется редко, например для рендера в текстуру глубины на картах АТИ Радеон 9***, которые не поддерживают получения данных буфера глубины более высокой разрядности.
- 24 бита. Можно сказать, стандартный тип данных буфера глубины, в основном используется он.
- 32 бита. Формат ещё более высокой точности, но совершенно не распространён, не стоит рассчитывать на его поддержку.
Если для отрисовки нужен буфер трафарета, то данные для него будут расположены вместе с данными буфера глубины. Например, при использовании 24-битного буфера глубины на один фрагмент изображения будет приходиться 32 бита данных (не считая цвета), 8 бит которых будут представлять данные буфера трафарета.
Проверка видимости этим методом на современных видеокартах может проводиться в двух местах:
а) До выполнения фрагментного шейдера (early Z test), если фрагментный шейдер не изменяет глубину фрагмента (впрочем, вполне могут быть и другие условия, по причине которых early Z test проводиться не будет). Дополнительно к этому, современные видеокарты могут отбрасывать сразу целые блоки фрагментов, что ещё более повышает производительность.
б) После выполнения фрагментного шейдера.
Проверка производиться с использованием значения глубины текущего фрагмента в пост- проективном пространстве и предыдущего значения, хранящегося в буфере глубины. Сравнение происходит с использованием функции, выбранной пользователем. Доступны следующие функции:
Действие | Название в Direct3D10 | Название в Direct3D9 | Название в OpenGL |
false | D3D10_COMPARISON_NEVER | D3DCMP_NEVER | GL_NEVER |
Znew < Zold | D3D10_COMPARISON_LESS | D3DCMP_LESS | GL_LESS |
Znew == Zold | D3D10_COMPARISON_EQUAL | D3DCMP_EQUAL | GL_EQUAL |
Znew <= Zold | D3D10_COMPARISON_LESS_EQUAL | D3DCMP_LESSEQUAL | GL_LEQUAL |
Znew > Zold | D3D10_COMPARISON_GREATER | D3DCMP_GREATER | GL_GREATER |
Znew != Zold | D3D10_COMPARISON_NOT_EQUAL | D3DCMP_NOTEQUAL | GL_NOTEQUAL |
Znew >= Zold | D3D10_COMPARISON_GREATER_EQUAL | D3DCMP_GREATEREQUAL | GL_GEQUAL |
true | D3D10_COMPARISON_ALWAYS | D3DCMP_ALWAYS | GL_ALWAYS |
Где Znew значение глубины фрагмента и Zold предыдущее значение глубины.
Функция сравнения устанавливается функциями IDirect3DDevice::SetRenderState(D3DRS_ZFUNC, func) в DirectX, и glDepthFunc(func) в OpenGL. Также для работы следует включить тест глубины функциями IDirect3DDevice::SetRenderState(D3DRS_ZENABLE, true) в DirectX, и glEnable(GL_DEPTH_TEST) в OpenGL.
После того как тест пройден, новое значение записывается в буфер глубины. В некоторых алгоритмах требуется отключить данный шаг. Это делается вызовами IDirect3DDevice::SetRenderState(D3DRS_ZWRITEENABLE, false) или glDepthMask(false); значение по умолчанию - true.
Значение глубины точки можно рассчитать при помощи следующей формулы:
z' = zfar + znear + 1 * (-2 * zfar * znear)
zfar - znear z * (zfar - znear)
Полученное значение z' затем нормализуется в диапазон [0; 1], где 0 — у ближней плоскости отсечения, и 1 — у дальней.
Значения глубины точки не находятся в линейной зависимости от расстояния до камеры. Значения у ближней плоскости расположены очень плотно, а с увеличением дальности к дальней плоскости отсечения всё более редко. По этой причине нужно следить за расстояниями, на которых вы ставите плоскости отсечения: ближнюю плоскость не стоит ставить слишком близко! В противном случае можно получить множество артефактов изображения вдали, в особенности z-fighting, когда небольшое изменение ракурса камеры может изменить видимость близко расположенных треугольников.
Что такое Буфер глубины (Z-buffer)?
#буферы, #Direct3D, #OpenGL, #pipeline
19 апреля 2007 (Обновление: 17 ноя 2009)
Комментарии [4]