前言#
本文主要记录如何使用 CMake + VSCode 在 Windows 环境下搭建图形学项目的开发环境,涵盖 GLFW、GLAD、GLM 等常用库的配置与集成。
文中内容源于我的实际踩坑经历,力求简洁实用,也欢迎读者批评指正。
你可能会用到的 powershell 命令#
- 清空文件夹:
Remove-Item -Recurse -Force 文件夹名 - 展现某个文件夹的下一级所有文件与文件夹:
Get-ChildItem 文件夹名 - 列出文件夹中所有文件与文件夹:
ls -Recurse - 查看某文件中某一行的内容:
Get-Content 文件名 | Select-Object -Index 第几行(注意这里的第几行应该比实际行少1,因为行索引从0开始,比如我要查看12行,我命令里写11)
你会用到的 VSCode 扩展#
- CMake Tools
- glsl_analyzer
- Shader languages support for VS Code
第一步、在本地创建新项目#
1. 在本地创建一个项目#
-
项目结构推荐:
1项目名/2|———— CMakeLists.txt3|———— third_party/4| |──── glad/5| | |──── src/6| | └———— include/7| |———— glfw/8| |———— glm/9| |———— stb/10|———— src/11| └─── main.cpp12└─── .gitignore -
在 OpenGL 项目中一般都会用到下面这五个常用库:
- GLFW:创建操作系统窗口,并绑定 OpenGL 渲染上下文;处理键盘、鼠标等输入事件。
- GLAD:这是 OpenGL 的函数加载器,在程序运行时,动态获取当前显卡驱动的 OpenGL 函数地址 (必须项)
- GLM:提供图形学常用的数学运算,比如向量、矩阵、叉积等等
- stb_image.h:放在 stb 文件夹内,负责图片读取,将图片解码为原始像素数组存储在 CPU 中,用于环境贴图和纹理贴图
- stb_image_write.h:图片输出,将渲染结果保存为静态图片
2. 拉取 GLAD#
- 打开 https://gen.glad.sh
- 在页面中,Generator 默认 C/C++,APIs 里选择 gl,下拉列表里选择 Version 4.6(现在的最新版本)。将 gl 同行右侧的 Compatibility 更改为 Core(我现在的布局大致是这样,之后可能会稍加变动),其他可以先不用管,下拉到最后在右下角点击 GENETATE,然后在弹出的界面选择下载 glad.zip,最后解压。
- 解压过后你会得到一个 glad 文件,里面应该有 inlude 与 src 两个文件夹,将他们整个拷贝到项目的 third_party/glad/ 下(如上图结构)
3. 拉取 GLFW#
- 打开 https://github.com/glfw/glfw
- 克隆整个仓库到本地,你应该会得到一个叫 glfw-master.zip 的文件,解压它。
- 将 glfw-master 文件里的内容全部拷贝到 third_party/glfw/ 下(如上图结构)
4. 拉取 GLM#
- 打开 https://github.com/g-truc/glm
- 克隆整个仓库到本地,你应该会得到一个叫 glm-master.zip 的文件,解压它。
- 将 glm-master 文件里的内容全部拷贝到 third_party/glm/ 下(如上图结构)
5. 获取 stb_image.h#
- 打开 https://github.com/nothings/stb/blob/master/stb_image.h
- 将整个 stb_image.h 拷贝到 third_party/stb/ 下
6. 获取 stb_image_write.h#
- 打开 https://raw.githubusercontent.com/nothings/stb/master/stb_image_write.h
- 将整个 stb_image_write.h 拷贝到 third_party/stb/ 下
网址如果打不开建议刷新一下,并用梯子解决
7. 在 .gitignore 文件内写上:#
1build/2.vscode/第二步、写 CMakeLists.txt 文件#
将下面的内容复制进 CMakeLists.txt,注意把其中“你的项目名”改成你具体的项目名
1cmake_minimum_required(VERSION 3.15)2project(你的项目名)3
4# 强制 UTF-85if(MSVC)6 add_compile_options(/utf-8)7endif()8
9set(CMAKE_CXX_STANDARD 17)10set(CMAKE_CXX_STANDARD_REQUIRED ON)11
12# ---------- GLFW ----------13set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)14set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)15set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)16set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)17add_subdirectory(third_party/glfw)18
19# ---------- GLAD ----------20add_library(glad STATIC third_party/glad/src/glad.c)21target_include_directories(glad PUBLIC third_party/glad/include)22
23# ---------- GLM ----------24set(GLM_BUILD_LIBRARY OFF CACHE BOOL "" FORCE)25set(GLM_BUILD_TESTS OFF CACHE BOOL "" FORCE)26add_subdirectory(third_party/glm)27
28# ---------- stb ----------29add_library(stb INTERFACE)30target_include_directories(stb INTERFACE ${CMAKE_SOURCE_DIR}/third_party/stb)31
32# ---------- 主程序 ----------33add_executable(你的项目名 src/main.cpp)34target_link_libraries(你的项目名 PRIVATE glfw glad glm::glm stb)35
36# windows 特有的37if(WIN32)38 target_link_libraries(你的项目名 PRIVATE opengl32)39endif()第三步、src/main.cpp (验证)#
将一下内容复制进 main.cpp,稍后进行运行检查是否报错。
点击展开 main.cpp 代码用于检验
1#include <glad/glad.h>2#include <GLFW/glfw3.h>3#include <iostream>4
5int main() {6 if (!glfwInit()) {7 std::cerr << "GLFW init failed\n";8 return -1;9 }10
11 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);12 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);13 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);14
15 GLFWwindow* window = glfwCreateWindow(800, 600, "Compute Shader Raytracer", nullptr, nullptr);16 if (!window) {17 std::cerr << "Window creation failed\n";18 glfwTerminate();19 return -1;20 }21 glfwMakeContextCurrent(window);22
23 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {24 std::cerr << "GLAD init failed\n";25 return -1;26 }27
28 // 确认显卡支持compute shader所需的版本29 std::cout << "OpenGL version: " << glGetString(GL_VERSION) << "\n";30 std::cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";31
32 int workGroupCount[3];33 for (int i = 0; i < 3; i++)34 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, i, &workGroupCount[i]);35 std::cout << "Max compute work groups: "36 << workGroupCount[0] << ", " << workGroupCount[1] << ", " << workGroupCount[2] << "\n";37
38 while (!glfwWindowShouldClose(window)) {39 glClearColor(0.1f, 0.1f, 0.15f, 1.0f);40 glClear(GL_COLOR_BUFFER_BIT);41 glfwSwapBuffers(window);42 glfwPollEvents();43 }44
45 glfwTerminate();46 return 0;47}这里特别强调一下 main.cpp 顶部如何包含库:
1// 1. OpenGL 加载器,必须最先2#include <glad/glad.h>3
4// 2. 窗口/输入库5#include <GLFW/glfw3.h>6
7// 3. 数学库8#include <glm/glm.hpp>9#include <glm/gtc/matrix_transform.hpp>10#include <glm/gtc/type_ptr.hpp>11
12// 4. 图像加载,仅在这一个文件里定义实现宏13#define STB_IMAGE_IMPLEMENTATION14#include <stb_image.h>15
16// 5. 标准库17#include <iostream>18#include <vector>每写好一个文件记得 CTRL+C 保存
配置并编译#
在你 VSCode 的终端中依次输入下面的命令 (确保下面命令都是在根目录中进行,我这里用的是 powershell!):
首先输入:#
1cmake -B build第一步成功标志是:你应该会在最后看到终端给你如下这般信息:
1···2-- Configuring done (11.1s)3-- Generating done (0.1s)4-- Build files have been written to: D:/CG/raytracer_gpu/build <- 注意这里:build 文件已在根目录生成(这是我的一个项目示例目录)TIP如果你已经输入并执行了上述命令,但是发现自己忘保存文件等等情况(总之就是你想重来),你可以按 CTRL + C 终止。然后输入
Remove-Item -Recurse -Force build清空 build 文件夹 (切记!)。
接下来输入:#
1cmake --build build第二步成功标志是:你应该会在最后看到终端给你如下这般信息:
1raytracer_gpu.vcxproj -> D:\CG\raytracer_gpu\build\Debug\raytracer_gpu.exe下面试着跑一下你刚生成的 exe:
1.\build\Debug\你的项目名.exe你应该会看到一个深灰色小窗口弹出来,同时终端打印类似这样的内容:
1OpenGL version: 4.3.0 NVIDIA 592.002GLSL version: 4.30 NVIDIA via Cg compiler3Max compute work groups: 2147483647, 65535, 65535这里打印的是 OpenGL 和 GLSL 版本,以及你 GPU 支持的最大计算工作组数量(了解一下你的 GPU 上限)
如果一切顺利,恭喜你完成了最难的环境配置部分!
以后项目该如何维护?#
需要修改 CMakeLists.txt 的情况#
在 src/ 里新增 .cpp 源文件(例如 Camera.cpp、Scene.cpp)
这样改,增添 cpp 文件即可:
1# ---------- 主程序 ----------2add_executable(你的项目名3 src/main.cpp4 src/Camera.cpp5 src/Scene.cpp6)不需要修改 CMakeLists.txt 的情况#
修改 main.cpp 里的代码,在 shaders/ 里增加着色器文件(如 .comp、.vert、.glsl)
每次修改完后续编译#
每次修改完 C++ 代码,直接输入如下指令编译并运行即可
1cmake --build build2.\build\Debug\你的项目名.exe如果只是单纯修改了shader,那么直接运行 .\build\Debug\你的项目名.exe 即可,因为 shader 文件不参与 C++ 编译、
push 到 github#
既然有了一个专属于自己的 OpenGL 项目,怎么说都得 push 到你的 github 上吧。
如果你下面这部分很熟,那么本篇文章的内容就到此为止了。
1. 在你的 github 里创建一个新仓库。#
TIP建立新仓库时最好不要勾选一同创建 README.md,这会让后面的推送过程变得复杂,会多出从远程仓库把 README 拉下来和本地仓库合并的这一步。所以我一般会选择在本地创建 README.md
2. 在本地初始化 git#
在你的根目录终端内依次输入以下指令:
1git init2git add .3git commit -m "Initial commit"至此,你的本地仓库已经建立,并完成了第一次提交。不出意外的话,你的根目录下会多出一个 .git 文件夹。
3. 关联远程仓库#
复制你刚才在 GitHub 上创建好的仓库地址(形如 https://github.com/用户名/仓库名.git),然后执行:
1git remote add origin https://github.com/用户名/仓库名.git再最后一步前,先检查你本地分支的类型,因为你的 github 上新建仓库默认分支是 main,输入以下指令
1git branch如果输出:* master,那么将本地分支重命名:
1git branch -m master main直到看见输出:* main
最后输入:
1git push -u origin main以后提交只用输入 git push 即可
如果一切顺利,恭喜你,项目已经成功托管到 GitHub 上了!
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
