我尝试用C++和opengl在一个场景中实现昼夜循环。我试过glutTimerFunc。虽然我把时间片限制在10000 ms = 10 s,但它给了我一个非常快的翻转效果。
这就是我所做的。
void turn (int value){
if(night)
{
glDisable(GL_LIGHT0);
glEnable(GL_LIGHT1);
night=!night;
}
else
{
glDisable(GL_LIGHT1);
glEnable(GL_LIGHT0);
night=!night;
}
//glutPostRedisplay();
glutTimerFunc(10000,&turn,2);
}
在DrawGLScene
函数中我调用了这个函数。下面是WinMain函数:
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
// Ask The User Which Screen Mode They Prefer
//if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
//{
fullscreen=FALSE; // Windowed Mode
//}
// Create Our OpenGL Window
if (!CreateGLWindow("day night",700,500,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
glutTimerFunc(10000,&turn,2);
//turn(1);
while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("day night",700,500,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}
// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
2条答案
按热度按时间gstyhher1#
如果您的
DrawGLScene
已经使用glutDisplayFunc
注册,并因此被调用来绘制每一帧,那么您也将在 * 每次 * 重绘帧时(即每次调用glutPostRedisplay()
时)注册您的定时器函数。要启动定时器序列,您应该只调用
glutTimerFunc
一次,* 在 * 调用glutMainLoop
之前,而不是在DrawGLScene
中调用它。仍然需要调用
glutTimerFunc
*within * timer函数来启动下一次翻转。EDIT我发现你甚至没有使用
glutMainLoop
。这意味着你对glutTimerFunc
的调用没有做任何事情。基于GLUT的处理程序 * 只有 * 在由glutMainLoop
函数调度时才能工作。您的代码执行任何操作的唯一原因是,您在 Windows 事件循环中调用
DrawGLScene
,然后在每次通过Windows事件循环时直接调用您的计时器函数。这就是意外高频率的来源。如果您打算坚持使用Windows事件模型,那么最好使用标准的Windows计时器事件(即
SetTimer
)来处理翻转。或者,重写代码以使用
glutMainLoop
,并让GLUT处理所有按键和其他事件。4zcjmb1e2#
这是因为真实的白天/黑夜不是布尔型的,它是白天和黑夜之间的渐变。此外,只有10秒是一个非常短的白天/黑夜周期-你通常至少想要几分钟。