OpenGL ES 线程中的 Android 时序不是单调的 [英] Android timing in OpenGL ES thread is not monotonic

查看:20
本文介绍了OpenGL ES 线程中的 Android 时序不是单调的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在我的 Android 应用中测量循环动画/粒子/等的时间间隔.应用程序是动态壁纸,因此它不会阻止系统按比例缩小时钟以节省电量.因此,所有测量最后一帧之间的时间间隔的方法都不能测量单调时间 - 我体验到的动画不一致地减慢和加速.

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.

我已经使用了所有可能的方法来检索系统时间 - 它们都不是单调的(即使 SystemClock.elapsedRealtime()System.nanoTime()保证是单调的,但不是它们.

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).

如果我将手指放在屏幕上以防止省电,所有动画都是流畅的.这个问题在 Nexus10 上非常明显,在第一代 Nexus7 上稍微明显,在 Nexus4 上根本不存在.

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();
}

推荐答案

根据你的代码大纲,你的 onDrawFrame() 方法在伪代码中稍微扩展一下我认为你在做什么代码如下:

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()

此序列的问题在于,您从总动画时间中丢失了第 1 点和第 2 点之间的时间.您需要确保所有 deltaTime 值的总和(即应用于动画的时间)涵盖动画的整个挂钟时间.根据您使用的逻辑,情况并非如此.您只需将一次通话的结束到下一次通话的开始之间的时间相加.您没有考虑执行该方法所需的时间,这可能很重要.

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

关键是你每帧只调用一次 elapsedRealtime().

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

这篇关于OpenGL ES 线程中的 Android 时序不是单调的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆