Tsa*_*ras 11 opengl 3d frame-rate
我试图找到一个可靠的方法,能够准确设置我希望我的OpenGL应用程序在屏幕上呈现多少FPS.我可以通过休眠1000/fps毫秒在某种程度上做到这一点,但这没有考虑渲染所需的时间.哪种是将fps限制在所需数量的最一致方法?
您可以在opengl中使用wglSwapIntervalEXT同步到vblank.它不是很好的代码,但确实有效.
http://www.gamedev.net/topic/360862-wglswapintervalext/#entry3371062
bool WGLExtensionSupported(const char *extension_name) {
PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglGetExtensionsStringEXT = NULL;
_wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT");
if (strstr(_wglGetExtensionsStringEXT(), extension_name) == NULL) {
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
和
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = NULL;
if (WGLExtensionSupported("WGL_EXT_swap_control"))
{
// Extension is supported, init pointers.
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
// this is another function from WGL_EXT_swap_control extension
wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
}
Run Code Online (Sandbox Code Playgroud)
由于OpenGL只是一个低级图形API,因此您不会直接在OpenGL中找到这样的内容.
但是,我认为你的逻辑有点缺陷.而不是以下:
你应该做这个:
这样一来,如果你只是等待你应该的数量,那么你应该每秒非常接近60(或者你的目标)帧数.
OpenGL本身没有任何允许限制帧速率的功能.期.
然而,在现代GPU上有许多功能,包括帧速率,帧预测等等.有一些John Carmack的问题,他推动了为它提供一些功能.还有NVidia的自适应同步.
这对你意味着什么?把它留给GPU.假设绘图是完全不可预测的(就像你只坚持使用OpenGL时那样),自己定时事件并将逻辑更新(如物理)与绘图分开.这样,用户将能够从所有这些先进技术中受益,您将不再需要担心这一点.
不要使用睡眠。如果您这样做,那么您的应用程序的其余部分必须等待他们完成。
相反,跟踪已经过去了多少时间并仅在满足 1000/fps 时进行渲染。如果计时器尚未达到,则跳过它并执行其他操作。
在单线程环境中,很难确保您以精确的 1000/fps 进行绘制,除非这绝对是您所做的唯一事情。一种更通用和更可靠的方法是在单独的线程中完成所有渲染,并在计时器上启动/运行该线程。这是一个更复杂的问题,但会让您最接近您的要求。
此外,跟踪发出渲染所需的时间将有助于动态调整渲染的时间。
static unsigned int render_time=0;
now = timegettime();
elapsed_time = last_render_time - now - render_time;
if ( elapsed_time > 1000/fps ){
render(){
start_render = timegettime();
issue rendering commands...
end_render = timegettime();
render_time = end_render - start_render;
}
last_render_time = now;
}
Run Code Online (Sandbox Code Playgroud)