суббота, 30 апреля 2011 г.

Синильный рендеринг и поверхностное рисование–Часть 1

 

Ссылка на статью оригинал:

GPU Gems - Chapter 15. Blueprint Rendering and "Sketchy Drawings"

В этой главе мы рассмотрим два способа аппаратно-ускоренного, не фотореалестичного рендеринга: синильный рендеринг и поверхностное рисование.

Структурирование и усиление видимых и закрытых особенностей архитектурных планов и технических деталей являются существенными методиками для того, чтобы визуализировать сложные составные объекты и для того, чтобы иллюстрировать позицию, схему размещения, и соотношение их компонентов. Синильный рендеринг - новая техника мультипроходного рендеринга, основанная на усилении видимых и наиболее важных невидимых ребер 3D объектов. Первоначально слово "blueprint" расшифровывалось как: фотографическая печать белым цветом на светло-синем фоне или синим цветом на белом фоне специально для копировальных карт, машинных чертежей и архитектурных планов. Синильный рендеринг представляет собой прозрачную копию объекта, обозначенного только его контуром. Он способствует легкому пониманию структуры комплексов зданий, компоновку деталей, что позволяет упростить создание архитектурных планов, промышленных чертежей и дизайнов.

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

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

Поверхностное рисование – это техника рендеринга в реальном времени для создания набросков важных видимых ребер и внутренних цветных заплаток, произвольных 3D геометрий, даже вне их геометрической границы. Вообще говоря, при поверхностном рисовании мы делаем набросок 3D геометрии, тем самым создавая неопределенность и “меловые” цветные заплатки, создающие небрежность в рисунке. Объединяя оба варианта, в результате мы получаем мультяшный эффект, именно он притягивает внимание к персонажу и сцене в целом.

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

15.1 Основные принципы

Синильный и поверхностный рендеринги построены на трех единых принципах: (1) сохранение изображений геометрии сцены при промежуточном рендере, (2) осуществить выделение контура объекта, и (3) и применить рендер спрайта глубины. Мы кратко опишем эти понятия в следующих разделах.

15.1.1 Промежуточные результаты рендеринга

Мы обозначим 2D данные, полученные из 3D геометрии и рендеринга текстуры, как промежуточные результаты рендеринга. Также, мы реализуем G-буфер (Сэйто и Такахаши 1990), который сохраняет свойства геометрии в 3D geometry. (см. Также главу 9 этой книги, "Отсроченное затенение в S.T.A.L.K.E.R.," программная реализация этой идеи в реальном рендеринге.) Мы создаем буфер нормалей и z-буфер, путем рендеринга закодированных нормалей и z-значений 3D геометрии напрямую в 2D текстуру, см. Рисунок 15-1. В методе многопоточного рендеринга, мы создаем промежуточные результаты рендеринга один раз, и потом они могут использоваться в последовательности прохождений рендера. Технически, мы используем аппаратные возможности рендеринга в текстуру. Это позволяет нам рендерить значения высокой точности(цвета) и буферы высокой точности(как в текстурах).

clip_image001

Figure 15-1 Steps in Creating an Edge Map

15.1.2 Усиление ребер

Для извлечения важных видимых ребер из 3D геометрии на объектной основе, мы реализуем технику усиления ребер изображения (Ниенхаус и Дёллнер 2003). Важные видимые ребра включают в себя силуэт, грань и изогнутые ребра. Мы получаем эти ребра путем обнаружения разрывов в буфере нормалей и z-буфере. Для этих целей мы текстурируем выравненную четверть, у которой выделены края, используя текстуры и вычисляя координаты текстуры (s, t) для каждого фрагмента четверти, созданных в таком же порядке, каком они запрашивают координаты окна. Отбор соседних тикселей (пикселей текстуры) позволяет нам извлечь разрывы, как результаты значений интенсивности. Собрание значений интенсивности составляют ребра, которые мы рендерим прямо в единую текстуру, которую назовем карта ребер. Рисунок 15-2 отображает буфер нормалей, z-буфер и результаты карты ребер.

clip_image002

Рисунок 15-2 Z-буфер, буфер нормалей, и карта ребер для каждого слоя

15.1.3 Рендеринг спрайта глубины

В принципе, спрайт глубины – это 2D изображение, которое содержит дополнительное z-значение в каждом пикселе для тестирования глубины. Для наших целей, мы реализуем рендеринг спрайта глубины следующим образом:

  1. Мы рендерим выравненную, затекстурированную четверть с текстурой высокой точности, содержащую z-значения.
  2. Применяем специальный фрагмент программы построения теней(шейдер), который заменяет фрагмент z-значений в четверти, с z-значениями принятыми от текстуры. Для оптимизации мы дополнительно убираем фрагмент, если его z-значение равно 1—которое обозначает глубину дальнего отрезка плоскости. В другом случае, этот фрагмент-шейдер высчитывает RGBA значения цвета этого фрагмент.
  3. Рендеринг продолжается с обычным тестом глубины. Если фрагменты прошли тест, буфер кадров будет заполнен цветом и z-значениями спрайта глубины.

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

15.2 Синильный рендеринг

Для синильного рендеринга мы выбираем видимые и невидимые ребра 3D геометрии. Видимые ребра – это ребра, которые непосредственно видно в виртуальную камеру; невидимые – это ребра, которые закрыты плоскостью 3D геометрии; проще сказать, их не видно. Чтобы извлечь ребра, мы объединяем технику глубинной очистки (Эверитт 2001) и технику усиления ребер. Сгенерировав один раз, мы сравниваем видимые и невидимые ребра как светокопии в буфере кадров.

15.2.1 Глубинная очистка

Глубинная очистка – это техника воздействия на каждый фрагмент основы и извлечения 2D слоев из 3D геометрии в отсортированном по глубине порядке. В общем говоря, глубинная чистка последовательно очищает слои с уникальной сложностью глубины.

Фрагменты, прошедшие обычный тест глубины, определены минимальным z-значением каждого пикселя. Но мы не можем определить фрагмент, который пришел вторым (третьим и т.д), соблюдая их сложность глубины. Таким образом, нам нужен дополнительный тест глубины, извлекающий те фрагменты, номер слоя которых, соответствует данному порядковому номеру (Дифенбах 1996). Мы можем выбрать первых n слоев с помощью n проходов рендера.

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

Псевдокод в Листинге 15-1 показывает нашу разработку глубинной чистки. Он срабатывает при установке G в 3D геометрии. Мы рендерим G несколько раз, в результате rasterizer создает F фрагментов. Цикл работы заканчивается, когда все фрагменты будут обработаны; иначе мы обрабатываем следующий слой глубины. То есть, если число проходов рендера достигло максимальной глубины сложности, то условие выполнено.

Example 15-1. Псевдокод совмещения Глубинной чистки и Улучшения Ребер для Синильногорендеринга
procedure depthPeeling(G clip_image003 3DGeometry) begin
   i=0
   do
     F clip_image003[1] rasterize(G)
     /* Подготовка теста глубины для первого прохода рендера */
     if(i==0)  begin
       for all fragment ∈ F  begin
         bool test clip_image003[2] performDepthTest(fragment)
         if(test)  begin
           fragment.depth clip_image004 z-buffer
           fragment.color clip_image004[1] color buffer
         end
         else reject fragment
       end
     end
     else begin
       /* Подготовка второго теста */
       for all fragment ∈ F  begin
         if(fragment.depth > fragment.valuedepthLayerMap(i-1)begin
         /* Первый тест */
          bool test clip_image003[3] performDepthTest(fragment)
          if(test)  begin
            /* Второй тест */
            fragment.depth clip_image004[2] z-buffer
            fragment.color clip_image004[3] color buffer
          end
          else reject fragment
        end
        else reject fragment
      end
    end
    depthLayerMap(i) clip_image003[4] capture(z-buffer)
    colorLayerMap(i) clip_image003[5] capture(color buffer)
    /* Усиление ребер */
    edgeMap(i) clip_image003[6] edges(depthLayerMap(i),colorLayerMap(i))
    i++
  while(occlusionQuery() clip_image005 0 )  /* Конечное состояние */
 end



Два теста глубины

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

В последующих проходах (i > 0), мы создаем дополнительный тест для каждого фрагмента. Для этого теста мы используем текстуру с картой глубины слоя из предыдущих проходов рендера (i - 1). Затем мы установим координаты текстуры для фрагмента, чтобы они соответствовали координатам. Таким образом, обращение к текстуре, обеспечивает фрагмент z-значением, сохраненным в z-буфере от предыдущего прохода рендера.

Оба теста работают следующим образом:


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

Когда мы обрабатываем все фрагменты, содержимое z-буфера и цветного буфера образуют новую карту слоя глубины и цветную карту слоя. Мы можем эффективно разрабатывать дополнительные тесты глубины используя фрагмент программы.

15.2.2 Извлечение видимых и невидимых ребер

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

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

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

Важно что ребра, в картах ребер последовательности слоев глубины, появляются неоднократно, потому что локальные разрывы остаются при очистке лиц 3D геометрии. Рассмотрим следующие варианты:


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

Рисунок 15-3 отображает оба случая. Как бы то ни было, но эффективность создания карты ребер практически не зависит от количества разрывов.

clip_image007

Рисунок 15-3 Два варианта очистки 3D геометрии

15.2.3 Составляющие синильного рендеринга

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


  • Мы текстурируем выравненную четверть, его карту ребер и объединенную карту глубин.
  • Далее мы применяем часть программы (1) отвечающую за рендеринг спрайта глубины и используем соответствующую карту глубин как ввод; (2) вычисляем RGB значение фрагмента, используя значение интенсивности ребер полученного от доступа к карте ребер, например синеватый цвет; и (3) установка альфа-значения интенсивности ребра.
  • Затем мы используем смешивание цветов, учитывая значения интенсивности ребер, как смешивающих факторов для обеспечения сложности глубины.

Мы обнаружили, что на практике, достаточно смешать несколько цветных карт слоя, для создания синильного рендеринга. Оставшиеся карты слоя теряют визуальный эффект, потому что цветных в них только несколько пикселей. Чтобы изменить условия окончания рендеринга и тем самым оптимизировать его скорость, мы точно определяем минимальную часть фрагментов (в зависимости от разрешения окна) при проходе теста глубины. Таким образом, мы сокращаем количество проходов рендера, при этом сохраняя качество на высоком уровне. Для оптимального соотношения скорости и качества, мы настраиваем запрет на продолжительные запросы. Рисунок 15-4a отображает результаты синильного рендеринг для кривошипного механизма.

clip_image008

Рисунок 15-4 Различные применения в технике

15.2.4 Маскировка глубины

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


  1. Мы получаем текстуру глубины, как маску глубины необходимого компонента из предыдущего прохода рендера.
  2. В последующих проходах, мы рендерим маску глубин, как спрайт глубин, как бы очищая при этом слой глубины. Если заданная часть фрагментов прошла обычный тест глубины, мы завершаем работу данной техники. Иначе, мы должны будем очистить большую часть слоев глубин.
  3. В конце мы просто интегрируем определенный компонент в момент компонования синильного рендеринга.

Модификации данного метода показаны в псевдокоде Листинг 15-2.

Листинг 15-2. Псевдокод с измененными условиями окончания метода маскировки глубины
procedure depthPeeling(G clip_image003[7] 3DGeometry,
C clip_image003[8] geometryOfOccludedComponent) begin
   depthMask clip_image003[9] depthTexture(C)
   quad clip_image003[10] createTexturedScreenAlignedQuad(depthMask)
   renderDepthSprite(quad)    /* Рендеринг четверти как спрайт глуубины */
   int Q = occlusionQuery()  /* Количество фрагментов объекта */
   . . .
   do
   . . .
 renderDepthSprite(quad)
 int R = occlusionQuery()   /* Количество видимых фрагментов
 объекта */
  while(R<fraction(Q))         /* Конечное состояние */
 end

15.2.5 Визуализация строений с использованием синильного рендеринга


Синильный рендеринг может быть использован для отрисовки архитектурных зданий. Мы применяем синильный рендеринг для создания планов зданий. При составлении этих планов используется ортогональная камера с простыми задачами. При визуализации Храма Рамзеса II в Абудосе (Рисунок 15-4b), мы можем увидеть комнаты, колонны и статуи. Таким образом, синильный рендеринг увеличивает визуальное восприятие изображения. Эти планы создаются автоматически.

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

Комментариев нет:

Отправить комментарий