OpenGL - "ultra smooth"简单水平移动物体的动画

OpenGL - "ultra smooth" animation of simple horizontally moving object

本文关键字:移动 动画 简单 ultra smooth OpenGL 水平      更新时间:2023-10-16

我只想对某个移动对象做一个简单的动画(例如,在C++中使用OpenGL),比如说从左到右的正方形的简单水平移动。

在OpenGL中,我可以使用"双缓冲"方法,假设用户(用动画运行我的应用程序)打开了"垂直同步",这样我就可以在每次监视器刷新时调用一些函数(例如,我可以通过Qt工具包及其函数"swapBuffers"来实现这一点)。

因此,我认为,我能实现的"最平滑"的动画是"每次显示器刷新时,将正方形移动1个像素(可以是其他值)",因此在每个"帧",正方形又增加了1个像素——"我已经测试过了,它确实工作得很平滑"。

但是,当我想为"游戏逻辑"(将正方形向右移动1个像素)和"动画"(在屏幕上显示正方形的当前位置)提供"独立"线程时,问题就出现了。因为假设游戏逻辑线程是一个while循环,我将正方形移动1个像素,然后"休眠"线程一段时间,例如10毫秒,例如,我的显示器每16毫秒刷新一次——正方形的移动"不会100%平滑",因为有时显示器会刷新两次,正方形只移动了1个像素,而不是2个像素(因为显示器和游戏逻辑线程有两个"不同"的频率)——而且移动看起来"有点不平稳"。

因此,从逻辑上讲,我可以使用第一种超平滑方法,但它不能用于例如"多人"(例如"服务器-客户端")游戏,因为不同的计算机有不同的监视器频率(所以我应该使用不同的线程来处理游戏逻辑(在服务器上)和动画(在客户端上))。

所以我的问题是:是否有一些方法,使用不同的线程进行游戏逻辑和动画,对一些移动的对象进行"100%平滑"的动画,如果有的话,请在这里描述它,或者当我只是有一些"更复杂的场景要渲染"时,我只是看不到我现在看到的"小动作",当我水平移动一些简单的正方形时,我会深深地专注于它:)?

这实际上是典型的独立游戏循环行为。您可以在一个线程中管理所有与物理(运动)相关的操作,让渲染线程完成其工作。这实际上是可取的。

不要忘记游戏循环的这种实现方式是在保持恒定物理速度的同时具有最大可用帧速率。在较高的FPS下,如果没有任何其他与代码相关的问题,你根本看不到这种效果。例如,帧速率和物理之间的一些挂钩。

如果你想实现你所说的完美平滑,你可以将你的物理引擎与VSync同步。只需在刷新开始之前做所有的物理运算,而不是等待另一个。

但这一切都适用于等速物体。如果你有一个动态速度的对象,你永远不知道什么时候该把它画成"同步"。同样的问题出现了,然后你想要多个具有不同恒定速度的物体。

此外,这不是你在复杂场景中想要的。V-sync的全部思想是限制屏幕撕裂效应。你绝对不应该挂钩你的物理或渲染代码显示刷新率。你希望你的物理代码运行独立于用户显示刷新率。例如,在多人游戏中,这可能是真正的痛苦。首先,看看这个页面:游戏循环如何工作

编辑:我认为你对完美平滑的设想是不切实际的。你可以用凯文写的技巧来掩饰它。但你总是会在刷新率或显示像素化等硬件限制方面遇到困难。例如,您有一个640x480像素的窗口。现在,您希望对象水平移动。您可以通过指向右下角的矢量移动对象,但必须通过浮点数(640/480)增加对象坐标。但在渲染中,使用整数。所以你的物体是锯齿状移动的。没有办法绕过这个。在小速度下,你可以注意到它。你可以模糊它,或者让它移动得更快,但永远不要摆脱它…

  1. 允许对象移动几分之一像素。在OpenGL中,可以通过将正方形绘制到纹理(即一个像素或更大的边界)上,而不是让它只是多边形边缘,来实现正方形的示例。如果你正在渲染2D精灵图形,那么你会自动得到它(但如果你有1:1像素的艺术,当它穿过像素边界时,它会变得模糊/清晰/模糊)。

  2. 平滑(抗锯齿)多边形边(GL_polygon_Smooth)。该技术的问题在于,它不适用于基于Z缓冲区的渲染,因为它会导致透明度,但如果您正在处理2D场景,则可以确保始终向后绘制。

  3. 启用多样本/超样本抗锯齿,这比较昂贵,但不存在上述问题。

  4. 使对象具有足够的动画外观,使像素偏移不容易被注意到,因为在该边缘发生了更多的事情(即,它本身以远大于1像素/帧的速度移动)。

  5. 让你的游戏足够复杂和引人入胜,让玩家分心而不去看像素。:)