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

I just want to make a simple animation (for example, in C ++ using OpenGL) of some moving object - let’s say, a simple horizontal movement of a square from left to right.

In OpenGL, I can use the “double buffering” method and say that the user (running my animation application) has turned on “vertical sync”, so I can call some function every time the monitor is updated (I can achieve this, for example, using Qt toolkit and its functions "swapBuffers").

So, I think that the “smoothest” animation that I can achieve is to “move a square, for example, 1 pixel (maybe different values) every time the monitor is updated,” so on every “frame” the square is 1 pixel further - "I TEST THIS, AND THIS WORKS HARDLY TO MIX."

But the problem arises when I want to have a "separate" thread for the "game logic" (moving the square 1 pixel to the right) and for the "animation" (displaying the current position of the square on the screen). Because let them say that the game logical thread is a while loop in which I move the square by 1 pixel, and then “sleep” the stream for some time, for example 10 milliseconds, and my monitor is updated, for example, every 16 milliseconds - movement the square “will not be 100% smooth”, because sometimes the monitor is updated twice, when the square moves only 1 pixel, and not 2 pixels (because there are two “different” frequencies of the monitor and game logic) - and the movement will look "a little jerk."

So, logically, I could stay with the first super-smooth method, but it cannot be used, for example, in multiplayer games (for example, server-client), since different computers have different monitor frequencies (therefore I should use different threads for game logic (on the server) and for animation (on the clients)).

So my question is: Is there any method that uses different threads for the logic of the game and animation, which perform a “100% smooth” animation of some moving object, and if there is any other, please describe it here, or when I just had some kind of “more complicated scene for rendering”, I just won’t see this “little jerky movement” that I see now when I move some simple square horizontally and I concentrate deeply on it :)?

+7
source share
2 answers

Well, this is actually a typical individual behavior in a game loop. You control all physical actions (movement) in one thread, allowing the visualization thread to do its job. This is really desirable.

Do not forget that this way of implementing the game cycle is to have the maximum available frame rate, while maintaining a constant speed of physics. With a higher FPS, you cannot see this effect by accident unless there is another problem with the code. Some connection between frame rate and physics, for example.

If you want to achieve what you call perfect smoothness, you can synchronize your physics engine with VSync. Just do all your physics before updating, but wait for another.

But all this applies to objects with a constant speed. If you have an object with dynamic speed, you will never know when it needs to be “synchronized”. The same problem arises when you want to use several objects with different constant speeds.

Also, this is NOT what you want in complex scenes. The whole idea of ​​V-sync is to limit the effect of screen tearing. You should definitely NOT intercept your physics or rendering code to display the refresh rate. You want your physical code to work regardless of the users displaying the refresh rate. It can be a REAL pain in multiplayer games, for example. To get started, check out this page: How the Game Loop Works

EDIT: I say that your vision of perfect smoothness is unrealistic. You can disguise it using the techniques that Kevin wrote. But you will always struggle with the limitations of HW as a refresh rate or pixel display. For example, you have a window with a size of 640x480 pixels. Now you want your object to move horizontally. You can move the object by the vector header to the lower right corner, BUT you must increase the coordinates of the object by the swimming number (640/480). But when rendering, you go to integers. Thus, your object moves gear. In no case. With a little speed you can notice it. You can blur it or make it move faster, but never get rid of it ...

+6
source
  • Allow your object to move in parts of a pixel. In OpenGL, you can do this for your square example by drawing a square on a texture (that is, a pixel with one pixel or more), instead of allowing it to be just the edge of the polygon. If you create 2D sprite graphics, you get it pretty much automatically (but if you have art with a 1: 1 pixel, it will be blurry / sharp / blurry when crossing the borders of the pixels).

  • The smooth (anti-alias) edge of the polygon (GL_POLYGON_SMOOTH). The problem with this method is that it does not work with Z-buffer-based rendering, as it causes transparency, but if you are making a 2D scene, you can always pay attention to the foreground.

  • Enable multisample / super-smoothing, which is more expensive but does not have the above problem.

  • Make your object animated enough that pixel shifts are not so easy to notice, because much more happens on this edge (i.e., it moves more than 1 pixel / frame into place).

  • Make the game challenging and addictive enough for players to get distracted by viewing pixels. :)

+5
source

All Articles