Open skulptur opened 6 years ago
why do you want to change the framerate?
Because I use regl to render animations that in the end run at 24fps but regl runs too fast most of the time so it's hard to predict what the final thing will look like.
Even for real time stuff I don't always want it to be at 60fps and using more resources than I can get away with.
I just want to be able to set a hard limit. If I have to do a custom loop that is fine but I think there should be more info on the docs since it mentions it vaguely.
Think you basically have to do something like:
const loop = () => {
regl.poll()
regl.clear({
color: [0, 0, 0, 1],
depth: true,
})
draw() // your draw commands here
}
Then you can choose how often to invoke loop
(e.g. setTimeout). Although you're probably better of making the duration of your animation invariant to the framerate (e.g. calculate delta time between frames and use this to determine how far to move / scale something etc.).
Thanks, I'll try that. I'm aware of time delta technique but in my case I really need my animations to be exactly the same frame by frame every time I run because I ultimately render to gifs or videos and also another reason for the hard limit is my computer heats a lot unecessarily while developing when it should be so easy to just make it run slower. I was actually surprised to not see that option as part of the lib. Not complaining though, regl is by far the nicest lib I've worked with.
but in my case I really need my animations to be exactly the same frame by frame every time I run because I ultimately render to gifs or videos
Depending on how you do your animations there is a technique that I've been using, which give's you a guarantee that your gif/video is correct in regards to fps and what every frame displays.
I don't use a render loop at all, but manually progress the animation (e.g. in the case of GSAP using .progress(newProgress)
) while doing a simple for-loop. In the following example code it looks like this gifTimeline.progress(currentFrame / numberOfFrames);
https://codepen.io/Prinzhorn/pen/GNEmWQ
The benefit is that you don't need your recording to be in sync with the rendering (Screencast will sometimes not be 100% in sync) and you can also render a, say 5 second video, in much less than 5 seconds of actual wall time.
I was actually surprised to not see that option as part of the lib
I think this might be partly because this is not possible to do in a reliable fashion across all browsers. requestAnimationFrame
does not give you any guarantees and setTimeout
is not accurate enough. requestAnimationFrame
is the best choice to get smooth animation for the current user. In your case, e.g. rendering gif/video, you might be better of using the technique described above.
Edit: in your case you might simply mock/patch Date.now/performance.now and progress the time "manually".
@Prinzhorn Thanks. The rendering part isn't as much of an issue as I'm currently using ccapture.js. My problem was really about previewing since it was running way too fast. As far as I'm concerned the issue is solved although an update to the docs with WebSeed's example might be a good idea.
@spredemann nice, thanks for pointing to ccapture.js
Sometimes, I like to have some shaders that I don't run at 60 fps because they are expensive in performance. Like read pixels for instance.
Here is what I do:
// define this somewhere
const slowerFrame = (regl, draw, dividerOfFramerate) {
let i = 0;
regl.frame( () => {
i = (i +1) % dividerOfFramerate;
if(!i) return;
draw();
})
}
// then I use it like that:
slowerFrame(regl, drawCommand, 2); // to divide the framerate of this draw loop by 2.
I only deal with multiple of the framerate, as I didn't find any reliable way to Hope that helps!
if(!i) return;
should be
if (i) return;
// or
//if (i > 0) return;
to skip most draw calls
I've searched the docs but couldn't figure out how to change the framerate of the regl.frame loop. It does mention that it's possible to create my own loop but that regl.frame performs some cleanup operations and to use it whenever possible. In case the only way is via a custom function, can someone provide an example of what such function would look like with all the proper precautions?