Примеры программ OpenGL с сетевым кодом? - PullRequest
1 голос
/ 10 октября 2009

Мне интересно, есть ли у кого-нибудь / известны какие-либо примеры сетевого кода, интегрированного с OpenGL.

По сути, мне нужно отправить координаты положения чего-либо по сети на мой дисплей OpenGL ... который затем нарисовал бы объект в правильном положении.

У меня проблема с интеграцией моего UDP-кода с игрой. У меня в основном есть цикл, который постоянно обновляет / рисует. Первоначально я думал, что я мог бы иметь код UDP в отдельном потоке и просто обновить общие координаты. Однако, если мои функции рисования читают позицию до того, как сетевой код завершит запись новой позиции, у меня будет состояние гонки и недопустимые данные ... однако я не могу сделать блок циклов Обновление или Рисование ...

Я не уверен, должен ли я использовать здесь код Синхронной или Асинхронной сети.

Итак, какие-нибудь советы, как я могу решить эту проблему? Спасибо

Ответы [ 4 ]

10 голосов
/ 12 октября 2009

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

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

    Буферизация

    Буферизация дает вам повышенную стабильность, потому что симуляция всегда будет отставать от данных, которые вы получаете. Таким образом, вы никогда не исчерпаете данные, которые будут использоваться для симуляции на принимающей стороне. Естественным следствием этого является небольшое увеличение задержки. При хорошей эвристике (буфер правильного размера) симуляция никогда не будет догонять буфером, т.е. синхронизация никогда не будет блокироваться, если сам канал связи не станет нестабильным в течение более длительного периода времени. Это может быть внезапное изменение доступной полосы пропускания, потеря пакетов, сильно увеличенная задержка и т. Д. Вы также можете использовать примитив синхронизации, который блокируется по тайм-ауту, скажем, 1 мс. Когда происходит тайм-аут, вы можете использовать экстраполяцию вместо интерполяции (см. Ниже), отказаться от обновления всех отсутствующих состояний и обновлять только то, что обрабатывается клиентским предсказанием (если есть), или отказаться от обновления чего-либо до тех пор, пока вы не свяжетесь с снова удаленная сторона.

    Имитация петли развязки

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

    Сохранить пропускную способность, интерполировать между выборками

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

    Резюме

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

Чтобы лучше понять теорию игровых сетей, посетите статьи в блоге Гленна Фидлера:
Gaffer на играх: сетевое взаимодействие для игровых программистов
Гэффер на игры: физика игры

2 голосов
/ 12 октября 2009

Для примера реальной игры, которая делает это, вы, конечно, можете просмотреть подходящий код Quake . Quake 3 Arena использует OpenGL и использует сеть UDP для своей многопользовательской игры.

2 голосов
/ 10 октября 2009

Запустить сеть в отдельном потоке, установить флаг (атомарную запись), когда поступят новые данные, проверить это в обновлении / отрисовке и синхронизировать только тогда. Затем вы можете использовать мьютекс для общих данных.

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

1 голос
/ 15 октября 2009

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

Таким образом, клиент может продолжать прогнозировать положение объекта, даже если обновления сервера происходят нечасто. Если ваши объекты движутся плавно, то это может работать очень хорошо. Это метод, который используется большинством многопользовательских игр. Обновления могут производиться только несколько раз в секунду (для экономии пропускной способности), а переменная задержка в сети может быть обработана.

...