Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  VSync in multi-threaded Game  (Read 1738 times)
0 Members and 1 Guest are viewing this topic.
Offline hvince95
« Posted 2012-12-07 04:38:11 »

Is there any way to get vSync to work for one thread (the main thread where rendering is done, all opengl is done in this thread), and allow a seperate, logic thread to operate at maximum speed?  Currently, vSync lowers the rendering thread FPS to below 60 (60 is what it sould be), and the logic thread is also lowered partially compared to if there is no vSync.
Display.sync(60) has similar effects, though the frame rate differences are not as significant.
Is there any way to fix it, or is I dumb?
Offline theagentd
« Reply #1 - Posted 2012-12-07 05:02:16 »

Seems like a problem on your end. VSync only affects the OpenGL thread. You're probably doing some kind of synchronization between your logic and rendering thread which leads to that behavior.

Your goal is a bit weird though. Usually you'd either have a fixed updating speed (30 updates per sec or so) and let rendering run as fast as possible, or you'd have a delta time step and just update once, render once in the same thread. Using a delta time in the first place is a pretty bad idea due to how floating point numbers work...

Myomyomyo.
Offline hvince95
« Reply #2 - Posted 2012-12-07 05:42:29 »

For real? haha.
I always thought that you should let the logic update as fast as possible (with interpolation), and only render at a specific frame rate (same as the screens refresh rate preferebly).
Currently, I have been updating and rendering once in the same thread, and the delta values dont seem to be giving me any troubles.  Seems that I probably shouldnt worry about splitting logic and rendering into seperate threads.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd
« Reply #3 - Posted 2012-12-07 10:32:16 »

Delta values have two problems: When the FPS is low, the time step is low. That means that your physics integrations are less accurate since objects are moved a longer distance between collision tests. If a player gets a 1 second lag-spike because his anti-virus decides that now is the absolute best time ever to do a virus scan, or he ran out of RAM so something has to be swapped back from harddrive, the physics will advance 1 whole second in a single update. Shaders might be compiled by the driver. Maybe the user just tabbed into the game and it switched to fullscreen mode which took some time. That might cause objects to tunnel through walls since they can easily make a long enough jump to completely miss the wall in 1 second. The player might fall through objects, shots might miss, etc if a frame is unusually long.

At high FPS we get a problem with floating point precision instead. Floating point numbers have different precision at different values. A higher value has a lower decimal precision. Multiplications and divisions can usually retain much of their precision, but addition (and especially subtraction) can get huge precision problems. With an extremely high FPS (1000) even doubles can run into trouble. Consider the following code:

1  
2  
3  
4  
velocityY += gravity * delta;

x += velocityX * delta;
y += velocityY * delta;


If velocityY is a high value and the delta is extremely small, the first line might not do a thing! The precision of velocityY might be too low to represent the change, and it might be rounded to the same value as it was before! With a high enough update speed (= a low enough delta) people would not be affected by gravity! It might not be that extreme, but gravity might affect you weirdly and inconsistently depending on the current FPS.

By putting logic in a separate thread without any synchronization, your update thread might run at 100 000 updates per second depending on how much is going on since there's no rendering to at least keep the frequency down to 5000 (that's when graphics cards start making weird whistling sounds). The problem is therefore MUCH worse in your case. No, fixed time steps are much better and have other benefits beside not exploding at extremely low or high FPS.

Myomyomyo.
Offline hvince95
« Reply #4 - Posted 2012-12-07 11:15:45 »

That was a long, but really interesting answer,
thankyou very much!
I never thought variable timestep for a game was so frowned upon, all websites make it seem much better than fixed timestep!  So what would be the best way to sort this out then?  Should I have both logic and rendering update at 60 frames per second, same as the refresh rate, or have rendering update at 60, and logic at 120?  Are you saying I should completely eliminate the interpolation factor (I have seen some game loops where the interpolation is passed to the render function, which does it there.  What is all this about?).
This would make life easier for me, however it seems too simple! Grin
Offline Varkas
« Reply #5 - Posted 2012-12-07 13:25:03 »

At high FPS we get a problem with floating point precision instead. Floating point numbers have different precision at different values. A higher value has a lower decimal precision. Multiplications and divisions can usually retain much of their precision, but addition (and especially subtraction) can get huge precision problems.

In a space flight game I once made I was wondering why my ship wouldn't move anymore. It had turned out that the movement delta, compared to the ships position, was such a tiny number, that the add operation diod not add anything to the big position value anymore (doubles have 48 bits for the actual precision, I believe - so if you add values which are more than 48 apart, it's like adding zero).

Even this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
    public void testDouble()
    {
        double v = 1.0;

        for(int i=0; i<100; i++)
            v += 0.1;        
       
        System.out.println("" + v);
    }


==> 10.999999999999979

This is beacuse 0.1 can't be represented as a finite fraction in 2's complement.

If you need precision, stick to integers and longs Wink

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline theagentd
« Reply #6 - Posted 2012-12-07 16:43:30 »

If you need fixed precision, stick to integers and longs Wink
FTFY. Just don't EVER use a delta time step with integers. That's literally suicide. xD

Delta time steps have done funny things in big commercial games like Call of Duty. At some specific FPS points (125, 250 and 333) your jump height increases markedly allowing you to get outside the map or to places you aren't supposed to be able to get to.
<a href="http://www.youtube.com/v/OUgcnBMJ9-s?version=3&amp;hl=en_US&amp;start=" target="_blank">http://www.youtube.com/v/OUgcnBMJ9-s?version=3&amp;hl=en_US&amp;start=</a>


What you want is pretty much fixed step logic combined with rendering at a very high speed. Therefore it's a good idea to set the update rate low enough to make sure that the game doesn't slow down on older computers, but fast enough to not introduce noticeable delay (usually manifested as "input delay" since that's what players actually notice). A good idea is to do 30 updates per second. It's possible to keep your current threaded design, but I don't think it's worth the additional complexity.

You also want rendering to be decoupled from updating. We'd rather run the game at 15 FPS than reduce the game speed in an extremely heavy scene, so we need to make sure that we can do multiple updates per rendered frame. This is easy to implement of course, just render when we have time over.

However, we also want the game to be able to run faster than 30 FPS, so we will need to use interpolation for our rendering to get smooth movement for objects at 60 FPS or any other FPS than 30. A game that did not include such interpolation was Command & Conquer Generals, so the game's FPS is locked to the update rate, which in turn depends on the game speed setting. Not a very good design in other words.

I'd recommend this article which gives a good overview of good and bad game loops: http://www.koonsolo.com/news/dewitters-gameloop/. It's not Java but it should be easy to understand, although the variable names are a bit weird. Dammit, now I feel like I have to port it!  Tongue

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
private final int UPDATES_PER_SECOND = 30;
private final long NANOS_PER_UPDATE = 1000000000L / UPDATES_PER_SECOND;

//The number of updates we can do in a row before we force a render. Gives a minimum FPS of 6 FPS before the game starts to slow down.
//This is to ensure that the game does not just call update() forever if update() takes too long and so we actually render the game now and then.
private final int MAX_FRAMESKIP = 5;

...

long nextUpdate = System.nanoTime();
long lastUpdate = nextUpdate;

while(running){
    int updates = 0;
    while(nextUpdate > System.nanoTime() && updates < MAX_FRAMESKIP){
        update();
       
        lastUpdate = nextUpdate; //Save the last updateTime, we need it for rendering
        nextUpdate += NANOS_PER_UPDATE;
        updates++;
    }
   
    //We now calculate our interpolation alpha, which is ratio of how we'll blend the last position
    //with the current position.
    //Also cap it to 1.0 since there's a veeeery minor chance that this might produce a value over 1.0
    //which would cause us to extrapolate (or crash depending on how you implement things ^^').
    float interpolationAlpha = Math.min((float)(System.nanoTime() - lastUpdate) / NANOS_PER_UPDATE, 1);
   
    renderWithInterpolation(interpolationAlpha);
}


The article actually does EXTRApolation, not interpolation. It's trying to predict where objects are moving. Instead, I would interpolate between the last state and the current state, at the cost of having a small (input) delay instead of trying to predict the future causing objects to continue into each other before being corrected when the next frame detects their collision. In short, each object needs to know its position last frame and its current position, and you linearly interpolate between those two based on an interpolation alpha value like this:
float interpolatedX = lastX * (1 - alpha) + currentX * alpha;

Myomyomyo.
Offline hvince95
« Reply #7 - Posted 2012-12-09 03:56:50 »

Thankyou so much!!!
You have no idea how much smoother this makes the game loop, no more nasty lag spikes and much simpler physics to code.  All while maintaining, if not improving, the overall look!  I combined your game loop, the one you linked, and the one by Eli (I think) found at http://www.java-gaming.org/index.php?topic=24220.0.
This is the game loop I will be using for all from now on!  The results can be found here:
http://www.java-gaming.org/topics/untitled-2d-side-scroller/28019/view.html
Offline theagentd
« Reply #8 - Posted 2012-12-09 04:23:13 »

Glad I could help. Even getting something as "basic" as a game loop right is hard nowadays!

Myomyomyo.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (38 views)
2014-10-17 03:59:02

Norakomi (29 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (56 views)
2014-10-14 00:39:48

TehJavaDev (55 views)
2014-10-14 00:35:47

TehJavaDev (46 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!