自定义vsync算法 [英] Custom vsync Algorithm

查看:90
本文介绍了自定义vsync算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用(可以)任何编程语言创建游戏时,具有固定的目标帧速率(游戏将重绘屏幕时)非常重要,但是某些语言不具有同步功能或计时器不可靠,因此有什么方法可以仅通过数学和/或通过使线程休眠来手动保持帧速率稳定?也许使用帧增量?
到目前为止,我只尝试过'sleep(targetframerate-(targetframerate-delta))' 可以认为这是因为前一帧花费的时间比目标时间长,因此可以通过使下一帧更快地进行补偿,但是它会影响自身,并简单地以指数倍地消除帧速率.
这些内置的同步功能必须以这种方法使用某种数学运算来稳定帧速率.在高端API(例如OpenGL)中如何完成?

When creating a game with any programming language (that can), it is important to have a fixed target frame rate the game will redraw the screen at, however some languages either do not have a sync function or timers are unreliable so is there any method of keeping the frame rate steady manually with only math and/or by sleeping the thread? Maybe using a frame delta?
So far I have only tried 'sleep(targetframerate - (targetframerate-delta))' This is supposed to realise that the previous frame took longer than the target so then compensates by making the next frame sooner, however it effects itself and simply kills the frame rate reverse exponentially.
These built-in sync functions must be using some sort of math in a method like this to steady the frame rate. How is it done in high-end APIs such as OpenGL?

推荐答案

创建一个运行速度非常快的计时器(例如每毫秒)(解释为什么稍后再解释),并声明这三个变量:

Create a timer that runs very quickly such as every millisecond (explained why later) and declare these three variables:

private int targetMillis = 1000/60,
            lastTime = (int)System.currentTimeMillis(), 
            targetTime = lastTime+targetMillis;

targetMilis是每个帧之间所需的毫秒数.将60更改为所需的帧速率.
lastTime只是最后一帧的时间,用于比较它的持续时间.设置为现在.
targetTime是下一帧的到期时间.现在+ targetMillis.
还可以添加一个可选的timerScaler,以缩放任何运动,以使它们不会减慢速度,因为帧速率具有:
public static float timeScaler = 1;
然后在计时器的每个刻度上运行此代码,以检查是否下一帧的时间,并设置下一帧-考虑到帧是否延迟并适当地使下一帧更快.

targetMilis is the desired amount of milliseconds between each frame. Change 60 to desired frame rate.
lastTime is simply when the last frame was, to compare how long its been. Set to now.
targetTime is what time the next frame is due. Now + targetMillis.
An optional timerScaler can be added also, to scale any movements so they don't slow down because the frame rate has with:
public static float timeScaler = 1;
Then on each tick of the timer, run this code that will check if it's time for the next frame and to set up the next - taking into account if the frame is late and making the next one sooner appropriately.

int current = (int)System.currentTimeMillis(); // Now time
if (current < targetTime) return; // Stop here if its not time for the next frame
timeScaler = (float)targetMillis/(current-lastTime);
//Scale game on how late frame is.
lastTime = current;
targetTime = (current+targetMillis)-(current-targetTime);
// Create next frame where it should be (in targetMillis) and subtract if frame was late.
[Game code here.]

我们会假设如果每个targetMillis都需要一个帧,那么我们可以为该时间创建一个计时器,但是正如您所说的,它们可能要花费几毫秒,因此,如果我们仍然使用此方法并将targetTime偏移了几秒钟,无关紧要,因为它总是会过冲,因此计时器的速度更像是精度的分辨率.

One would assume if we needed a frame every targetMillis we can just create a timer for that time, however as you said they can be a few milliseconds out therefore if we still used this method and did offset the targetTime a few back it wouldn't matter as it would always overshoot, therefore the speed of the timer is more of a resolution of accuracy.

这篇关于自定义vsync算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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