OpenGL - еще один шаг на пути к более быстрому рендерингу QUADS - PullRequest
1 голос
/ 19 октября 2011

Я немного экспериментировал и теперь могу вывести на экран около 3 миллионов GL_QUADS, используя

glDrawArrays(GL_QUADS, 0, nVertexCount);

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

ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

и

glUnmapBuffer(GL_ARRAY_BUFFER);

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

По моему опыту, использование отображения VBO почти в два раза быстрее, чем использование массивов кучи для данных вершин. Откуда мне знать? Потому что, поскольку я рендерил 3 миллиона GL_QUADS, частота кадров значительно ниже, чем 30 кадров в секунду. Я просто могу наблюдать своими глазами, как частота кадров в два раза выше для VBO.

Я также сделал замечание, что дважды вызывать glDrawArrays для каждого заполненного объекта буфера вершин (что приводит к удвоению числа квадратов для рендеринга, но после усилия для потоковой передачи данных вершин) - лишь незначительно медленнее, чем рендеринг только однажды. Поэтому я предполагаю, что основным узким местом является потоковая передача данных вершин в объекты буфера вершин (двухъядерный процессор с частотой 2 ГГц занят на 60% !!).

Прямо сейчас каждая вершина занимает 3 плавания плюс 2 плавания для координат текстуры. (Всего 20 байт). Я думаю, что я мог бы сократить эту сумму до 3 GL_SHORT плюс 2 GL_SHORT для координат текстуры. использование матриц перевода (всего 5 байт), но это ускорит только в 4 раза. (И как-то sizeof (GL_SHORT) дает 4 в моей системе, поэтому я тоже не уверен в этом.)

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

Я уверен, что мне все еще не хватает какого-то важного момента в процессе, но я просто не могу понять, что это такое. Есть предложения?

EDIT: Это свободные квадраты, как в системе частиц. (Или, скорее, потому, что у каждого может быть своя текстура (текстуры взяты из подтекстов одного, поэтому не требуется обширного связывания;)))

Ответы [ 3 ]

2 голосов
/ 20 октября 2011

Я уверен, я все еще упускаю важный момент в процессе

Смысл должен быть Нужно ли рисовать 3 МБ треугольников? вместо Как мне преодолеть аппаратный лимит?

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

Как я понимаю, вам нужно обновлять буферы вершин при рендеринге; Таким образом, вы отображаете объект буфера, обновляете данные, снимаете карту и визуализируете. Я полагаю, вы делаете это повторно. В этом случае вы должны учитывать скорость передачи от CPU к GPU; Вы можете уменьшить данные, необходимые для рендеринга сцены? Может быть, интерполировать ключевые позиции вершин?

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

В 1920x1080 пикселей 2 МБ ... Мне нужно использовать 2 МБ треугольников для его рисования? Возможно, фрагментный шейдер будет работать лучше.

Существует множество методов, используемых для снижения нагрузки на обработку (как на CPU, так и на GPU) и скорости передачи:

  • выбраковка
  • уровень детализации
  • инстансированный рендеринг
  • ключевая анимация
  • скелетная анимация
1 голос
/ 19 октября 2011

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

Может быть, вершинный или геометрический шейдер может сделать это вместо этого?* Во всяком случае, есть игры, которые даже довольно старые, но каждый кадр рендерит намного больше 3 миллионов примитивов на экране каждый раз (и они неизбежно должны передавать эти вершины, потому что ни один графический процессор не может хранить столько данных)

3000000 * 20 bytes = 60 megabytes, что легко доступно даже для более старых графических процессоров.

1 голос
/ 19 октября 2011

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

  1. Рисуйте треугольники, а не четырехугольники.В конечном итоге, квадроциклы все равно будут разделены на трис (графическое оборудование оптимизировано для обработки треугольников).
  2. Когда у вас есть большие объекты, состоящие из такого количества треугольников, вы будете использовать полосы и вентиляторы везде, где сможете (уменьшаетколичество данных вершин, которые нужно отправить от 3N до N + 2).
  3. Умное кэширование данных (особенно при рендеринге больших сцен) является жизненно важным.Как вы заметили, передача данных является узким местом в системе.Таким образом, в основном каждый движок сильно оптимизирован, чтобы избежать ненужной передачи данных.Это зависит от приложения, хотя.Там это также тема, о которой можно написать (и было) много книг.

Я могу порекомендовать эти книги как вступление к теме:

http://www.realtimerendering.com/

http://www.gameenginebook.com/

...