1. 为什么还要在 VS2019 里折腾 glut 这套老环境先把话说在前头如果你现在打开搜索引擎搜 OpenGL 环境配置跳出来的十有八九是 GLFW、SDL2、glad、glew 这一套现代组合拳。glut 这东西严格来说已经是个上古遗物了官方最后一个稳定版本停在 3.7 左右原作者早就停止维护后来社区里有人接手做了 freeglut 才勉强续命。那为什么还有一批人非得在 VS2019 里把 glut 配起来答案很现实教学场景和存量代码。国内不少高校的计算机图形学课程、OpenGL 入门实验指导书用的还是 glut 那套 API。老师给的示例代码里#include GL/glut.h一写glutInit、glutDisplayFunc、glutMainLoop一调你换 GLFW 就得把整个代码结构重写一遍。对于刚入门、连窗口系统是什么都还没搞明白的同学来说这个改造成本太高了。所以与其纠结为什么不用现代的不如先把 glut 跑通把图形学的核心概念图元、变换、光照、纹理学明白工具链的事以后再说。这篇内容就是冲着这个需求来的。我会把VS2019 glut这套环境从零配到能跑出第一个三角形中间所有容易踩的坑、每个文件该放哪、链接器该怎么填、32 位和 64 位怎么选全部讲透。适合的人群很明确正在上图形学课的学生、需要维护老项目的开发者、以及想快速验证一段 glut 示例代码的人。你不需要有 VS 的深度使用经验但至少要能新建一个空项目、知道解决方案资源管理器在哪。我自己的经历是第一次配 glut 的时候卡了整整一个下午问题出在把 32 位的库文件塞进了 64 位的项目里链接器报了一堆LNK2019 无法解析的外部符号当时完全看不懂。后来才明白glut 的库是分位数的项目平台和库的位数必须严格一致。这个坑我在下面会重点讲你照着做能省下那几个小时。2. 配置前的整体思路与文件规划2.1 glut 环境的三个组成部分很多人配不成功根本原因是没搞清楚 glut 到底由哪些东西组成。它不像一个 pip 包或者 npm 包装完就完事。glut 在 Windows 上是一套手工拼装的依赖分成三块头文件.hglut.h你的代码里#include的就是它。它声明了所有 glut 函数比如glutInit、glutCreateWindow。导入库.libglut32.lib或glut.lib链接阶段用。它告诉链接器这些函数在某个 DLL 里运行时去那儿找。动态库.dllglut32.dll或glut.dll运行时用。程序启动时系统会去加载它找不到就直接报缺少 xxx.dll。这三块缺一不可而且位数必须统一。32 位的头文件其实和 64 位通用因为头文件只是声明但 lib 和 dll 必须和你的项目平台位数一致。这是整个配置里最容易翻车的地方。2.2 为什么推荐项目内配置而不是系统级配置配置 glut 有两种流派一种是把头文件、lib、dll 分别拷到系统目录比如C:\Program Files (x86)\Windows Kits\...或者System32另一种是全部放在项目文件夹里通过项目属性指定路径。我强烈推荐第二种项目内配置。理由有三条第一可移植。你把整个项目文件夹拷给同学他直接就能编译不用再配一遍环境。系统级配置换个电脑就失效了。第二不污染系统。往System32里塞 dll 是很多老教程的做法但这会让系统里多出一堆来源不明的库文件卸载还麻烦。万一你塞了个 32 位的 dll 进 64 位系统目录还可能引发其他程序的诡异问题。第三多版本共存。你可能有多个项目一个用 glut一个用 freeglut项目内配置互不干扰。系统级配置就得来回覆盖非常痛苦。所以下面的实操全部基于项目内配置这个思路。我会建一个清晰的目录结构把头文件、库文件、dll 分门别类放好。2.3 目录结构设计在项目根目录下我习惯建这么一个结构MyOpenGLProject/ ├── MyOpenGLProject.sln ├── MyOpenGLProject/ │ ├── MyOpenGLProject.vcxproj │ ├── main.cpp │ ├── include/ │ │ └── GL/ │ │ └── glut.h │ ├── lib/ │ │ ├── x86/ │ │ │ └── glut32.lib │ │ └── x64/ │ │ └── glut.lib │ └── bin/ │ ├── x86/ │ │ └── glut32.dll │ └── x64/ │ └── glut.dll这个结构的好处是include 放头文件lib 按位数分文件夹bin 放运行时 dll。项目属性里引用路径时用$(Platform)这个宏就能自动区分 x86 和 x64不用手动改来改去。$(Platform)在 VS 里会被替换成Win32或x64注意 Win32 对应的文件夹名我写的是 x86这里要么统一命名要么在属性里写死下面会讲怎么处理。提示如果你拿到的 glut 包只有 32 位版本很多老资源都是这样那就老老实实把项目平台设成 x86别硬上 x64。强行混用只会得到一堆链接错误。3. 获取 glut 文件与位数选择的关键决策3.1 glut 文件的来源与甄别glut 的原始版本由 Mark Kilgard 维护后来停止更新。现在网上流传的 glut 包五花八门有的叫glut-3.7.6-bin有的叫glutdlls37beta还有各种二次打包的。这些包内容大同小异核心就是那几个文件。我建议你找那种结构清晰、明确标注了 32/64 位的包。一个靠谱的 glut 包解压后应该能看到类似这样的内容glut/ ├── glut.h ├── glut32.lib ├── glut32.dll ├── glut.lib (64位) └── glut.dll (64位)注意命名规律带 32 的是 32 位不带的是 64 位。这是 glut 社区约定俗成的命名方式。有些包会把 64 位的也叫glut32.lib那就得看包里的说明文档或者用工具查一下位数。怎么查一个 lib 或 dll 是 32 位还是 64 位最土但最有效的办法是用 VS 自带的dumpbin工具。打开开发者命令提示符Developer Command Prompt for VS2019敲dumpbin /headers glut.lib | findstr machine32 位会显示machine (x86)64 位显示machine (x64)。dll 同理把文件名换成 dll 就行。这个命令我用了很多年比任何第三方工具都靠谱。3.2 32 位还是 64 位到底怎么选这是个决策问题我给你一个简单的判断标准场景推荐位数理由课程作业、示例代码x8632位老资源几乎都是 32 位省事需要链接其他 64 位库x64位数必须统一不能混不确定、只想先跑通x8632 位兼容性最好坑最少项目要求大内存x6432 位进程内存上限约 2GB我的建议是如果你没有特殊需求直接用 x86。原因很简单网上能下到的 glut 包绝大多数是 32 位的64 位的要么难找要么是别人自己编译的、来源不明。用 32 位能避开找不到 64 位库这个最大的坑。VS2019 新建项目时默认平台可能是 x64也可能是 x86取决于你选的模板。所以第一步就是去配置管理器里确认一下当前平台。菜单路径是生成 → 配置管理器看活动解决方案平台那一栏。如果是 x64而你只有 32 位的 glut就点下拉框选新建添加一个 Win32 平台。3.3 把文件放进项目目录按照 2.3 节的结构把文件归位glut.h→include/GL/glut.h注意 GL 这个子文件夹因为代码里是#include GL/glut.h32 位glut32.lib→lib/x86/glut32.lib32 位glut32.dll→bin/x86/glut32.dll64 位glut.lib→lib/x64/glut.lib64 位glut.dll→bin/x64/glut.dll这里有个细节头文件里的#include GL/glut.h决定了你必须建一个 GL 文件夹。如果你直接把 glut.h 放在 include 根目录那代码里就得改成#include glut.h但这样又和很多示例代码不兼容。所以老老实实建 GL 子文件夹保持和标准写法一致。注意有些 glut 包里的头文件还依赖GL/gl.h和GL/glu.h这两个是 Windows SDK 自带的不用你管。但如果编译时报找不到 gl.h说明你的 VS 没装 Windows SDK得去 Visual Studio Installer 里补上Windows 10 SDK组件。4. VS2019 项目属性配置全流程4.1 新建项目与平台确认打开 VS2019选创建新项目模板选空项目Empty Project语言选 C。给项目起个名字比如GlutDemo。创建完成后先别急着写代码去生成 → 配置管理器确认平台。如果你要配 32 位活动解决方案平台应该是Win32有的版本显示x86。如果是x64点下拉框 → 新建 → 选Win32→ 确定。这样你就有了一个 32 位的配置。接下来在解决方案资源管理器里右键源文件 → 添加 → 新建项 → C 文件命名main.cpp。先放一个空的 main 函数进去方便后面测试编译。4.2 配置头文件搜索路径右键项目 → 属性打开属性页。注意左上角的配置和平台两个下拉框配置选所有配置平台选你刚才确定的平台比如 Win32。这样改一次Debug 和 Release 都生效。找到C/C → 常规 → 附加包含目录点右边的编辑添加$(ProjectDir)include$(ProjectDir)是 VS 的宏代表项目文件.vcxproj所在目录。因为我们的 include 文件夹就在项目目录下所以这个路径能正确指向include进而找到include/GL/glut.h。这里解释一下为什么用$(ProjectDir)而不是写死绝对路径。写死路径的话项目一换电脑就失效而且团队协作时每个人的路径都不一样。用宏是标准做法可移植性强。4.3 配置库文件搜索路径接着找链接器 → 常规 → 附加库目录添加$(ProjectDir)lib\$(Platform)这里用到了$(Platform)宏。在 Win32 平台下它会被替换成Win32在 x64 平台下替换成x64。但我们的文件夹叫x86和x64Win32对不上x86这就出问题了。解决办法有两个一是把文件夹改名成Win32和x64二是路径里不用宏直接写$(ProjectDir)lib\x86。我推荐第一个办法文件夹跟着 VS 的宏命名走这样最省心。所以把lib/x86改名为lib/Win32bin/x86也改成bin/Win32。改完之后附加库目录就是$(ProjectDir)lib\$(Platform)在 Win32 平台下自动指向lib\Win32在 x64 下指向lib\x64完美。4.4 指定要链接的库名光有库目录还不够还得告诉链接器我要链接哪个库。找链接器 → 输入 → 附加依赖项添加glut32.lib注意这里填的是库文件名不是路径。链接器会去附加库目录里找这个文件。如果你配的是 64 位库名可能是glut.lib那就填glut.lib。有个常见误区有人把opengl32.lib、glu32.lib也一起加进去。其实 glut 的库已经隐含依赖了这些系统库一般不用手动加。但如果编译时报gluPerspective之类的符号找不到那就把glu32.lib加上。opengl32.lib是 Windows 自带的路径在 SDK 里不用你指定目录。4.5 让 dll 在运行时能被找到前面三步配完编译链接应该能过了。但一运行很可能弹窗报找不到 glut32.dll。这是因为 dll 是运行时加载的系统默认只会在 exe 所在目录、System32 目录、以及 PATH 环境变量里的目录找。最省事的办法是把 dll 拷到 exe 旁边。VS 默认把 exe 生成在项目目录\平台\配置\下比如GlutDemo\Win32\Debug\。所以你要把bin\Win32\glut32.dll拷到Win32\Debug\和Win32\Release\里。但每次手动拷太麻烦而且容易忘。更好的办法是用生成后事件自动拷贝。在项目属性里找生成事件 → 后期生成事件 → 命令行填入xcopy /Y /I $(ProjectDir)bin\$(Platform)\*.dll $(OutDir)$(OutDir)是输出目录的宏指向 exe 所在文件夹。这样每次编译完dll 会自动拷过去一劳永逸。/Y表示覆盖不提示/I表示目标当作目录处理。提示如果你嫌生成后事件麻烦也可以直接把 dll 拷到C:\Windows\SysWOW6432位 dll或C:\Windows\System3264位 dll。但我不推荐原因在 2.2 节说过污染系统。生成后事件是更干净的做法。5. 第一个 glut 程序与验证5.1 最小可运行代码环境配好了写个最小的程序验证一下。在main.cpp里写#include GL/glut.h void display() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(-0.5f, -0.5f); glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(0.5f, -0.5f); glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(0.0f, 0.5f); glEnd(); glFlush(); } int main(int argc, char** argv) { glutInit(argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); glutCreateWindow(Glut Demo); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glutDisplayFunc(display); glutMainLoop(); return 0; }这段代码画一个彩色三角形。glutInit初始化glutInitDisplayMode设置显示模式单缓冲 RGBglutCreateWindow建窗口glutDisplayFunc注册绘制回调glutMainLoop进入事件循环。这是 glut 程序的标准骨架几乎所有示例都是这个结构。5.2 编译运行与预期结果按 F5 编译运行。如果一切正常会弹出一个 600x600 的黑色窗口中间一个红绿蓝渐变的三角形。关掉窗口程序结束。如果编译报错对照下面的排查表。如果运行报错多半是 dll 没找到检查生成后事件有没有生效或者手动把 dll 拷到 exe 旁边。5.3 验证配置是否真正生效跑通之后建议做几个验证确认配置是真生效而不是碰巧能跑第一切换平台测试。把活动平台从 Win32 切到 x64重新编译。如果你 64 位的库配好了应该也能跑如果没配 64 位库会报链接错误。这能验证你的$(Platform)宏路径是否工作正常。第二清理重建。菜单生成 → 清理解决方案然后重新生成。有时候增量编译会掩盖配置问题全量重建能暴露出来。第三换个目录。把整个项目文件夹拷到另一个路径重新打开编译。如果还能跑说明你的配置全是相对路径可移植性没问题。6. 常见问题与排查技巧实录6.1 链接错误 LNK2019 无法解析的外部符号这是最高频的问题报错长这样error LNK2019: 无法解析的外部符号 __imp____glutInitWithExit12原因几乎都是位数不匹配或库没链接上。排查顺序确认项目平台和 lib 位数一致。用dumpbin /headers查 lib 的 machine 字段。确认附加依赖项里填了glut32.lib。确认附加库目录指向了正确的文件夹且该文件夹里确实有这个 lib。确认附加包含目录指向了含GL/glut.h的目录。我遇到过一次特别隐蔽的情况附加库目录写的是$(ProjectDir)lib\$(Platform)但文件夹实际叫x86而不是Win32导致路径解析失败链接器找不到 lib。这种问题不会报目录不存在只会报符号找不到很容易误导人。6.2 运行时找不到 dll报错是弹窗由于找不到 glut32.dll无法继续执行代码。原因就是 dll 不在 exe 的搜索路径里。解决办法按优先级检查生成后事件是否配置正确$(OutDir)下有没有 dll。手动把 dll 拷到 exe 旁边。确认 dll 位数和 exe 一致。32 位 exe 加载 64 位 dll 会报不是有效的 Win32 程序。6.3 窗口一闪而过或黑屏程序跑起来但窗口立刻消失通常是glutMainLoop没被调用或者main函数提前返回了。检查代码结构glutMainLoop必须在最后它会阻塞在那里处理事件。黑屏但窗口在可能是display回调没注册或者绘制内容在可视区域外。检查glutDisplayFunc(display)有没有写以及顶点坐标是否在[-1, 1]范围内。6.4 常见问题速查表现象可能原因解决方向LNK2019 符号找不到位数不匹配 / 库未链接查 lib 位数补附加依赖项找不到 glut32.dlldll 不在 exe 目录配生成后事件或手动拷贝不是有效的 Win32 程序dll 与 exe 位数不符统一为 32 或 64 位窗口一闪而过未调用 glutMainLoop检查 main 结构黑屏无内容回调未注册 / 坐标越界查 glutDisplayFunc 和顶点找不到 GL/glut.h包含目录不对确认 include/GL/glut.h 存在6.5 几个独家避坑心得心得一别信一键配置脚本。网上有些脚本号称自动配好 glut 环境实际上就是往系统目录拷文件位数还经常搞错。手工配一次理解每个文件的作用比用脚本靠谱得多。心得二Debug 和 Release 都要测。有些人只在 Debug 下跑通就完事结果 Release 一编译就挂。原因是 Release 的优化可能暴露未定义行为或者生成后事件只配了 Debug。属性页里配置选所有配置能避免这个问题。心得三路径里别用中文和空格。VS 对中文路径的支持时好时坏glut 这种老库更是敏感。项目放在纯英文、无空格的路径下能省掉一堆玄学问题。心得四备份一份配好的空项目。配好一次之后把整个项目文件夹存一份当模板。以后要开新项目直接复制这个模板改代码不用重新配环境。这个习惯帮我省了无数次重复劳动。7. 从 glut 到现代 OpenGL 的平滑过渡建议glut 跑通之后你迟早会碰到它的天花板不支持多窗口、事件处理简陋、没法做现代 OpenGL 的核心模式Core Profile开发。这时候就该考虑迁移了。迁移路径我推荐freeglut → GLFW。freeglut 是 glut 的开源替代品API 几乎完全兼容把glut.h换成freeglut.h库名换一下大部分代码不用改就能跑。它修复了原版 glut 的很多 bug还支持更多功能。等你熟悉了 freeglut再上 GLFW 就顺理成章了。GLFW 的窗口创建、事件回调设计和 glut 思路类似但更灵活。配合 glad 加载 OpenGL 函数指针就能玩现代 OpenGL 了。这个过渡不用急先把 glut 上的图形学基础打牢工具链的升级是水到渠成的事。我个人在实际操作中的体会是glut 这套环境虽然老但它的简单粗暴恰恰适合入门。你不需要理解窗口系统、上下文管理、函数加载这些复杂概念就能把注意力集中在图形学本身。等你真正需要那些高级特性时再迁移也不迟。工具是为人服务的别被必须用最新技术的焦虑绑架。最后再分享一个小技巧如果你在配环境时反复失败不妨把项目属性页里每一个改过的地方截图存下来和一份能跑通的配置对比。差异往往就藏在某个不起眼的路径或库名里。这个笨办法比漫无目的地搜索有效得多。
阅读完成 · 觉得有帮助?