jacquesr Posted October 28, 2015 Share Posted October 28, 2015 Hi, I'm writing an app that essentially only needs to render when the user does something. There are a few edge cases that cause one-time animations, all other stuff is a one time render situation. The main reason to avoid the render loop is that there is nothing generally going on that requires visual updates so we can save a lot of resources by not rendering all the time I currently try to handle the render loop the following way: Some consumer code calls a render on my babylon js wrapper object that handles everythingIn this moment, a pendingFrames variable is increased (default 0) and startRenderLoop is called with a callback doing nothing apart from scene.render()In onAfterRender, I look for further pending frames ( pendingFrames > 0). If there is nothing, I call stopRenderLoop.For animations, there is a similar approach, with the difference that the pendingAnimations variable is increased whenever an animation starts and decreased in every end animation callback.So, let's take away the animation case.I have a mouse move interaction that calls my render call on my wrapper object. It increases the pendingFrames by one every time. This is my first problem, because there is no 1:1 relation between mouse move and rendering, so I can increase more render calls than I actually need.Before, I did not use "pendingFrames" but instead had a simple flag that managed to render the scene using scene.render if anyone requested a frame. Then I did not have the relation problem BUT: positioning changes that were handled in onBeforeRender did not work even though I changed positions on depending meshes before the render call. Upon the next mouse move, without any further change, it then suddenly was correct again. So, that may also have something to do with the timing. In the end, my question now is, how do I correctly take full control so that I do not render anything I do not need. It was also noticable that, against a general render loop, my mouse move based enabling and disabling of rendering was 7 fps slower (against 37) which I currently don't really have an answer for.EDIT:I should note that another noticable thing is that the movement is not really smooth when I use my enable/disable render loop logic. The camera movement tends to jump a little. I must do something seriously wrong. Maybe some technical background helps :-) Tibotiber 1 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 28, 2015 Share Posted October 28, 2015 Hey, you are not doing anything wrong and this is pretty smart actually. The first problem that I can foresee is that you won't have camera movement inertia with your system because this requires several rendering to achieve it One idea here: Your stop condition should be: no pending frames AND no running animations (ie: scene.._activeAnimatables.length === 0) AND camera.cameraDirection === Vec3(0) AND camera.cameraRotation === 0 as well Tibotiber 1 Quote Link to comment Share on other sites More sharing options...
jacquesr Posted October 29, 2015 Author Share Posted October 29, 2015 Hey Deltakosh, we have set the inertia to 0.1 because we also did not want that and we are aware of that problem. Well, inertia 0.1 is not 0 but I learned that babylon "does not like zero values" I will try improving the check in the renderloop management.Anyway, do you have an idea why my manual start/stop costs me 7 fps? 30 to 37 (when we once start the renderloop and let it run) I first thought it might be the mousemove, but I guess that mouse move interrupts are a lot more often than 60 fps (at least in theory without logic inside) in the end... Now I tend to think that it is due to the binding and unbinding of the renderloop callback or the general approach with initializing and deinitializing a renderloop. I guess that internally, you are working on requestAnimationFrame Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 29, 2015 Share Posted October 29, 2015 How do you measure the FPS? Quote Link to comment Share on other sites More sharing options...
jacquesr Posted October 29, 2015 Author Share Posted October 29, 2015 with your debug overlay that's also available in the playground... I just continuously move the mouse in my manual rendering then, of course Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted October 29, 2015 Share Posted October 29, 2015 Ok this is why...there is TOO much time between two calls when you move the mouse. requestAnimationFrame runs 60 times per second so the FPS you've got are wrong Quote Link to comment Share on other sites More sharing options...
jacquesr Posted November 6, 2015 Author Share Posted November 6, 2015 I've got some 3D snapping and collision logic in my mousemove but it's hard to believe that it needs 32ms per move... Will check it out Quote Link to comment Share on other sites More sharing options...
jacquesr Posted March 16, 2016 Author Share Posted March 16, 2016 Hey @Deltakosh I recently added the changes you suggested. Running on babylon 2.3. if (sceneObjects.pendingAnimationCount > 0 || sceneObjects.pendingFrames > 0 || sceneObjects.forceKeepRendering || cam.cameraDirection.x !== 0 || cam.cameraDirection.y !== 0 || cam.cameraDirection.z !== 0 || cam.cameraRotation.x !== 0 || cam.cameraRotation.y !== 0) {} else this.stopRenderLoop(); yet, that doesn't work since cameradirection/rotation seems to be always 0... I have an arcrotatecamera here Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted March 16, 2016 Share Posted March 16, 2016 in this case check for camera.alpha and beta Quote Link to comment Share on other sites More sharing options...
Hanesu Posted June 12, 2017 Share Posted June 12, 2017 Making the renderer stop rendering when there is nothing to do - this is something I would like to implement as well. Do you have any PG for this? I cannot find any full example above. Thanks lot! Quote Link to comment Share on other sites More sharing options...
aWeirdo Posted June 12, 2017 Share Posted June 12, 2017 @Hanesu Here's an example with rendering while the pointer is being pressed and stopping again when it is released. http://playground.babylonjs.com/#3A2PUF#2 Hanesu and GameMonetize 2 Quote Link to comment Share on other sites More sharing options...
Hanesu Posted June 20, 2017 Share Posted June 20, 2017 Thank you, this is a nice and simple example, but the functionality I a bit limited. How could I extend it to render as long as the camera or some object is moving? Quote Link to comment Share on other sites More sharing options...
JohnK Posted June 20, 2017 Share Posted June 20, 2017 2 hours ago, Hanesu said: How could I extend it to render as long as ..... some object is moving? Mmmmmmmmmmmmmm what is going to start the object moving? I know I will set a random time T milliseconds after which the object will move. Mmmmmmmm how will I know T milliseconds have passed? I know I will write a routine that that runs once every sixtieth of a second and see if the time has passed yet? Mmmmmmmmmm! No I wont I will just use new BABYLON.Animation and leave the rendering alone. Mmmmoral is I better have a very good reason to want to stop rendering else I am just going to give myself a lot of work for no good reason! Does it really matter that if nothing is going on then the BabylonJS engine is rendering the same screen upto 60 times a second? Quote Link to comment Share on other sites More sharing options...
Hanesu Posted June 21, 2017 Share Posted June 21, 2017 8 hours ago, JohnK said: Mmmmoral is I better have a very good reason to want to stop rendering else I am just going to give myself a lot of work for no good reason! Does it really matter that if nothing is going on then the BabylonJS engine is rendering the same screen upto 60 times a second? There is a very good reason why I want to stop rendering if there is nothing new to render: I have complicated meshes (scientific data) to visualize with millions of triangles. If they are re-rendered 60 times a second, the cpu load goes up to 100%, my laptop gets freaking loud, crazy hot, and runs out of battery after one hour! If I have means to stop rendering, like for example with the simple solution by @aWeirdo above, the cpu load goes down below 5%, my laptop is quiet, keeps cool, and runs for eight hours on battery! gonzalle and JohnK 1 1 Quote Link to comment Share on other sites More sharing options...
JohnK Posted June 21, 2017 Share Posted June 21, 2017 6 hours ago, Hanesu said: There is a very good reason why I want to stop rendering if there is nothing new to render: I have complicated meshes (scientific data) to visualize with millions of triangles. If they are re-rendered 60 times a second, the cpu load goes up to 100%, my laptop gets freaking loud, crazy hot, and runs out of battery after one hour! If I have means to stop rendering, like for example with the simple solution by @aWeirdo above, the cpu load goes down below 5%, my laptop is quiet, keeps cool, and runs for eight hours on battery! That is a very good reason and that will start the rendering if the user moves the pointer and so moves the camera. However you then said 17 hours ago, Hanesu said: Thank you, this is a nice and simple example, but the functionality I a bit limited. and asked to extend this 17 hours ago, Hanesu said: to render as long as .... some object is moving The question then becomes what event starts and stops the object moving. If it is an external event such as a key press or pointer move then capturing that event works in the same way as aWeirdo showed. The following PG will also render when the key g is pressed and stop when s is pressed. NOTE click on scene before pressing key so scene has focus. http://playground.babylonjs.com/#3A2PUF#3. If it is a timed event then use setTimeout http://playground.babylonjs.com/#3A2PUF#4 Hanesu 1 Quote Link to comment Share on other sites More sharing options...
Hanesu Posted June 24, 2017 Share Posted June 24, 2017 Thanks for the examples, very helpful. I will check out the actionManager stuff. One thing that still bothers me is when I zoom with the arcRotateCamera through mouse scroll. When I scroll the mouse wheel nothing happens (of course, because the mouse button is not pressed). Then, when I press the mouse button, the scrolling motion happens, it is somehow remembered and the action is delayed. This behavior is not useful, so one way around it would be an "onScroll" event analogous to the "onPointerDown", but this event does not seem to exist. That is why I thought it would be simpler and more general to check for motions in the camera, like camera.alpha/beta/radius changes. How could I check for changes in those parameters and only render in case of change? Quote Link to comment Share on other sites More sharing options...
JohnK Posted June 24, 2017 Share Posted June 24, 2017 As far as I know you can only rotate or move the camera when you have a pointer or key down and aWeirdo's method will detect this. As far as scrolling goes then I think any zoom is a browser zoom not a BJS zoom and so there is no change of radius. IMHO without rendering and using scene.registerAfterRender you could only check for an camera.alpha change using setInterval to check every few milliseconds if oldAlpha was currentAlpha but alpha will only change if you are are moving the mouse with pointerdown so back to above. An alternative would be to use BABYLON.GUI and change alpha, beta and radius values on the click of a button, but then as you are clicking the button this event is captured and you can then switch rendering on during the onclick function. If you have other ways of checking for alpha, beta and radius values let us know. Quote Link to comment Share on other sites More sharing options...
sable Posted June 26, 2017 Share Posted June 26, 2017 The inputs to arc rotate camera don't modify the alpha/beta/radius directly, but rather modifies inertialAlphaOffset, inertialBetaOffset and inertialRadiusOffset, which in turn sets the alpha, beta and radius of the camera (adds the offset, then multiplies the offset by inertia, repeat until the offset is ~0, see here). If you just want to make sure movement hasn't been buffered while the render is stopped, you can just set these offset to 0 before the render. https://www.babylonjs-playground.com/#AFPV4K#2 If you just want to allow rendering while the camera is moving, you can however just use a render loop that checks if these values are not 0. https://www.babylonjs-playground.com/#AFPV4K#5 @Deltakosh When inertia is set to 0 in the above pg, the movement seems to be a frame behind (if zoom in then out, the first frame after the zoom out scroll wheel tick will zoom in). Something to do with render order? Also if you zoom, then just click move to rotate normally, it will do the final zoom on that render. Hanesu and Tibotiber 2 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted June 26, 2017 Share Posted June 26, 2017 Yep it is related. Is it an issue? Quote Link to comment Share on other sites More sharing options...
sable Posted June 26, 2017 Share Posted June 26, 2017 Not really, was just curious why this seemed to only happen with an inertia of 0. GameMonetize 1 Quote Link to comment Share on other sites More sharing options...
Hanesu Posted July 1, 2017 Share Posted July 1, 2017 On 6/24/2017 at 4:37 PM, JohnK said: As far as I know you can only rotate or move the camera when you have a pointer or key down and aWeirdo's method will detect this. As far as scrolling goes then I think any zoom is a browser zoom not a BJS zoom and so there is no change of radius. By monitoring camera.radius you immediately see that scrolling directly changes the radius. JohnK 1 Quote Link to comment Share on other sites More sharing options...
Hanesu Posted July 1, 2017 Share Posted July 1, 2017 On 6/26/2017 at 7:58 PM, sable said: The inputs to arc rotate camera don't modify the alpha/beta/radius directly, but rather modifies inertialAlphaOffset, inertialBetaOffset and inertialRadiusOffset, which in turn sets the alpha, beta and radius of the camera (adds the offset, then multiplies the offset by inertia, repeat until the offset is ~0, see here). If you just want to make sure movement hasn't been buffered while the render is stopped, you can just set these offset to 0 before the render. https://www.babylonjs-playground.com/#AFPV4K#2 If you just want to allow rendering while the camera is moving, you can however just use a render loop that checks if these values are not 0. https://www.babylonjs-playground.com/#AFPV4K#5 That's it, the second PG does exactly what I need. Thank you so much, you made my week! sable 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.