我正在用opengl和C编写一个小游戏。 我遇到了一个问题: 由于剪辑...我的动画(实际上基于glutTimerFunc)没有一个恒定的fps。 变量fps不是问题,但是动画会受到影响,所以它不对应于时间,那么:fps1,pos1; FPS2,POS2; fps3,POS3 ... 但如果fps不规则,那么动画就不会。 我会实现它:fps1,pos1;(如果没有绘制fps1)fps2,pos1; (fps1绘图已结束,所以现在,因为我跳过了一个帧)fps3,pos3。
我该怎么办?我会使用clock()函数,但它始终为0
ps:如何强制在opengl中使用v-sync?
答案 0 :(得分:1)
OpenGL更新是否与垂直回扫同步将以特定于平台的方式进行通信,因为它与您的平台已将OpenGL绑定到自身相关。所以它是Mac上界面设计器的勾选框,在Windows上有一个名为WGL_EXT_swap_control的WGL扩展,在X11中有一个GLX扩展。
假设您有一些方法可以安装在垂直回扫时触发的回调(例如通过Mac上的CVDisplayLink
;遗憾的是我没有使用Windows / Linux等效功能),并且您希望物理以每秒恒定的步数运行,你可以写出类似的东西:
void myRetraceFunction()
{
static unsigned int timeError = 0;
static unsigned int timeOfLastFrame = 0;
unsigned int timeNow = getTimeNow(); // assume this returns in ms
// Get time since last frame.
// Since we ignore overflow here, we don't care that the result of
// getTimeNow presumably overflows.
unsigned int timeSinceLastFrame = timeNow - timeOfLastFrame;
// Store this so that we get correct results next time around.
timeOfLastFrame = timeNow;
// Establish the number of times to update physics per second, as the
// name says. So supposing it has been 0.5 of a second since we last
// drew, we'd want to perform 0.5*200 physics updates
const unsigned int numberOfTimesToUpdatePhysicsPerSecond = 200;
// calculate updates as (updatesPerSecond * timeSinceLastFrame / 1000),
// because we're assuming time is in milliseconds and there are 1000
// of them in a second. What we'll do though is preserve any amount we'd
// lose by dividing here, so that errors balance themselves.
//
// We assume that timeSinceLastFrame will be small enough that we won't
// overflow here.
unsigned int timeSinceLastFrameNumerator =
timeSinceLastFrame * numberOfTimesToUpdatePhysicsPerSecond
+ timeError;
// calculate how much of the numerator we're going to lose to
// truncation, so that we add it next frame and don't lose time
timeError = timeSinceLastFrameNumerator % 1000;
// calculate how many physics updates to perform
unsigned int physicsUpdatesToPerform = timeSinceLastFrameNumerator / 1000;
// do the physics work...
while(physicsUpdatesToPerform--)
updatePhysics();
// ... and draw a frame
drawFrame();
}
那个timeError的东西是为了规范舍入问题。例如。假设你以每秒70帧的速度运行,并希望物理更新每秒60次。如果您忽略了累积的错误,那么您实际上会在一秒钟内运行零物理更新,因为在每个时刻代码都会得出结论:自上一帧绘制以来的时间长度不足以使物理更新具有已被要求。如果你采用其他方式,你也会遇到别名问题,任何帧速率都不是物理更新速率的整数除数。
如果你没有一个明确的回扫函数,而是一个永久循环,它会推出帧但是会阻止垂直回扫,那么你就会写出同样的东西。
如果您根本无法阻止垂直回扫,则可以按目标帧速率安装计时器并假装是垂直回扫同步。你可以尽可能快地推出框架,但是你可能会对任何拥有笔记本电脑或其他机器的人抱怨,当粉丝来的时候很明显。