带网络代码的OpenGL程序示例?

时间:2009-10-10 17:55:59

标签: multithreading networking opengl boost network-programming

我想知道是否有人知道任何与OpenGL集成的网络代码示例。

基本上,我需要通过网络将某些东西的位置坐标发送到我的OpenGL显示器......然后将对象绘制到正确的位置。

我遇到的问题是将我的UDP代码与游戏集成。我基本上有一个不断更新/绘制的循环。我原本以为我可以在单独的线程中使用UDP代码并只更新共享坐标。但是,如果我的绘制函数在网络代码写入新位置之前读取位置,那么我有一个竞争条件和无效数据...但是我不能使更新或绘制循环块...

我不确定我是否应该在这里使用同步或异步网络代码。

那么,关于如何解决这个问题的任何提示?感谢

4 个答案:

答案 0 :(得分:10)

我认为你的游戏是实时的,因为你写的是你使用UDP,而你没有说过。这个问题的一般解决方案是:

  • 实现从网络缓冲状态,这会延迟稳定性。
  • 将模拟与渲染循环分离。
  • 在两个或多个状态之间进行插值,而不是将状态视为绝对状态。
  • 实施客户预测。

    缓冲

    缓冲可以提高稳定性,因为模拟总是会滞后于您收到的数据。这样,您将永远不会耗尽用于接收端仿真的数据。这种自然结果是潜伏期略有增加。使用良好的启发式(适当大小的缓冲区),模拟将永远不会赶上缓冲区,即同步永远不会阻塞,除非通信通道本身在较长时间内变得不稳定。这可能是可用带宽的突然变化,数据包丢失,延迟严重增加等。您还可以使用同步原语来阻止超时,例如1 ms。当发生超时时,您可以使用外推而不是插值(见下文),放弃一起更新缺失状态并仅更新客户端预测处理的内容(如果有),或拒绝更新任何内容,直到您与偏远的一面。

    模拟环路解耦

    您的模拟应以恒定频率进行采样。通过将模拟与渲染分离,您可以以比模拟采样更高的频率进行渲染。例如,您的模拟可以以30 fps的速度运行,但您仍可以以图形卡允许的速度进行渲染,例如300 fps。这意味着您需要通过网络发送更少的数据,但不会牺牲动画质量。

    节省带宽,在样本之间进行插值

    在两个样本之间平滑插值,而不是将数据视为绝对数据。例如可以是游戏中的玩家位置。如果您使用矢量直接移动捕捉玩家位置,则需要一些非常高的采样频率,这会淹没您的网络。通过分别在两点或三点之间使用线性或三次插值,可以获得平滑的运动,但采样点非常少。这当然需要指向插入到,所以它会增加一个增量时间的延迟,即你的时间步长。

    摘要

    编辑:好的,那么这些概念与您的问题直接相关?你的问题是一个设计问题;您只需将数据直接输入到模拟中,并在它们到达线路时进行渲染。使用wait()函数超时的互斥锁,可以修复阻塞问题,但不能解决数据不足问题。 某些延迟优于频繁超时。这就是为什么我建议实现缓冲,并将带宽使用量降低到理智水平。 只发送所需的数据,以获得足够好的结果。

  • 。响应明智,审美

有关游戏网络理论的优秀见解,请访问Glenn Fiedler博客上的文章:
Gaffer on games : networking for game-programmers
Gaffer on games : game-physics

答案 1 :(得分:2)

在单独的线程中运行网络,在新数据到达时设置标志(原子写入)并在更新/绘制中检查,然后仅进行同步。然后,您可以使用互斥锁作为共享数据。

同步部分可能与代码的其余部分相比非常高效,因此它不会对绘制循环产生太大影响。

答案 2 :(得分:2)

对于这样做的真实游戏的例子,您当然可以浏览一些合适的Quake源代码。 Quake 3 Arena使用OpenGL,并为其多人游戏使用UDP网络。

答案 3 :(得分:1)

Mads的建议非常好,所以我只想补充一下。沿着插值的方向,使用客户端预测是非常有价值的。同步位置和速度(以及可选的加速度)而不仅仅是位置。作为额外的改进,当更新到达时指示当前位置出错时,在几帧内插入到新的正确位置而不是直接捕捉到它。

这样,即使服务器更新很少,客户端也可以继续预测对象位置。如果您的对象移动顺畅,那么这可以很好地工作。这是大多数多层游戏使用的方法。每秒只能进行几次更新(以节省带宽),并且可以处理可变的网络延迟。