在OpenGL ES线程Android的时机不单调线程、单调、时机、OpenGL

2023-09-05 03:56:37 作者:生性招摇

我测量时间间隔环形动画/粒/等在我的Andr​​oid应用程序。应用程序是一个动态壁纸所以也没有prevent系统结垢时钟下来省电。 因为这一切的方法来衡量最后的帧之间的时间间隔不测量单调的时间 - 我体验到动画不一致放缓,加快

我用一切可能的方法来检索系统时间 - 所有的人都不是单调的(甚至 SystemClock.elapsedRealtime()系统。 nanoTime()它们的保证的是单调的,但没了,他们都没有)。

如果我用手指按住屏幕prevent节电所有的动画是光滑的。 这个问题是非常明显的Nexus10,稍微明显的Nexus7第一代和Nexus4它不是present的。

下面是code摘录测量时间:

 公共无效onDrawFrame(GL10 glUnused){
    //计算定时器的基础上lastFrameTime和SystemClock.elapsedRealtime差异动画()
    ...
    //保存最后的时间戳记此帧
    lastFrameTime = SystemClock.elapsedRealtime();
}
 
Android的线程和线程池

解决方案

这是什么,我认为你正在做基于你的code纲要扩展了一下,你的 onDrawFrame()伪code方法是这样的:

  deltaTime = SystemClock.elapsedRealtime() -  lastFrameTrime
// 1点,见下面的文字
基于deltaTime更新动画
并条机
//点​​2,请参见下面的文字
lastFrameTime = SystemClock.elapsedRealtime()
 

该序列的问题是,你从你的总动画时间失去1点和2点之间的时间。你需要确保你的所有 deltaTime 值,这是应用到你的动画时代,的总和覆盖amimation整个挂钟时间。你们用什么逻辑,这是情况并非如此。您只需在结束一个呼叫到之间加入了时代开始下一个通话。你不占要执行的方法,可以是显著所需要的时间。

此可以固定与序列中的微小变化:

  currentTime的= SystemClock.elapsedRealtime()
deltaTime = currentTime的 -  lastFrameTime
lastFrameTime = currentTime的
基于deltaTime更新动画
并条机
 

关键的一点是,你只 elapsedRealtime()每帧调用一次。

I'm measuring time interval for looped animations/particles/etc in my Android app. App is a live wallpaper so it doesn't prevent system from scaling clock down for power saving. Because of this all methods to measure time intervals between last frames doesn't measure monotonic time - I experience animations inconsistently slowing down and speeding up.

I've used all possible methods to retrieve system time - all of them are not monotonic (even SystemClock.elapsedRealtime() and System.nanoTime() which are guaranteed to be monotonic but nope they are not).

If I hold a finger on screen to prevent power saving all animations are smooth. This issue is very noticeable on Nexus10, slightly noticeable on Nexus7 1st gen and on Nexus4 it is not present at all.

Here is code excerpt to measure time:

public void onDrawFrame(GL10 glUnused) {
    // calculate timers for animations based on difference between lastFrameTime and SystemClock.elapsedRealtime()
    ...
    // save last timestamp for this frame
    lastFrameTime = SystemClock.elapsedRealtime();
}

解决方案

Expanding a little on what I think you're doing based on the outline of your code, your onDrawFrame() method in pseudo code looks like this:

deltaTime = SystemClock.elapsedRealtime() - lastFrameTrime
// point 1, see text below
update animation based on deltaTime
draw frame
// point 2, see text below
lastFrameTime = SystemClock.elapsedRealtime()

The problem with this sequence is that you lose the time between point 1 and point 2 from your total animation time. You need to make sure that the total sum of all your deltaTime values, which are the times applied to your animation, covers the entire wall clock time of the amimation. With the logic you use, this is not the case. You only add up the times between the end of one call to the start of the next call. You do not account for the time needed to execute the method, which can be significant.

This can be fixed with a slight change in the sequence:

currentTime = SystemClock.elapsedRealtime()
deltaTime = currentTime - lastFrameTime
lastFrameTime = currentTime
update animation based on deltaTime
draw frame

The key point is that you only call elapsedRealtime() once per frame.

 
精彩推荐
图片推荐