OpenGL — еще один шаг на пути к более быстрому рендерингу QUADS

Я немного поэкспериментировал и теперь могу отобразить около 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 миллионов примитивов в каждом кадре (и им неизбежно приходится стримить эти вершины, потому что ни один GPU не может хранить столько данных) и при этом получить приличную частоту кадров более 100 кадров в секунду!

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

РЕДАКТИРОВАТЬ: Это свободные квадроциклы, как в системе частиц. (Или, скорее, потому, что на каждой из них может оказаться другая текстура (текстуры берутся из подтекстур одной, поэтому нет обширной привязки ;)))


person Fejwin    schedule 19.10.2011    source источник
comment
Являются ли эти свободные четырехугольники (каждый четырехугольник имеет вершины, независимые от других четырехугольников, например, в системе частиц) или это сетка, состоящая из четырехугольников?   -  person Nicol Bolas    schedule 19.10.2011
comment
Между прочим: ... уже довольно старые, но рендерят гораздо больше, чем 3 миллиона.... Я бы очень сомневался в этом. Тот факт, что мир состоит из более чем 3 миллионов треугольников, не означает, что все они рендерятся в каждом кадре. Подумайте об отсечении усеченной пирамиды видимости, отсечении порталов, PVS и т. д., и это лишь некоторые из техник, которые наверняка применяются в этих играх. Но это не значит, что это помогает в вашем случае, просто чтобы уточнить, что вы не можете просто проводить такие простые сравнения между сложностью сцены и производительностью.   -  person Christian Rau    schedule 19.10.2011
comment
@Nicol Bolas: Свободные квадрицепсы. Смотрите мою правку. Кристиан Рау: У меня есть отсечение усеченной пирамиды, но его использование потребляет больше ресурсов ЦП, чем просто запись 20 байтов. В моем случае я пытаюсь нарисовать даже более 3 миллионов квадов. Если 15 из 40 миллионов будут эффективно отброшены позже, это здорово, но мне все равно нужно будет отрендерить более 3 миллионов...   -  person Fejwin    schedule 19.10.2011
comment
@Fejwin В настоящее время, во времена чрезмерной пакетной обработки и рендеринга экземпляров, такие методы, привязанные к ЦП, такие как отбраковка усеченного конуса и тому подобное, не всегда дают предполагаемое повышение производительности (как в вашем случае, похоже). Вот почему вы не можете проводить такие простые сравнения с другими приложениями, которые были созданы с совершенно другими целями оптимизации, не говоря уже о том, что предположение, что они отображают более 3 миллионов треугольников за кадр, в любом случае, вероятно, было неверным.   -  person Christian Rau    schedule 19.10.2011
comment
@ChristianRau Они отображают меньше примитивов, чем 3 миллиона? Честно говоря, я не знаю точно, сколько это в среднем. Может быть, вы мне подскажете? В принципе я понимаю, что мой подход не оптимизирован. Любые предложения, что я могу сделать?   -  person Fejwin    schedule 19.10.2011
comment
Попробуйте умножить три матрицы на каждый квадрат для получения рендеринга. Когда все закончится, позвони мне, чтобы рассказать, как это было...   -  person Luca    schedule 20.10.2011
comment
Кстати. sizeof(GL_SHORT) равен 4, потому что GL_SHORT сопоставляется с целым числом. То, что вы ищете, скорее всего, sizeof(GLshort)   -  person Martin Gerhardy    schedule 23.12.2016


Ответы (3)


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

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

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

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

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

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

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

  • выбраковка
  • уровень детализации
  • инстансный рендеринг
  • анимация по ключевым кадрам
  • скелетная анимация
person Luca    schedule 19.10.2011
comment
Только сейчас понял, что вы совершенно правы! Я поместил все свои вершины в VBO и отрендерил их без обновления — результат все равно сильно тормозил. Следовательно, это аппаратное ограничение! =) Сейчас я сосредоточусь на переходе от четырехугольников к треугольникам, поскольку они не устарели и, надеюсь, немного повысят производительность. С этого момента я буду хранить все свои вершины в VBO навсегда без чрезмерных обновлений, так как графический процессор все равно не может отобразить всю свою память без задержек. Я узнал это сегодня! Большое тебе спасибо! знак равно - person Fejwin; 20.10.2011

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

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

В качестве входа в тему могу порекомендовать эти книги:

http://www.realtimerendering.com/

http://www.gameenginebook.com/

person cli_hlt    schedule 19.10.2011
comment
Спасибо, посмотрю эти! - person Fejwin; 19.10.2011
comment
Рисовать треугольники, а не четырехугольники, почему? это было бы просто крайне неэффективно, не так ли? четверка делит свои последние 2 вершины. так же, как это делает треугольная полоса. просто используя один верт для следующего tri. я не думаю, что они были бы такими тупыми, чтобы обманывать последние две вершины для каждого треугольника, тратя тонны памяти графического процессора, как будто каким-то образом индексация будет быстрее. я точно знаю, что больше памяти делает его медленнее. например, один цвет int против 3 цветов с плавающей запятой rgb. если бы opengl выполнял какую-либо автоматическую оптимизацию данных вершин, они бы наверняка преобразовали числа с плавающей запятой в байты. они не делают. - person Puddle; 27.09.2019
comment
и причина этого в том, что вы определяете, как будет использоваться загруженная вами память vbo. - person Puddle; 27.09.2019
comment
также вся причина для индексирования vbo заключается в том, чтобы экономить память вершин при использовании треугольников. quads, казалось, просто реализуют это автоматически. - person Puddle; 27.09.2019

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

Может быть, вершинный или геометрический шейдер может сделать это вместо этого?

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

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

person Piotr Praszmo    schedule 19.10.2011
comment
Это просто простые операции добавления и сохранения, возможно, 30 байтов для до 240 байтов данных вершин. Мой пример с 3 миллионами вершин, конечно, довольно мал. Если взять 30 миллионов, ни одна видеокарта не справилась бы с этим 3 года назад. - person Fejwin; 19.10.2011
comment
@Fejwin: Вы забываете, что многое из того, что вы видите на экране, — это повторно используемые данные. Вы можете, например, иметь только небольшое количество моделей человеческих персонажей, но путем изменения текстур и настройки нескольких матриц скинов придать им очень отчетливый вид. Также 3 года назад видеокарты с объемом памяти 512 МБ были довольно распространены. Например, я все еще работаю и разрабатываю GeForce8800GTX с 768MB RAM, которую я купил в ноябре 2006 года, т.е. почти 5 лет назад. До этого у меня был GeForce7800 с 256Мб ОЗУ, а до этого Radeon9800 тоже с 256Мб, купил 2003г. - person datenwolf; 20.10.2011
comment
@datenwolf: Кажется, я пытаюсь работать на видеокарте 2008 года, которая отстает от вашей карты 2006 года! =) (Не стоит ожидать многого от ноутбука с графическим процессором). Я думаю, вы, ребята, правы! Я мог хранить все необходимые данные на графическом процессоре. Потому что даже тогда графический процессор не мог отобразить все это за один раз с хорошей производительностью, так что это аппаратное ограничение. - person Fejwin; 20.10.2011