Бесплатная реклама

Автор: Дмитрий Трифонов «DikobrAz»

Опубликовано: 11.04.2010

Изменено: 11.04.2010

Постоянная ссылка

Комментарии [24]

Визуализация водной поверхности. Быстрое преобразование Фурье на GPU





Страницы: 1 2 3 4

    5.8 Производительность и оптимизации

При визуализации океанской поверхности, самая медленная операция - вывод проекционной сетки(конечно, если не производить БПФ огромного размера). И хотя пиксельный шейдер для воды с преломлениями и отражениями не самый простой, основной удар по производительности наносит именно выборки из текстуры в вершинном шейдере. Поэтому, имеет смысл оптимизировать вывод сетки именно для вершинного процессора. Разумеется, от выборок из текстуры никак не избавиться, но можно попробовать наиболее эффективно использовать вершинный кэш, в котором хранятся вершины, прошедшие обработку в вершинном шейдере(Post-TnL cache).

Рассмотрим пару возможных топологий проекционной сетки:


Рисунок 28. Самая простая топология на основе GL_QUADS.
Колличество индексов: (sizeX - 1) * (sizeY - 1) * 4 sizeX, sizeY - колличество вершин по oX и oY соответсвенно.

Рисунок 29. Топология для отрисовки одним GL_TRIANGLE_STRIP. Для правильной отрисовки отсечение должно быть отключено.
Колличество индексов: (sizeY - 1) * sizeX * 2 + 2, sizeX, sizeY - колличество вершин по oX и oY соответсвенно.

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


Рисунок 30. Кэш промахи при импользованиии топологии 1. Красные вершины считаются два раза.

Рисунок 31. Кэш промахи при импользованиии топологии 2. Красные вершины считаются два раза.

Утверждается, что Post-TnL кэш работает по принципу FIFO: проверяем, есть ли вершина в кэше, если нет - добавляем её туда и удаляем самую старую вершину. Автору это доподлинно неизвестно, но с высокой долей вероятности можно утверждать, что он кэш вытесняет самые старые или самые редкоиспользуемые вершины. Учитывая это, можно составить топологию таким образом, чтобы из кэша не успевали удалиться вершины, которые будут использоваться при построении очередного треугольника. Например, можно построить следующую топологию:


Рисунок 32. Топология для эффективного использования вершинного кэша на основе GL_TRIANGLES.
Колличество индексов: (sizeY - 1) * (sizeX - 1) * 6 , sizeX, sizeY - колличество вершин по oX и oY соответсвенно.

Видно, что если используется принцип FIFO, к моменту построения каждой следующей полоски, кроме первой полоски в столбце, обработанные вершины ещё будут находиться в кэшэ, если длина полоски более чем в два раза меньше размера кэша. Яснее будет, если рассмотреть порядок добавления вершин в кэш: 0, 9, 10, 1, 11, 2, 12, 3, ... . Таким образом, после отрисовки первых двух треугольников из второй полоски из кэша удалятся вершины 0, 9, 10, 1 которые уже не понадобятся.

Можно пойти дальше. Видно, что в кэше идут вершины из двух рядов вперемежку, хотя при отрисовке полоски нужен только один ряд. Было бы замечательно, если бы вершины добавлялись в кэш следующим образом: 0, 1, 2, 3, 9, 10, 11, ... . Тогда длину полоски можно было бы увеличить в два раза. Сделать это можно, если использовать фиктивную полоску треугольников, составленую из вершин первого ряда, например: (0 1 2) (3 4 5), а потом уже добавлять "нормальные" полоски. Разумеется, хотя везде и говорится про полоску треугольников, это не значит что необходимо использовать GL_TRIANGLES или аналог, можно создавать такую топологию, используя GL_QUADS, GL_QUAD_STRIP, GL_TRIANGLE_STRIP, более подробно про организацию полосок и кэш можно прочитать тут.

Так же как и для предыдущих топологий на следующем рисунке визуализированы редполагаемые кэш промахи при иcпользовании оптимизированной топологии.


Рисунок 33. Кэш промахи при импользованиии топологии 3. Красные вершины считаются два раза.

Должен возникнуть вопрос: а какая максимальная длина используемых полосок или какой размер Post-TnL кэша? К сожалению, автору неизвестен ответ на вопрос. На следующем графике изображена зависимость времени отрисовки проекционной сетки от длины полоски, по нему, в частности, можно приблизительно определить размер кэша для тестируемой видеокарты: когда полоски уже не влезают в кэш, производительность должна резко упасть. На самом деле, судя по графику, она упала не резко, и не только эта особенность кажется странной. Единственное разумное объяснение, что драйвер каким-то образом сам переставляет треугольники для лучшего кэширования, но судя по всему, не всегда удачно это делает :).


Рисунок 31. Скорость отрисовки проекционной сетки при разных топологиях на 7600GT. Отражения и преломления выключены.

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

800x600, proj grid 150x600, FFT 128x128 800x600, proj grid 150x600, FFT 256x256 800x600, proj grid 150x600, FFT 512x512 800x600, proj grid 150x600, FFT 1024x1024 1280x1024, proj grid 240x960, FFT 128x128 1280x1024, proj grid 240x960, FFT 256x256 1280x1024, proj grid 240x960, FFT 512x512 1280x1024, proj grid 240x960, FFT 1024x1024
GeForce 7300Go 17 fps 12 fps 5.3 fps 1.26 fps 6.7 fps 5.7 fps 3.57 fps 1.13 fps
GeForce 7600GT 85 fps 54 fps 21 fps 5.8 fps 37 fps 29 fps 16 fps 5.3 fps
Radeon 3870HD 290 fps 275 fps 133 fps 39 fps 170 fps 143 fps 93 fps 34 fps
Radeon 4850HD 370 fps 360 fps 161 fps 47 fps 270 fps 220 fps 126 fps 43 fps
Таблица 3. Сравнение производительности тестового приложения. Водная поверхность, ~50 объектов в сцене,
построцессный туман, отражения и преломления включены.

6. Заключение

В статье были рассмотрены лишь некоторые алгоритмы синтеза водной поверхности из их великого множества. У всех этих алгоритмов совершенно разные достоинства и недостатки, а соответсвенно и сферы применения.

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

Разумеется, огромное влияние оказывает и целевая аудитория. Так например, если будет использоваться алгоритм, в котором необходимо производить выборки из текстуры или же рендерить в вершинный буфер, пользователи с видеокартами уровня ниже GeForce 6 серии вообще не смогут запустить приложение. На самом деле, учитывая производительность подобной операции, класс видеокарт, которые нормально справятся с нормальным приложением, использующем её, будет ещё меньше.

Последним фактором при выборе того или иного алгоритма оказывается сложность реализации (не смотря на то, что любой руководитель проекта поставил бы его первым пунктом). Реализовать статистическую модель синтеза поверхности океана и БПФ на GPU, определенно, сложно. Есть некоторые библиотеки, которые это делают, но вполне вероятно, что их использование окажется неприемлемым. При этом сложность модели только вершина айсберга. Как было видно из статьи, крупные волны усложняют практически все алгоритмы смежные с визуализацией водной поверхности: управление уровнем детализации, добавление отражений, физика взаимодействия с водой и т. д.

К сожалению, в статье не рассмотрены алгоритмы визуализации каустиков, пены, просвечивающих сквозь толщу воды лучей солнца, но всё это можно найти в работе Lasse Staff Jensen & Robert Golias "Deep-Water Animation and Rendering". Дополнительную информацию по статистической модели можно получить из статьи Jerry Tessendorf "Simulating Ocean Water". В работе Tarjei Kvamme Loset "Real-Time Simulation and Visualization of Large Sea Surfaces" кроме вопросов реализации статистической модели рассматиривается физическое моделирование водной поверхности как карты высот. И пожалуй, ещё стоит почитать про vertex texture fetch и R2VB, чтобы учеть ньансы и не ходить по граблям как это делал я. Пожалуй всё, удачи.

7. Источники

Интернет источники:
Статьи источники:
  • Jerry Tessendorf. "Simulating Ocean Water".
    SIGGRAPH course notes, 2004. paper
  • Lasse Staff Jensen & Robert Golias. "Deep-Water Animation and Rendering".
    Gamasutra article, September 2001. article
  • Jason L. Mitchell. "Real-Time Synthesis and Rendering of Ocean Water".
    ATI Research Technical Report, April 2005. paper
  • Philipp Gerasimov, Simon Green, Randima (Randy) Fernando. "Shader Model 3.0. Using Vertex Textures".
    NVIDIA Corporation, June 2004. paper
  • Claes Johanson. "Real-time water rendering. Introducing the projected grid concept".
    Lund University, March 2004. paper
  • Martin Mittring. "Finding Next Gen – CryEngine 2".
    Crytek GmbH, SIGGRAPH course notes, 2007. paper
  • Tarjei Kvamme Loset. "Real-Time Simulation and Visualization of Large Sea Surfaces".
    Norwegian University of Science and Technology Department of Computer and Information Science, June 2007. paper
  • Kenneth Moreland & Edward Angel. "The FFT on a GPU".
    Sandia National Laboratories, Albuquerque, 2003. paper
  • Thilaka Sumanaweera & Donald Liu. "Medical Image Reconstruction with the FFT".
    Siemens Medical Solutions USA. GPU Gems 2 chapter, April 2005. article
  • Mark Finch & Cyan Worlds. "Effective Water Simulation from Physical Models".
    GPU Gems chapter, April 2005. article

8. Демо и исходный код

Здесь вы можете скачать демострационный пример к статье: GPU_water_demo2.zip (3.2 Мб)

Исходный код можно скачать здесь: GPU_water_demo_src2.zip (0.6 Мб)

Обновлено 14 мая 2010 г.

 


 

Статья участвовала в конкурсе статей по программированию #4 (2009).

 

Страницы: 1 2 3 4