我的OpenGL ES类和代码源自Apple的GLES2Sample code sample。我用它们来显示围绕一个轴平滑旋转的3D物体,我希望它是一个恒定的旋转速度。目前,应用程序使用的帧间隔为1,每次绘制OpenGL视图时(在EAGLView的drawView
方法中),我都会将模型旋转一定角度。
在实践中,这给出了不错的结果,但并不完美:在旋转期间,当物体的大部分不在视线范围内时,渲染变得更快,因此旋转不具有恒定的角速度。我的问题是:如何让它更顺畅?
虽然我欢迎所有的建议,但我已经有了一个想法:每隔半秒测量一次渲染FPS,并在每次重绘的基础上调整旋转角度。然而,这听起来并不是很好,所以:你怎么看待这个问题,你将如何处理这个问题呢?
答案 0 :(得分:3)
我倾向于使用CADisplayLink在帧请求中触发新帧和简单时间计算,以确定推进逻辑的程度。
假设您有一个类型为NSTimeInterval的成员变量timeOfLastDraw。你希望你的逻辑能够达到每秒60次的节拍。然后(用一大堆变量来使代码更清晰):
- (void)displayLinkDidTick
{
// get the time now
NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate];
// work out how many quantums (rounded down to the nearest integer) of
// time have elapsed since last we drew
NSTimeInterval timeSinceLastDraw = timeNow - timeOfLastDraw;
NSTimeInterval desiredBeatsPerSecond = 60.0;
NSTimeInterval desiredTimeInterval = 1.0 / desiredBeatsPerSecond;
NSUInteger numberOfTicks = (NSUInteger)(timeSinceLastDraw / desiredTimeInterval);
if(numberOfTicks > 8)
{
// if we're more than 8 ticks behind then just do 8 and catch up
// instantly to the correct time
numberOfTicks = 8;
timeOfLastDraw = timeNow;
}
else
{
// otherwise, advance timeOfLastDraw according to the number of quantums
// we're about to apply. Don't update it all the way to now, or we'll lose
// part quantums
timeOfLastDraw += numberOfTicks * desiredTimeInterval;
}
// do the number of updates
while(numberOfTicks--)
[self updateLogic];
// and draw
[self draw];
}
在您的情况下,updateLogic将应用固定数量的轮换。如果你想要的是恒定旋转,那么你可以将旋转常数乘以numberOfTicks,甚至可以跳过这整个方法并执行以下操作:
glRotatef([NSDate timeIntervalSinceReferenceData] * rotationsPerSecond, 0, 0, 1);
而不是保留自己的变量。除了最微不足道的情况之外,你通常希望每次都能做一大堆复杂的事情。
答案 1 :(得分:1)
如果您不希望渲染速度变化,并且您希望使用CADisplayLink或其他动画计时器运行开环(即完全倾斜),则可以执行以下两项操作:
1)优化您的代码,使其永远不会低于60 FPS - 设备在任何情况下的最大帧速率。
2)在运行时,通过几个完整的循环测量应用的帧速率,并设置绘制速率,使其永远不会超过您的最低测量绘图性能。
我认为调整旋转角度不是解决此问题的正确方法,因为您现在正试图保持两个参数相互竞争(绘制速率和旋转速率),而不是简单地固定单个参数:绘制速率
干杯。