问题
前文我们遇到的问题是,如何正确地给 glutInit() 这个函数传递一个正确的入口参数,使它能够正确地初始化OpenGL环境。
假设大家都在使用Visual C++。当我们创建一个控制台应用程序,而且不考虑Unicode的情形,那么我们的main函数自然而然地提供了 glutInit() 所需的两个参数:
int main (int argc, char* argv[])
{
glutInit (&argc, argv);
// ...
// ...
return 0;
}
但是,如果我们创建的是一个考虑了Unicode情形的控制台应用程序,那么我们的main函数就变成了:
int _tmain (int argc, _TCHAR* argv[])
现在我们该如何调用 glutInit() 来初始化OpenGL环境呢?
甚至于,如果我们创建的不是一个控制台应用程序,而是一个Win32应用程序(带GUI的那种),那么我们的main函数就变成了:
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
这时候我们又该如何调用 glutInit() 来初始化OpenGL环境呢?
所以我们必须要了解,该如何正确地给 glutInit() 传递入口参数。
分析
我们从FreeGLUT官方网站下载源代码,然后分析其源码。只需要看 src 目录下的 fg_init.c 这个文件就可以了。
我们看来看 glutInit() 的入口参数:
/*
* Perform initialization. This usually happens on the program startup
* and restarting after glutMainLoop termination...
*/
void FGAPIENTRY glutInit( int* pargc, char** argv )
看这个函数的实现。只需要看与入口参数相关的部分:
void FGAPIENTRY glutInit( int* pargc, char** argv )
{
// ...
if (pargc && *pargc && argv && *argv && **argv)
{
fgState.ProgramName = strdup (*argv);
// ...
}
// ...
fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
// ...
}
只有两处代码用到了入口参数。
fgState.ProgramName = strdup (*argv);
如果在一个控制台应用程序中,“char* argv[]”的第一个参数无非是应用程序的路径和文件名。所以当这个参数缺失时,我们“手动”给这么一个名字即可。
fghParseCommandLineArguments
看这个函数的实现:
void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
阅读源码可知这个函数是从控制台应用程序的环境变量字符串里面提取下列参数,用来设置“char **pDisplayName”和“char **pGeometry”:
getenv( “DISPLAY” )
这个用来设置pDisplayName。
-display
如果它存在,则用它来设置pDisplayName。
getenv( “GLUT_FPS” )
它用来设置fgState.FPSInterval。
-geometry
它用来设置pGeometry 。
-direct和-indirect
它用来设置fgState.DirectContext。
-iconic
它用来设置fgState.ForceIconic。
-gldebug
它用来设置fgState.GLDebugSwitch。
-sync
它用来设置fgState.XSyncSwitch。
结论
现在应该清楚该如何正确地构建 glutInit() 的入口参数了吧。