Как анимация обрабатывается в не-немедленном OpenGL?

8

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

Как это достигается в не-немедленном OpenGL? Очевидно, что загрузка свежих данных VBO для каждого кадра обязательно приведет к перегружению графической шины. Я не нашел никакой литературы о современном способе сделать это. Размышляя об этом, я пришел к нескольким вариантам:

  • Атрибуты: анимация как 3D-смещение. Для каждого кадра передается различный (возможно интерполированный) атрибут смещения для каждой вершины, который применяется к одной и той же вершине каждого ключевого кадра.
  • Индексы: хранение ключевых кадров в виде абсолютных вершин и доступ к ним посредством индексации с использованием различного набора вершин для каждого ключевого кадра. Я считаю такой подход невозможным, поскольку вы не можете получить доступ к смежным ключевым кадрам и, следовательно, не можете интерполировать их. Также кажется плохой идеей для процедурной анимации.
  • Текстура: это может быть очень эластичным, но звучит как хорошее решение для меня. Опять же, анимация рассматривается как смещение XYZ для каждой вершины. Каждый ключевой кадр может храниться в одномерной текстуре, где измерение отображается на vertexID. Если я не ошибаюсь, в OpenGL 4.0 вы можете получить доступ к текстурам из любого шейдера, чтобы вы могли читать эту текстуру из вершинного шейдера и применять каждое преобразование вершин. 2D текстура может содержать несколько кадров. Вы по-прежнему выполняете интерполяцию (и если интерполяция работает для текстур вне фрагментного шейдера, в которых я не уверен, вы можете линейно интерполировать бесплатно!) Это можно применить к более сложным системам анимации, таким как анимация костей, без особых усилий.

Я обдумываю это? Кто-нибудь может пролить свет?

kaoD
источник

Ответы:

5

Я не нашел никакой литературы о современном способе сделать это.

Обычно это связано с тем, что «современный способ» анимации персонажей - это взвешивание скелета, а не смешивание вершин.

Однако, если вы настаиваете на анимации на основе вершин, вы можете это сделать. Самый простой способ - просто отправить два ключевых кадра, которые вы хотите объединить, в качестве атрибутов. У вас есть данные о положении для всех ключевых кадров; просто используйте glVertexAttribPointer(или, glVertexPointerесли вы настаиваете), чтобы выбрать конкретные ключевые кадры. Поскольку каждый ключевой кадр должен иметь свои данные позиции, хранящиеся в том же порядке (для соответствующих позиций), они могут использовать один и тот же индексный список для рендеринга.

Шейдер получает два атрибута "position", один для ключевого кадра перед текущим временем и один для ключевого кадра после. Вы также передали бы униформу, которая указывает, сколько смеси нужно сделать между ними. Вы вычисляете новую позицию как смесь между двумя ключевыми кадрами, а затем делаете обычные преобразования оттуда.

Николь Болас
источник
У вас есть какие-нибудь рекомендуемые книги или статьи для чтения, чтобы начать знакомство с написанием кода для взвешивания скелетных костей?
michael.bartnett
Я искал "как перемещать вершины", а не как делать реальную анимацию. Ну, это не так уж и отличается от веса скелетной кости, в конце концов, все сводится к движению вершин, независимо от того, являются ли они предварительно вычисленными (смешанными по вершинам) или взвешенными по кости на лету. Являются ли атрибуты единственным способом двигаться дальше? Разве подход, основанный на текстуре, все еще осуществим и быстрее, чем передача большого количества данных для каждой вершины в каждом кадре? (по крайней мере, как ключевые кадры для каждой кости, так и фактор смешения). Текстура все еще может кодировать вращение кости, и поиск текстуры выполняется намного быстрее, чем передача атрибутов.
КаоД
Также: «Поскольку каждый ключевой кадр должен хранить свои данные о положении [...], они могут использовать один и тот же индексный список для рендеринга». Разве это невозможно? Как я могу получить доступ к двум индексам для интерполяции? Разве вершинный шейдер не забывает друг о друге и даже больше о других индексах?
kaoD
@kaoD: невозможно? Разве это не то, что вы делаете в настоящее время, чтобы вычислить новую позицию вершины? Для каждой позиции в каждом массиве ключевых кадров вы смешиваете их вместе и записываете их в OpenGL. Все, что я говорю, это то, что вы предоставляете эти ключевые кадры для OpenGL и позволяете шейдеру выполнять смешивание. Что касается поиска текстур, то в иерархии «быстрых вещей в шейдерах» поиск текстур обычно находится внизу . Атрибуты более или менее бесплатны .
Никол Болас
@NicolBolas: приятно знать, что поиск текстуры происходит медленнее, чем я думал. Что я имею в виду под невозможным, так это то, что, если я не ошибаюсь, каждая вершина может «видеть» только себя в шейдере и, следовательно, не может индексировать другие вершины или получать доступ к любым другим массивам (ключевым кадрам). Что я понимаю из вашего ответа это то, что я должен передать эти две позиции ключевых кадров как атрибуты для каждой вершины вместе с равномерным коэффициентом смешения, но тогда у меня не будет массива вершин, не так ли? Хотя я только что понял, что вы можете использовать текущий ключевой кадр в качестве массива вершин и следующий кадр в качестве массива атрибутов, вы это имели в виду?
kaoD