   Time based rendering placement problems (updated)
Skip to the last post for the newer stuff.Yeah I know that the title is kind of confusing, but I didn't really know what else to have it as.Anyway, the problem is that the code that I have to do time based rendering so I restrict the fps of the engine is currently in my SceneManager class. When I need to render, I simply call SceneManager::render() and that traverses the scene graph tree and calls 'render' for everything.So, the code to restrict the engine fps needs to be in SceneManager::render().I recently realised that if I call SceneManager::render() more than once every frame, I get problems. For instance if I need to render twice for shadows, or to draw reflections, or something like that.It's a little bit of a story, so here goes:This is the code that restricts the fps of the engine:/** * Render all objects in the scene graph. */void CSceneGraph::render(){while( (m_time += m_hiResTimer.getElapsedSeconds()) < m_minTimeBetweenFrames );//if( (m_time += m_hiResTimer.getElapsedSeconds()) < m_minTimeBetweenFrames )//return;util::list<ISceneGraphNode*>::iterator i;// pre renderfor(i = m_nodeList.begin() ; i != m_nodeList.end(); i++)(*i)->preRender( m_time );// renderfor(i = m_nodeList.begin() ; i != m_nodeList.end(); i++)(*i)->render();// post renderfor(i = m_nodeList.begin() ; i != m_nodeList.end(); i++)(*i)->postRender( m_time );// reset time to 0.0f because we have just drawn a framem_time = 0.0f;}I currently have to use the while statement, otherwise I get serious flickering and no restriction of the fps. I think I know why this is. Whenever VideoDriver::endScene is called, it swaps the buffers for the window, and obviously if no rendering is done then nothing gets drawn to the back buffer and a blank buffer gets swapped to the screen, causing the flickering. I think.So, for both these reasons, (blank buffer swap, and calling SceneManager::render more than once a frame) I need to move the fps code to the video driver, so I can prevent the buffer being swapped when nothing has been drawn to it.Should I just have a pointer to the scene graph inside the video driver, move the fps code to the video driver and instead of calling 'render' on the scene graph object, do it on the video driver object?How have other people done this bit? Or did you all do the smart thing and have a better design than I did?[Edited by - Endar on May 23, 2006 4:17:16 AM]
  Time restriction does not below in a scene graph.When you call "render" on a scene graph, it should traverse the graph, and render all the items to the indicated target, using the current state of the objects. It should not change the state of the objects, or check the time, or anything like that. When it comes to object state, the scene graph should be absolutely dumb (only the user changes the objects).If calling Render() twice in a row in your scene graph causes an empty frame to be rendered, you have a bug in your scene graph.If you need to limit the frame rate, you should first try turning on vSync in your code -- D3DPRESENTINTERVAL_xxx has some options for you. This will remove all tearing. Only after that should you start throttling in the application -- and, in that case, in the high-level code. I e, your code might look something like:  forever() {    toSleep = nextTime - time();    Sleep(toSleep);    nextTime = time() + desiredFrameTime;    ReadInput();    ProcessPhysics(desiredFrameTime);    RenderScene();  }Note that Sleep() may be a little bit jittery on some systems; you may have better results with something like MsgWaitForMultipleObjectsEx() with a timeout.;Quote:Original post by hplus0603If you need to limit the frame rate, you should first try turning on vSync in your code -- D3DPRESENTINTERVAL_xxx has some options for you.Do you know the equivalent for OGL? Oh, well I don't think it matters as I'm not currently using full screen, I'm just doing it windowed.   ;  Okay, I thought this would work, but I'm having problems with the code and it's better to post here than start up a new thread.void IVideoDriver::render(){// If the total time since the last frame is less than the time between frames for the desired fps// ie. If to restrict to the desired fps, we don't have to draw yetif( (m_time += m_hiResTimer.getElapsedSeconds()) < m_minTimeBetweenFrames )return;// if we get here, then we should be rendering a frame// if we have a scene managerif( m_sceneManager )m_sceneManager->render( m_time );// render the scene graph// reset the timem_time = 0.0f;// indicate we should be renderingm_renderFrame = true;}/** * Does housekeeping for the end of rendering a frame. */virtual void IVideoDriver::endScene(){// if we should be rendering a frameif( m_renderFrame ){m_fpsCounter.endFrame();// register the end of a frame, so, calculate the FPSm_renderFrame = false;// it's the beginning of a new frame}}/** * Does OGL housekeeping for the end of rendering a frame. * Flushes the pipeline, swap buffers, counts fps. */void COpenGLDriver::endScene(){// If the time since the last frame is greater than the min time between frames// ie. If we should be renderingif( m_renderFrame ){glFlush();// flush the pipelineSwapBuffers(m_hdc);// render the scene to the window// do the FPS calculating, etcIVideoDriver::endScene();}}Note:: COpenGLDriver inherits from IVideoDriver.If I use the code was is, the FPS counter says the fps is ~50. But when I do some rotation on the cube, which is the only thing is the scene, it rotates way too fast for 50 fps.If I comment out the first if statement, and don't add to 'm_time' at all, I get about ~87.This is really confusing.   ;  bump   ;  You are only restricting the rendering frame rate by putting checks in a render() function, not the physics frame rate. Your high-level message loop is the place to restrict speed, not a rendering function.And you don't need to bump after 7 hours.   ;Quote:Original post by Bob JanovaYou are only restricting the rendering frame rate by putting checks in a render() function, not the physics frame rate. Your high-level message loop is the place to restrict speed, not a rendering function.At the moment, I'm only trying to restrict the rendering speed (I currently have no physics).Why is the high-level message loop the place to restrict speed? Can't I have each system restricting it's own speed to whatever it needs or wants?Quote:Original post by Bob JanovaAnd you don't need to bump after 7 hours.Uh, 3:45am I wrote the post, and bumped it at 10:55pm.   ;  Okay, you don't need to bump after X hours, where X < 24 and your page is still on the first screen :P.Quote:At the moment, I'm only trying to restrict the rendering speed (I currently have no physics).Uh, where does rotating this model happen, then? The rate at which that occurs will be related to your input framerate, which I presume is not called from within render(). You don't restrict the framerate of your message loop at all by returning from render() (to do that you need to wait).Quote:Why is the high-level message loop the place to restrict speed? Can't I have each system restricting it's own speed to whatever it needs or wants?Well, yes, it's just more complicated. By restricting frame rate at the highest level you ensure all your game modules run at the same speed. If you want to restrict each component separately then that's fine, but don't expect your input and rendering to happen at the same frame rate!   ;Quote:Original post by Bob JanovaUh, where does rotating this model happen, then? The rate at which that occurs will be related to your input framerate, which I presume is not called from within render(). You don't restrict the framerate of your message loop at all by returning from render() (to do that you need to wait).I thought that eventually I'd be able to do something like this:while( running ){processInput();render();physicsUpdate();sleep();}And for the rendering and physics, or at least the rendering calc the seconds (fractions obviously) between each render to get a specific fps, and if we've not hit it yet, then just don't render and go on to the physics. Kind of the same with the physics (kind of, I know nothing about physics yet).Or was this what you were telling me and it's just not entering my thick, thick head?   ;  Okay, so in that case what is the problem with the cube rotating faster than 50 fps :P ? If you're just not rendering then you'd expect the other parts of the game (input, physics) to go faster. Sounds like your solution is working just like you wanted it to 8).   