Sign in to follow this  

Flickering when restricting fps

This topic is 4379 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm having problems properly restricting the fps of my engine. I mean, I can restrict the fps, but if I do it properly, it won't draw properly.
/**
 * Set the fps to not go over a certain value.
 * \param f The value for the fps to not to exceed
 */
void CSceneGraph::setFPS(float f)
{
	m_minTimeBetweenFrames = 1.0f / f;
	m_time = 0.0f;
}

/**
 * Render all objects in the scene graph.
 */
void CSceneGraph::render()
{
	util::list<ISceneGraphNode*>::iterator i = m_nodeList.begin();

	//while( (m_time += m_hiResTimer.getElapsedSeconds()) < m_minTimeBetweenFrames );

	if( (m_time += m_hiResTimer.getElapsedSeconds()) < m_minTimeBetweenFrames )
		return;


	for( ; i != m_nodeList.end(); i++){
		// use these three to get the constant frame rate going
		(*i)->preRender( m_time );
		(*i)->render();
		(*i)->postRender( m_time );
	}

	// reset time to 0.0f because we have just drawn a frame
	m_time = 0.0f;
}



The way it is now, it should return to the main loop so whatever else that should be done can be done. ie - non graphics related things. But, it flickers insanely, and I don't get the fps restriction. And, if I use the while loop instead, it works perfectly, without any flickering, and the restriction is perfect. This is the main loop:
// temp vars for counting the FPS
unsigned int lastFPS = 0;
char str[1024];
while( engine->run() ){
		
	driver->beginScene();
		
	// reset the world/modelview matrix to the identity matrix
	driver->resetMatrix(video::WORLD_MATRIX);

	// use input to rotate
	t->addRotationX(xrot);
	t->addRotationY(yrot);

	engine->getSceneManager()->render();

	driver->endScene();

	// count the FPS
	unsigned int temp = driver->getFPSCounter().getFPS();
		
	if( temp != lastFPS ){
		lastFPS = temp;
		sprintf(str, "Current FPS: %d", temp);
		engine->setWindowCaption(str);
	}
}

I'm using openGL, and nothing actually gets passed to openGL (transformation and rendering) until the scene manager renders the scene graph. But, in 'driver->endScene()', I am calling the windows function 'SwapBuffers'. Could that be causing this? Because if I haven't actually drawn anything, just a blank buffer will be swapped to the front, right? If you think this is my problem, is there a way to find out if a change has been made to the back buffer?

Share this post


Link to post
Share on other sites
I do swap only at the end.


/**
* Does OGL housekeeping for the end of rendering a frame.
* Flushes the pipeline, swap buffers, counts fps.
*/

void COpenGLDriver::endScene()
{
glFlush(); // flush the pipeline

SwapBuffers(hDC); // render the scene to the window

// do the FPS calculating, etc
IVideoDriver::endScene();
}



This is only called once every iteration of the loop.

Share this post


Link to post
Share on other sites
Check your timer routines. You swap uncontrolled. The cause of flickering is in my opinion that you must integrate your swap into your frame limiter, in other words check for delta time. if it is bigger as 1.0 / desired fps, then swap

Share this post


Link to post
Share on other sites
One is how the swap is done. You can provide a hint to swap or copy, but on my machine it always copies. If you actually swap, i.e. back becomes front and front becomes back, then you would need the same image in both to keep swapping. If it's copy you just need the right image in the back buffer. The easiest way to check is just do it manually. During setup clear to one color, swap, then clear to another. Then in response to a kep press swap buffers. No drawing, no clearing, just swap. If the screen stays one color it's copying, if it changes it's swapping.

If it's copying then make sure you aren't clearing the buffer between swaps while not always rendering. Otherwise the image may only be displayed a small fraction of the fixed frame time. The swap is going to take 1ms or so with vertical sync turned off. It makes a nice, easy way to idle the CPU while you wait. If you don't care about burning CPU then you shouldn't swap without changing the image.

Share this post


Link to post
Share on other sites

This topic is 4379 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this