stringtranslate.com

Трафаретный буфер

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

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

В простейшем случае буфер трафарета используется для ограничения области рендеринга (трафаретирования). Более продвинутое использование буфера трафарета использует сильную связь между Z-буфером и буфером трафарета в конвейере рендеринга . Например, значения трафарета могут автоматически увеличиваться/уменьшаться для каждого пикселя, который не проходит или проходит тест глубины.

Простая комбинация теста глубины и модификаторов трафарета делает возможным огромное количество эффектов (таких как объемные тени трафарета , двухсторонний трафарет, [1] композиция, декалькирование, растворение, затухание, смахивание, силуэты, контурное рисование или выделение пересечений между сложными примитивами ), хотя они часто требуют нескольких проходов рендеринга и, следовательно, могут сильно нагружать графическое оборудование.

Наиболее типичным применением по-прежнему является добавление теней в 3D-приложения . Также используется для плоских отражений.

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

Доступ к буферу трафарета и его модификаторам в компьютерной графике можно получить с помощью таких API, как OpenGL , Direct3D , Vulkan или Metal .

Архитектура

Трафаретный буфер обычно разделяет то же пространство памяти, что и Z-буфер, и обычно соотношение составляет 24 бита для Z-буфера + 8 бит для буфера трафарета или, в прошлом, 15 бит для Z-буфера + 1 бит для буфера трафарета. Другой вариант — 4 + 24, где 28 из 32 бит используются, а 4 игнорируются. Трафаретный и Z-буферы являются частью кадрового буфера, связанного с буфером цвета. Первым чипом, доступным для более широкого рынка, был Permedia II от 3Dlabs, который поддерживал однобитный буфер трафарета.

Биты, выделенные в буфер трафарета, могут использоваться для представления числовых значений в диапазоне [0, 2 n -1], а также в виде булевой матрицы (n — количество выделенных битов), каждая из которых может использоваться для управления определенной частью сцены. Также возможна любая комбинация этих двух способов использования доступной памяти.

Тест трафарета

Тест трафарета или трафаретная печать относится к операциям над пикселями/фрагментами (попиксельные операции), расположенным после альфа-теста и перед тестом глубины . Тест трафарета гарантирует, что нежелательные пиксели не попадут в тест глубины. Это экономит время обработки сцены. Аналогично, альфа-тест может предотвратить попадание соответствующих пикселей в тест трафарета.

Сам тест выполняется над буфером трафарета до некоторого значения в нем, или измененного или использованного, и выполняется с помощью так называемой функции трафарета и операций трафарета. Функция трафарета — это функция, с помощью которой значение трафарета определенного пикселя сравнивается с заданным опорным значением. Если это сравнение логически истинно , тест трафарета проходит. В противном случае — нет.

При этом возможная реакция, вызванная результатом сравнения трех различных состояний-глубин и трафаретных буферов:

Для каждого из этих случаев можно задать различные операции над исследуемым пикселем. В функциях трафарета OpenGL опорное значение и маска, соответственно, определяют функцию glStencilFunc. В Direct3D каждый из этих компонентов настраивается индивидуально с помощью методов SetRenderState устройств, находящихся в данный момент под контролем. Этот метод ожидает два параметра, первый из которых является условием, которое задается, а другой — его значением. В порядке, который был использован выше, эти условия называются D3DRS_STENCILFUNC, D3DRS_STENCILREF и D3DRS_STENCILMASK.

Операции трафарета в OpenGL настраивают функцию glStencilOp, которая ожидает три значения. В Direct3D, опять же, каждое состояние задает определенный метод SetRenderState. Три состояния, которые могут быть назначены хирургии, называются D3DRS_STENCILFAIL, D3DRENDERSTATE_STENCILZFAIL и D3DRENDERSTATE_STENCILPASS.

Z-бой

Из-за отсутствия точности в Z-буфере копланарные полигоны, которые находятся на небольшом расстоянии или перекрываются, могут быть изображены как одна плоскость с множеством нерегулярных поперечных сечений. Эти сечения могут различаться в зависимости от положения камеры и других параметров и быстро меняются. Это называется Z-борьбой. Существует несколько решений этой проблемы:

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

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

- Раздвигайте полигоны дальше друг от друга, что ограничивает возможности художника по созданию сложной сцены.

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

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

Объем тени

Объем тени — это метод, используемый в 3D-компьютерной графике для добавления теней к визуализированной сцене. Впервые они были предложены Фрэнком Кроу в 1977 году [2] как геометрия, описывающая трехмерную форму области, скрытой от источника света. Объем тени делит виртуальный мир на две части: области, которые находятся в тени, и области, которые не находятся в тени.

Реализация теневых объемов с помощью трафаретного буфера обычно считается одной из самых практичных универсальных техник затенения в реальном времени для использования на современном оборудовании для 3D-графики. Она была популяризирована видеоигрой Doom 3 , а конкретная вариация техники, используемая в этой игре, стала известна как Carmack's Reverse .

Размышления

Отражение сцены рисуется как сама сцена, преобразованная и отраженная относительно «зеркальной» плоскости, что требует нескольких проходов рендеринга и использования буфера трафарета для ограничения областей, где работает текущий проход рендеринга:

  1. Нарисуйте сцену, исключая зеркальные области – для каждого зеркала заблокируйте Z-буфер и цветовой буфер.
    1. Визуализируйте видимую часть зеркала
    2. Тест глубины настроен таким образом, что каждый пиксель проходит для ввода максимального значения и всегда проходит
  2. для каждого зеркала:
    1. Тест глубины настроен таким образом, что он проходит только в том случае, если расстояние до пикселя меньше текущего (поведение по умолчанию)
    2. Матричное преобразование изменяется для отражения сцены относительно плоскости зеркала.
    3. Разблокируйте Z-буфер и цветовой буфер
    4. Нарисуйте сцену, но только ту ее часть, которая находится между зеркальной плоскостью и камерой. Другими словами, зеркальная плоскость также является плоскостью отсечения
    5. Снова блокирует цветовой буфер, тест глубины настроен так, что он всегда проходит успешно, сбрасывает трафарет для следующего зеркала.

Плоские тени

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

Другая проблема, которая может или не может проявиться, в зависимости от техники, — это проектирование большего количества полигонов в одной части тени, что приводит к более темным и более светлым частям одного и того же оттенка. Все три проблемы можно решить геометрически, но из-за возможности непосредственного использования аппаратного ускорения это гораздо более элегантная реализация с использованием буфера трафарета: 1. Включить освещение и источники света 2. Нарисовать сцену без полигонов, на которые должны проецироваться тени 3. Нарисовать все полигоны, на которые должны проецироваться тени, но без источников света. При этом буфер трафарета, пикселю каждого полигона, будет присвоено определенное значение для земли, к которой они принадлежат. Расстояние между этими значениями должно быть не менее двух, поскольку для каждой плоскости будут использоваться два значения для двух состояний: в тени и ярко. 4. Отключить любое глобальное освещение (чтобы гарантировать, что следующие шаги повлияют только на отдельный выбранный источник света) Для каждой плоскости: Для каждого источника света: 1. Отредактировать буфер трафарета и только те пиксели, которые несут определенное значение для выбранного уровня. Увеличить значение всех пикселей, которые проецируются на объекты между заданным уровнем и яркостью. 2. Разрешить только выбранному свету рисовать уровень, на котором часть ее конкретного значения не изменилась.

Пространственные тени

Реализация буфера трафарета для пространственного рисования теней — это любая тень геометрического тела, объем которого включает часть сцены, которая находится в нем. Если какая-либо часть сцены принадлежит этому объему, свет не освещается, в противном случае он освещается. Эта проблема усугубляется увеличением количества источников света, но не решает количество областей, на которые падают тени. Существует несколько решений проблемы, но мы следовали следующему алгоритму: 1. Нарисовать сцену без света 2. Заблокировать Z-буфер и буфер цвета, чтобы они не могли вносить изменения Для каждого источника света 1. Использовать подробную информацию о сцене (Z-буфер) для заполнения буфера трафарета только на тех участках сцены, где объемная тень отсутствует или не видна из существующих зданий. 2. Разблокировать буфер для цвета и настроить функцию Z-буфера, чтобы разрешить поправки только там, где значение глубины равно существующему 3. Нарисовать сцену, освещенную только этим источником света, но только для части сцены, проходящей тест трафарета

Каждый из этих отрывков подразумевает, что можно использовать чистый трафаретный буфер.

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

Другие приложения

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

Другая реализация включает область визуализации при моделировании твердых тел методом конструктивной твердотельной геометрии (CSG), где буфер трафарета совместно с Z-буфером может успешно решать задачи булевых операций SOLiD.

OpenGL

glEnable ( GL_STENCIL_TEST ); // по умолчанию не включено glStencilMask ( stencilMask ); // разрешить запись в буфер трафарета, по умолчанию (0xFF) без маски. glClearStencil ( clearStencilValue ); // очистить значение трафарета, по умолчанию = 0 glStencilFunc ( func , ref , mask ); // по умолчанию GL_ALWAYS, 0, 0xFF, всегда проходить тест трафарета glStencilOp ( fail , zfail , zpass ); // по умолчанию GL_KEEP, GL_KEEP, GL_KEEP, не изменять буфер трафарета glClear ( GL_STENCIL_BUFFER_BIT ); // очистить буфер трафарета, заполнить (clearStencilValue & stencilMask)        

Тест: (ссылка и маска) функция (значение трафарета и маска)

В зависимости от трех возможных условий функции трафарета/функции глубины.

1. Функция проверки трафарета не работает:

 Если, скажем, func — GL_NEVER, тест трафарета всегда будет неудачным. Ни Color/Z-буферы не изменяются. Буфер трафарета изменяется в соответствии с glStencilOp fail. Если сказать glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP), то GL_REPLACE имеет место и stencilValue = (ref & stencilMask) // станет ref

2. Функция проверки трафарета прошла успешно/Функция проверки глубины не прошла успешно:

 Если, скажем, func — это GL_ALWAYS, тест трафарета всегда будет пройден, но тест глубины может не пройти. Ни Color, ни Z-буфер не изменяются. Буфер трафарета изменяется согласно glStencilOp zfail. Если сказать glStencilOp(GL_KEEP, GL_INCR, GL_KEEP), то имеет место GL_INCR и stencilValue = (stencilValue+1) // станет 1

3. Проходы функции трафарета/проходы функции глубины:

 Если, скажем, func — GL_ALWAYS, тест трафарета всегда будет пройден. Если тест глубины также пройден. Оба Color/Z-буфера изменены. Буфер трафарета изменен согласно glStencilOp zpass. Если, скажем, glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP), то значения трафарета не изменяются, изменяются только цвет и Z-буферы.

Обычно буфер трафарета инициализируется путем установки масок Z-буфера и буфера цвета в значение false, а затем установки соответствующего значения ссылки для буфера трафарета путем каждый раз провала теста трафарета.

 // отключить цвет и Z-буферы glColorMask ( GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE ); glDepthMask ( GL_FALSE ) ;      glStencilFunc ( GL_NEVER , 1 , 0xFF ); // никогда не проходит тест трафарета glStencilOp ( GL_REPLACE , GL_KEEP , GL_KEEP ); // заменяем значения буфера трафарета на ref=1 glStencilMask ( 0xFF ); // буфер трафарета свободен для записи glClear ( GL_STENCIL_BUFFER_BIT ); // сначала очищаем буфер трафарета, записывая значение трафарета по умолчанию (0) во все буферы трафарета. draw_stencil_shape (); // в пикселях формы трафарета в буфере трафарета заменяем значения буфера трафарета на ref = 1             

Теперь используйте инициализированный буфер трафарета и проверку трафарета, чтобы записывать только в те места, где значение трафарета равно 1:

 // включить цвет и Z-буферы. glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ); glDepthMask ( GL_TRUE );      // больше не нужно изменять буфер трафарета при проходе трафарета и глубины. glStencilMask ( 0x00 ); // также можно получить с помощью glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);   // тест трафарета: пройти тест трафарета только при stencilValue == 1 (предполагая, что тест глубины пройдет успешно.) // и записать фактическое содержимое в буфер глубины и цвета только в местах расположения формы трафарета. glStencilFunc ( GL_EQUAL , 1 , 0xFF ); draw_actual_content ();      

Смотрите также

Ссылки

  1. ^ «Методы буферизации трафарета (Direct3D 9) — приложения Win32».
  2. ^ Кроу, Франклин С.: «Теневые алгоритмы для компьютерной графики», Компьютерная графика (Труды SIGGRAPH '77) , т. 11, № 2, 242-248.