предпонятий
Хорошо, так что я собрала так:
- не использовать фиксированный конвейер (не рекомендуется или не рекомендуется)
- vbos хранит "объектные модели" (в основном n данных вершин)
- vaos описывает, как данные располагаются так, чтобы вызовы отрисовки знали, какая часть каждого vbo предназначена для какой информации о вершине (один vao может ссылаться на несколько vbos, обратное довольно сложно)
- каждый вызов отрисовки также отправляет данные вершин в шейдеры
Как я вижу 3D (опционально)
Учитывая эту информацию, я вижу, как хорошо рисовать сложные 3D-объекты в современном OpenGL. В основном вы загружаете кучу объектных моделей (возможно, из Blender или другого подобного программного обеспечения) в VBO с локальными координатами, а затем просто предоставляете для каждого экземпляра объекта свой параметр шейдера (смещение) для рисования в мировом пространстве.
Проблема / вопрос
В 2D проблемы и приоритеты совершенно иные. Вы не рисуете много сложных объектов, вам не нужны сложные проекционные матрицы, а еще много чего проще и шейдеров.
Как лучше всего рисовать часто (действительно часто, в основном, каждый кадр) изменяющуюся геометрию с помощью современного OpenGL?
В следующем параграфе вы можете увидеть некоторые идеи о проблемах (проблема окружности и прямоугольника), которые лучше определяют вид изменений, которые меня интересуют.
Мои попытки (необязательно)
Итак, я начал думать, как мне поступить с рисованием базовой 2D-геометрии на экране:
- квадрат: загрузить
[(1, 0), (1, 1), (0, 1), (0, 0)]
VBO для геометрии квадрата в локальном пространстве, затем предоставить шейдеру фактическую ширину квадрата, мировые координаты и информацию о цвете.
остывает, выглядит легко. Давайте перейдем к кругу:
- круг: треугольный веер с ... эх. насколько точность (количество вершин)? для маленьких кругов точность должна быть небольшой, а для кругов с ошибками - высокой. Очевидно, что загрузка 1 VBO не может подходить для всех случаев. Что если мне нужно добавить точность, потому что размер круга увеличен, чтобы он был больше?
Менее круто. Давайте перейдем к чему-то немного более простому, прямоугольнику:
- прямоугольник: да. нет "общей геометрии прямоугольника". У вас просто есть соотношение ширины и высоты, и все, но каждый прямоугольник, вероятно, отличается, если размер изменяется.
Как вы можете видеть, все идет вниз оттуда. Особенно со сложными полигонами и еще много чего.
Нет кода политики: P
Мне просто нужен обзор идеи, код не нужен, особенно код на C или C ++. Просто скажите что-то вроде: «создайте VBO с этими данными вершин, а затем свяжите их, ...».
Ответы:
Ваш главный вопрос, кажется, таков:
В большинстве случаев нет большой разницы между 2d и 3d OpenGL. Графический конвейер имеет одну дополнительную координату, Z, которая не будет использоваться так много в 2d, но это все.
Есть несколько способов изменить геометрию на каждом розыгрыше.
Вы можете выдвигать новые предоставленные процессором вершины каждый кадр. (См. Https://stackoverflow.com/questions/14155615/opengl-updating-vertex-buffer-with-glbufferdata для некоторых заметок о повторном использовании буферов.)
Вы можете нарисовать различные части существующего буфера, с помощью
glDrawArrays(mode, first, count)
. Если анимация повторяется, возможно, вы можете поместить предварительно вычисленные кадры с различными списками вершин в один большой буфер и нарисовать соответствующую часть буфера каждый кадр.Вы можете влиять на список вершин с помощью других данных, таких как однородный массив или текстура. В своем вершинном шейдере прочитайте эти данные и примените их соответствующим образом. Это просто другие идиомы для представления данных в графический процессор, и, вероятно, не будет иметь большой разницы в производительности.
Если у вас много экземпляров одной и той же геометрии (возможно, под влиянием атрибутов), тогда
glDrawElementsInstanced()
может быть полезноВы можете влиять на список вершин алгоритмически в вершинных, геометрических или тесселяционных шейдерах. Если анимация может быть описана математически, вы можете сохранить один и тот же список вершин и изменить только несколько шейдерных форм в каждом кадре.
И, возможно, ваша анимация может быть выражена в виде чистых текстур, причем вся анимация выполняется попиксельно процессором или предварительно визуализируется с диска.
В целом, я бы сказал: «Компьютеры быстры, сделайте так, чтобы они работали самым простым способом, каким вы можете, например, устанавливая свежие вершины, сделанные из ЦП, в каждом кадре. Затем посмотрите, достаточно ли это хорошо. Профилируйте использование батареи / ЦП во-первых, след памяти второй.
Ваш другой вопрос , перефразированный: «Какой хороший способ рисовать круги и прямоугольники?»
Круги.
С тесселяционными шейдерами (или геометрическими шейдерами) вы можете сделать вашу геометрию динамической.
Вы можете рисовать квадраты, а в вашем фрагментном шейдере только непрозрачные (альфа = 1,0) внутри радиуса и прозрачные (альфа = 0,0) вне радиуса. Тогда это идеальный пиксель каждый раз. (Сделайте ваши квадратные вершины от -1 до +1, а во фрагментном шейдере что-то вроде
outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;
. Может также немного сгладить край, там бы выглядело хорошо ...)Вы можете просто использовать, скажем, 120-треугольный вентилятор. Наверное, достаточно хорошо.
Прямоугольники.
источник
Я не могу сказать, что являюсь экспертом в этом вопросе, и в моем игровом проекте (ах) я сконцентрировался больше на 3D стороне, поэтому моя 2D сторона довольно проста, как правило, с использованием вещей, созданных для 3D стороны; и, очевидно, моя перспектива на стороне игры, поэтому моя 2D-графика больше ориентирована на блиц спрайтов, чем на геометрию. С этой точки зрения,
1) Квадраты и прямоугольники довольно просты. У меня есть только одна коробка 1x1 в VBO, которую я использую, чтобы уничтожить все. Я передаю матрицы MVP в шейдеры с этим «блоком единиц» и объединяю его с дополнительным масштабированием, чтобы масштабировать блок до нужных размеров - как вы знаете, у вас может быть различный масштаб x и y.
В своих целях я подумывал перейти от использования «блока юнитов» к какому-то движку частиц для бликов 2D спрайтов, но это уже другая история.
2) Я мало работаю с кругами, я просто использую фиксированные VBO с определенным количеством вершин. Но я мог предположить, что я мог бы сделать некоторые шаги, чтобы повлиять на количество вершин, нарисованных для круга.
При подключении данных VBO к атрибутам шейдера я использую glVertexAttribPointer. У него есть параметр шага, предназначенный для использования для чередующихся данных (которые я использую). Но может быть возможно использовать это так:
... чтобы выбрать каждую n-ю вершину из буфера, таким образом влияя на количество вершин, нарисованных для круга. Я мог бы создать несколько VAO, имеющих один и тот же VBO с разным шагом, влияющим на количество вершин, нарисованных для круга. Я не пробовал это, подумал.
В общем, да, работа с VBO и тому подобным делает настройку на стороне процессора немного более сложной, поэтому я изучал разные вещи, чтобы сделать настройку на стороне GPU (шейдеры). Тем не менее, согласно этой статье, использование VBO более эффективно на современном оборудовании, даже если вам нужно много «вмешательства» на стороне процессора:
http://www.quelsolaar.com/opengl_performance.txt
Надеюсь, что это поможет вам немного разработать и решить ваши направления.
источник