pouët.net

Frame dropping for previous-frame based effects?

category: code [glöplog]
 
Hi guys & gals,

So, in an ideal world when rendering an effect, all the effects are - I'm not sure how to put it correctly - let's call it, "frame number" based, so when the CPU is not strong enough to calculate the effect with a desired "n" FPS and can calculate only "k" FPS instead, at a certain point I can decide to skip rendering of "n-k" frames in order to maintain a synchronisation to a music. (I'm aware it's a simplification, but it's how roughly it works, right?).

Now: how do you deal with the above problem (i.e.: frame dropping / skipping), when the frame of effect rendered is based on the results from the previous frame, and the previous frame depends on yet another previous frame, and so on, and so forth (i.e. like in a blur effects).

Thanks in advance :)
added on the 2015-01-01 16:31:57 by argasek argasek
A - delta time based updates, like position += velocity * delta. Heavy-er math but you can run your demo at any framerate.

B - bake that data into a file and then it can be played from any position, even in reverse ect. This is used on many demos which have physics. You use interpolation and eliminate unnecessary data points to save space and make it playable at any frame-rate.

C - separate simulation from rendering... usually the rendering costs more, so you can easily drop rendering for a frame but keep the simulation running. (by rendering I mean any task necessary to make and display a frame and by simulation i mean any task necessary to make the data required for rendering)
added on the 2015-01-01 16:49:19 by musk musk
Although i must note that the delta time based method requires attention to numerical representation. You can easily run into issues where you lose data due to rounding errors... so this means that rounding errors produce side-effects and this can become quite messy if you ignore it.
added on the 2015-01-01 16:53:05 by musk musk
mu6k: thank you! In relation to the A - are these guys describing here: http://gafferongames.com/game-physics/fix-your-timestep/ the technique you've mentioned?
added on the 2015-01-01 17:01:14 by argasek argasek
And somewhat referring to the B: I was thinking on something like that, but basically my idea was to store the pre-rendered frames in the RAM (which would make sense in case of, example, 64K intro) :)
added on the 2015-01-01 17:02:52 by argasek argasek
What said mu6k is the right way and will fit most cases. Though , sometimes you need frames to be rendered and "velocity*delta" actually skips frames. When I coded 68000 Reasons, I wanted music synchro to be as accurate as possible, which meant no frames rendering skipping. The solution I adopted was the same as the one used by the game WipeOut on the PS3:
1. Measure the current frame-rate based on the number of frames rendered in the last 0.5 seconds.
2. If too slow, then render the FX in an offscreen texture, and make this texture smaller and smaller if the frame-rate keeps on being slow.
3. Render the offscreen texture to the screen (stretching it of course)
This works if your FX is slow because of the rendering only. Also, this is a clear trade-off between rendering quality VS frame-rate. In this case. I gave the priority to frame-rate. It really depends on the kind of demo you want to code.
added on the 2015-01-01 17:04:31 by Soundy Soundy
This is much case dependend, for my physics I try to use dt dependent on the time that passed from last frame, the problem is that simulation may become inaccurate and this depend on the numerical method used...

The synchronization is a problem if your dt cannot be made large. And I don't like the "animation" solution, is it still demo this way?
Maybe some kind of keyframing the important states would be better?
added on the 2015-01-01 18:31:17 by maq maq
or use a mixed technique, in my system I always interpolate between 2 simulation steps, so all code has to handle it. but with this in place I can run simulations not with 60 or 30Hz, also "only" 10Hz and it still looks smooth...
added on the 2015-01-02 14:16:48 by questor questor
Image-based feedback effects where the current frame depends on some portion of the previous frame are synchronised 1:1 with the output frame rate. If your process isn't done in time, it will arrive a frame late and your effect will appear to run in slow motion.

The only real way to avoid this is to buffer a few frames and progressively undersample your input as Soundy suggests in order to catch up.
added on the 2015-01-03 03:47:45 by Claw Claw
The problem with delta × velocity is that you need to be *really* careful when acceleration is involved. Let me put an example, let's say that something moves for a 1/6th second and accelerates at 0.1 every 1/60th of a second:

0 → 0.1 → 0.3 → 0.6 → 1.0 → 1.5 → 2.1 → 2.8 → 3.6 → 4.5 → 5.5

Now let's say we drop the framerate to 30FPS instead of 60FPS, this is what happens if you naively increase the acceleration (so 0.2 per frame):

0 → 0.2 → 0.6 → 1.2 → 2.0 → 3.0

See the problem? There are other issues but I think this is the biggest one. There are ways to fix this, but it isn't as trivial which can make things harder to deal with =P This is why usually it's better to just do fixed framerate and then do frameskip (i.e. skip rendering until it catches up) when it goes too slow.
added on the 2015-01-03 16:12:06 by Sik Sik
@Sik:
The problem you described does not exist. You were using the wrong formula.

P = V*t + A*t^2/2

P is position, V is velocity A is acceleration.
We can apply this formula in action by using a piece of code like this:

Code:// these vars represents the state of the object which we want to update vec3 position, velocity, acceleration; void update_position(float delta) { position += (velocity + acceleration*delta*0.5)*delta; }

Note: untested code... beware... and you should also update velocity... to get correct results... probably other problems too...

Also, I recommend understanding the difference between continuous growth and discrete growth to get a handle on how fundamentally different the deltatime method is compared to updates at a regular interval.
added on the 2015-01-03 16:43:12 by musk musk
Thank you guys for all the responses - I have at least a couple of ideas now how to cope with the problem. I will revive the thread when I get stuck with a particular implementation. Cheers! :)
added on the 2015-01-03 16:44:29 by argasek argasek
I also recommend testing your delta time code with something like

like
Code:a = new Object(prototype); b = new Object(prototype); a.update(1.0); a.update(1.0); a.update(1.0); a.update(1.0); b.update(4.0); Assert.areEqual(a.position, b.position, 0.0001);
added on the 2015-01-03 16:51:26 by musk musk
(ie. of course I mean it's still open for debate :D - as the subject is nontrivial)
added on the 2015-01-03 16:51:28 by argasek argasek

login