C 带计时的流动动画(OpenGL)
我正在用opengl和C编写一个小游戏。 我遇到了一个问题: 由于剪辑。。。我的动画(实际上基于GLUTIMERFUNC)没有固定的fps。 可变fps不是问题,但动画会受到影响,因此它与计时不对应,那么:fps1,pos1;fps2,pos2;fps3,位置3。。。 但是如果fps不规则,那么动画就不规则。 我会像这样实现它:fps1,pos1;(如果fps1未被提取)fps2,位置1;(fps1绘图结束,所以现在,因为我跳过了一帧)fps3,pos3 我怎么做?我会使用clock()函数,但它总是给出0C 带计时的流动动画(OpenGL),c,opengl,C,Opengl,我正在用opengl和C编写一个小游戏。 我遇到了一个问题: 由于剪辑。。。我的动画(实际上基于GLUTIMERFUNC)没有固定的fps。 可变fps不是问题,但动画会受到影响,因此它与计时不对应,那么:fps1,pos1;fps2,pos2;fps3,位置3。。。 但是如果fps不规则,那么动画就不规则。 我会像这样实现它:fps1,pos1;(如果fps1未被提取)fps2,位置1;(fps1绘图结束,所以现在,因为我跳过了一帧)fps3,pos3 我怎么做?我会使用clock()函数,但
ps:如何在opengl中强制进行v-sync?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();
}
那个时间误差的东西是为了防止舍入问题。例如,假设您以每秒70帧的恒定速度运行,并且希望每秒进行60次物理更新。如果忽略累积的错误,那么实际上会在一秒钟内运行零物理更新,因为在每一时刻,代码都会得出结论,即自上次帧绘制以来的时间长度不足以进行物理更新。如果你换一种方式,你也会遇到混叠问题,任何帧速率都不是物理更新率的整数除数
如果你没有一个显式的回溯函数,而是一个永久的循环,在垂直回溯上推出帧,但块,那么你会写同样的东西
如果您根本无法阻止垂直回溯,您可以在目标帧速率下安装一个计时器,并假装这是垂直回溯同步。你可以尽可能快地推出相框,但你可能会收到任何人对笔记本电脑或其他机器的投诉,当粉丝们出现时,这一点很明显。谢谢你的回答,但我正在寻找一种跨平台的方式,准确地说,只是在帧渲染前后获取计时器的值,没有跨平台的方式,除了实现我给出的基本算法和编写一些特定于平台的代码,以便(I)适当地调用函数;以及(ii)检索当前时间(以毫秒或其他任何单位为单位)。这就是像SDL这样的跨平台库提供SDL_gettick的原因。